container_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. package docker
  2. import (
  3. "bufio"
  4. "fmt"
  5. "github.com/dotcloud/docker/fs"
  6. "io"
  7. "io/ioutil"
  8. "math/rand"
  9. "os"
  10. "sort"
  11. "strings"
  12. "testing"
  13. "time"
  14. )
  15. func TestCommitRun(t *testing.T) {
  16. docker, err := newTestDocker()
  17. if err != nil {
  18. t.Fatal(err)
  19. }
  20. defer nuke(docker)
  21. container1, err := docker.Create(
  22. "precommit_test",
  23. "/bin/sh",
  24. []string{"-c", "echo hello > /world"},
  25. GetTestImage(docker),
  26. &Config{
  27. Memory: 33554432,
  28. },
  29. )
  30. if err != nil {
  31. t.Fatal(err)
  32. }
  33. defer docker.Destroy(container1)
  34. if container1.State.Running {
  35. t.Errorf("Container shouldn't be running")
  36. }
  37. if err := container1.Run(); err != nil {
  38. t.Fatal(err)
  39. }
  40. if container1.State.Running {
  41. t.Errorf("Container shouldn't be running")
  42. }
  43. // FIXME: freeze the container before copying it to avoid data corruption?
  44. rwTar, err := fs.Tar(container1.Mountpoint.Rw, fs.Uncompressed)
  45. if err != nil {
  46. t.Error(err)
  47. }
  48. // Create a new image from the container's base layers + a new layer from container changes
  49. parentImg, err := docker.Store.Get(container1.Image)
  50. if err != nil {
  51. t.Error(err)
  52. }
  53. img, err := docker.Store.Create(rwTar, parentImg, "test_commitrun", "unit test commited image")
  54. if err != nil {
  55. t.Error(err)
  56. }
  57. // FIXME: Make a TestCommit that stops here and check docker.root/layers/img.id/world
  58. container2, err := docker.Create(
  59. "postcommit_test",
  60. "cat",
  61. []string{"/world"},
  62. img,
  63. &Config{
  64. Memory: 33554432,
  65. },
  66. )
  67. if err != nil {
  68. t.Fatal(err)
  69. }
  70. defer docker.Destroy(container2)
  71. stdout, err := container2.StdoutPipe()
  72. stderr, err := container2.StderrPipe()
  73. if err := container2.Start(); err != nil {
  74. t.Fatal(err)
  75. }
  76. container2.Wait()
  77. output, err := ioutil.ReadAll(stdout)
  78. output2, err := ioutil.ReadAll(stderr)
  79. stdout.Close()
  80. stderr.Close()
  81. if string(output) != "hello\n" {
  82. t.Fatalf("\nout: %s\nerr: %s\n", string(output), string(output2))
  83. }
  84. }
  85. func TestRun(t *testing.T) {
  86. docker, err := newTestDocker()
  87. if err != nil {
  88. t.Fatal(err)
  89. }
  90. defer nuke(docker)
  91. container, err := docker.Create(
  92. "run_test",
  93. "ls",
  94. []string{"-al"},
  95. GetTestImage(docker),
  96. &Config{
  97. Memory: 33554432,
  98. },
  99. )
  100. if err != nil {
  101. t.Fatal(err)
  102. }
  103. defer docker.Destroy(container)
  104. if container.State.Running {
  105. t.Errorf("Container shouldn't be running")
  106. }
  107. if err := container.Run(); err != nil {
  108. t.Fatal(err)
  109. }
  110. if container.State.Running {
  111. t.Errorf("Container shouldn't be running")
  112. }
  113. }
  114. func TestOutput(t *testing.T) {
  115. docker, err := newTestDocker()
  116. if err != nil {
  117. t.Fatal(err)
  118. }
  119. defer nuke(docker)
  120. container, err := docker.Create(
  121. "output_test",
  122. "echo",
  123. []string{"-n", "foobar"},
  124. GetTestImage(docker),
  125. &Config{},
  126. )
  127. if err != nil {
  128. t.Fatal(err)
  129. }
  130. defer docker.Destroy(container)
  131. output, err := container.Output()
  132. if err != nil {
  133. t.Fatal(err)
  134. }
  135. if string(output) != "foobar" {
  136. t.Error(string(output))
  137. }
  138. }
  139. func TestKill(t *testing.T) {
  140. docker, err := newTestDocker()
  141. if err != nil {
  142. t.Fatal(err)
  143. }
  144. defer nuke(docker)
  145. container, err := docker.Create(
  146. "stop_test",
  147. "cat",
  148. []string{"/dev/zero"},
  149. GetTestImage(docker),
  150. &Config{},
  151. )
  152. if err != nil {
  153. t.Fatal(err)
  154. }
  155. defer docker.Destroy(container)
  156. if container.State.Running {
  157. t.Errorf("Container shouldn't be running")
  158. }
  159. if err := container.Start(); err != nil {
  160. t.Fatal(err)
  161. }
  162. if !container.State.Running {
  163. t.Errorf("Container should be running")
  164. }
  165. if err := container.Kill(); err != nil {
  166. t.Fatal(err)
  167. }
  168. if container.State.Running {
  169. t.Errorf("Container shouldn't be running")
  170. }
  171. container.Wait()
  172. if container.State.Running {
  173. t.Errorf("Container shouldn't be running")
  174. }
  175. // Try stopping twice
  176. if err := container.Kill(); err != nil {
  177. t.Fatal(err)
  178. }
  179. }
  180. func TestExitCode(t *testing.T) {
  181. docker, err := newTestDocker()
  182. if err != nil {
  183. t.Fatal(err)
  184. }
  185. defer nuke(docker)
  186. trueContainer, err := docker.Create(
  187. "exit_test_1",
  188. "/bin/true",
  189. []string{""},
  190. GetTestImage(docker),
  191. &Config{},
  192. )
  193. if err != nil {
  194. t.Fatal(err)
  195. }
  196. defer docker.Destroy(trueContainer)
  197. if err := trueContainer.Run(); err != nil {
  198. t.Fatal(err)
  199. }
  200. falseContainer, err := docker.Create(
  201. "exit_test_2",
  202. "/bin/false",
  203. []string{""},
  204. GetTestImage(docker),
  205. &Config{},
  206. )
  207. if err != nil {
  208. t.Fatal(err)
  209. }
  210. defer docker.Destroy(falseContainer)
  211. if err := falseContainer.Run(); err != nil {
  212. t.Fatal(err)
  213. }
  214. if trueContainer.State.ExitCode != 0 {
  215. t.Errorf("Unexpected exit code %v", trueContainer.State.ExitCode)
  216. }
  217. if falseContainer.State.ExitCode != 1 {
  218. t.Errorf("Unexpected exit code %v", falseContainer.State.ExitCode)
  219. }
  220. }
  221. func TestRestart(t *testing.T) {
  222. docker, err := newTestDocker()
  223. if err != nil {
  224. t.Fatal(err)
  225. }
  226. defer nuke(docker)
  227. container, err := docker.Create(
  228. "restart_test",
  229. "echo",
  230. []string{"-n", "foobar"},
  231. GetTestImage(docker),
  232. &Config{},
  233. )
  234. if err != nil {
  235. t.Fatal(err)
  236. }
  237. defer docker.Destroy(container)
  238. output, err := container.Output()
  239. if err != nil {
  240. t.Fatal(err)
  241. }
  242. if string(output) != "foobar" {
  243. t.Error(string(output))
  244. }
  245. // Run the container again and check the output
  246. output, err = container.Output()
  247. if err != nil {
  248. t.Fatal(err)
  249. }
  250. if string(output) != "foobar" {
  251. t.Error(string(output))
  252. }
  253. }
  254. func TestRestartStdin(t *testing.T) {
  255. docker, err := newTestDocker()
  256. if err != nil {
  257. t.Fatal(err)
  258. }
  259. defer nuke(docker)
  260. container, err := docker.Create(
  261. "restart_stdin_test",
  262. "cat",
  263. []string{},
  264. GetTestImage(docker),
  265. &Config{
  266. OpenStdin: true,
  267. },
  268. )
  269. if err != nil {
  270. t.Fatal(err)
  271. }
  272. defer docker.Destroy(container)
  273. stdin, err := container.StdinPipe()
  274. stdout, err := container.StdoutPipe()
  275. if err := container.Start(); err != nil {
  276. t.Fatal(err)
  277. }
  278. io.WriteString(stdin, "hello world")
  279. stdin.Close()
  280. container.Wait()
  281. output, err := ioutil.ReadAll(stdout)
  282. stdout.Close()
  283. if string(output) != "hello world" {
  284. t.Fatal(string(output))
  285. }
  286. // Restart and try again
  287. stdin, err = container.StdinPipe()
  288. stdout, err = container.StdoutPipe()
  289. if err := container.Start(); err != nil {
  290. t.Fatal(err)
  291. }
  292. io.WriteString(stdin, "hello world #2")
  293. stdin.Close()
  294. container.Wait()
  295. output, err = ioutil.ReadAll(stdout)
  296. stdout.Close()
  297. if string(output) != "hello world #2" {
  298. t.Fatal(string(output))
  299. }
  300. }
  301. func TestUser(t *testing.T) {
  302. docker, err := newTestDocker()
  303. if err != nil {
  304. t.Fatal(err)
  305. }
  306. defer nuke(docker)
  307. // Default user must be root
  308. container, err := docker.Create(
  309. "user_default",
  310. "id",
  311. []string{},
  312. GetTestImage(docker),
  313. &Config{},
  314. )
  315. if err != nil {
  316. t.Fatal(err)
  317. }
  318. defer docker.Destroy(container)
  319. output, err := container.Output()
  320. if err != nil {
  321. t.Fatal(err)
  322. }
  323. if !strings.Contains(string(output), "uid=0(root) gid=0(root)") {
  324. t.Error(string(output))
  325. }
  326. // Set a username
  327. container, err = docker.Create(
  328. "user_root",
  329. "id",
  330. []string{},
  331. GetTestImage(docker),
  332. &Config{
  333. User: "root",
  334. },
  335. )
  336. if err != nil {
  337. t.Fatal(err)
  338. }
  339. defer docker.Destroy(container)
  340. output, err = container.Output()
  341. if err != nil || container.State.ExitCode != 0 {
  342. t.Fatal(err)
  343. }
  344. if !strings.Contains(string(output), "uid=0(root) gid=0(root)") {
  345. t.Error(string(output))
  346. }
  347. // Set a UID
  348. container, err = docker.Create(
  349. "user_uid0",
  350. "id",
  351. []string{},
  352. GetTestImage(docker),
  353. &Config{
  354. User: "0",
  355. },
  356. )
  357. if err != nil || container.State.ExitCode != 0 {
  358. t.Fatal(err)
  359. }
  360. defer docker.Destroy(container)
  361. output, err = container.Output()
  362. if err != nil || container.State.ExitCode != 0 {
  363. t.Fatal(err)
  364. }
  365. if !strings.Contains(string(output), "uid=0(root) gid=0(root)") {
  366. t.Error(string(output))
  367. }
  368. // Set a different user by uid
  369. container, err = docker.Create(
  370. "user_uid1",
  371. "id",
  372. []string{},
  373. GetTestImage(docker),
  374. &Config{
  375. User: "1",
  376. },
  377. )
  378. if err != nil {
  379. t.Fatal(err)
  380. }
  381. defer docker.Destroy(container)
  382. output, err = container.Output()
  383. if err != nil {
  384. t.Fatal(err)
  385. } else if container.State.ExitCode != 0 {
  386. t.Fatalf("Container exit code is invalid: %d\nOutput:\n%s\n", container.State.ExitCode, output)
  387. }
  388. if !strings.Contains(string(output), "uid=1(daemon) gid=1(daemon)") {
  389. t.Error(string(output))
  390. }
  391. // Set a different user by username
  392. container, err = docker.Create(
  393. "user_daemon",
  394. "id",
  395. []string{},
  396. GetTestImage(docker),
  397. &Config{
  398. User: "daemon",
  399. },
  400. )
  401. if err != nil {
  402. t.Fatal(err)
  403. }
  404. defer docker.Destroy(container)
  405. output, err = container.Output()
  406. if err != nil || container.State.ExitCode != 0 {
  407. t.Fatal(err)
  408. }
  409. if !strings.Contains(string(output), "uid=1(daemon) gid=1(daemon)") {
  410. t.Error(string(output))
  411. }
  412. }
  413. func TestMultipleContainers(t *testing.T) {
  414. docker, err := newTestDocker()
  415. if err != nil {
  416. t.Fatal(err)
  417. }
  418. defer nuke(docker)
  419. container1, err := docker.Create(
  420. "container1",
  421. "cat",
  422. []string{"/dev/zero"},
  423. GetTestImage(docker),
  424. &Config{},
  425. )
  426. if err != nil {
  427. t.Fatal(err)
  428. }
  429. defer docker.Destroy(container1)
  430. container2, err := docker.Create(
  431. "container2",
  432. "cat",
  433. []string{"/dev/zero"},
  434. GetTestImage(docker),
  435. &Config{},
  436. )
  437. if err != nil {
  438. t.Fatal(err)
  439. }
  440. defer docker.Destroy(container2)
  441. // Start both containers
  442. if err := container1.Start(); err != nil {
  443. t.Fatal(err)
  444. }
  445. if err := container2.Start(); err != nil {
  446. t.Fatal(err)
  447. }
  448. // If we are here, both containers should be running
  449. if !container1.State.Running {
  450. t.Fatal("Container not running")
  451. }
  452. if !container2.State.Running {
  453. t.Fatal("Container not running")
  454. }
  455. // Kill them
  456. if err := container1.Kill(); err != nil {
  457. t.Fatal(err)
  458. }
  459. if err := container2.Kill(); err != nil {
  460. t.Fatal(err)
  461. }
  462. }
  463. func TestStdin(t *testing.T) {
  464. docker, err := newTestDocker()
  465. if err != nil {
  466. t.Fatal(err)
  467. }
  468. defer nuke(docker)
  469. container, err := docker.Create(
  470. "stdin_test",
  471. "cat",
  472. []string{},
  473. GetTestImage(docker),
  474. &Config{
  475. OpenStdin: true,
  476. },
  477. )
  478. if err != nil {
  479. t.Fatal(err)
  480. }
  481. defer docker.Destroy(container)
  482. stdin, err := container.StdinPipe()
  483. stdout, err := container.StdoutPipe()
  484. defer stdin.Close()
  485. defer stdout.Close()
  486. if err := container.Start(); err != nil {
  487. t.Fatal(err)
  488. }
  489. io.WriteString(stdin, "hello world")
  490. stdin.Close()
  491. container.Wait()
  492. output, err := ioutil.ReadAll(stdout)
  493. if string(output) != "hello world" {
  494. t.Fatal(string(output))
  495. }
  496. }
  497. func TestTty(t *testing.T) {
  498. docker, err := newTestDocker()
  499. if err != nil {
  500. t.Fatal(err)
  501. }
  502. defer nuke(docker)
  503. container, err := docker.Create(
  504. "tty_test",
  505. "cat",
  506. []string{},
  507. GetTestImage(docker),
  508. &Config{
  509. OpenStdin: true,
  510. },
  511. )
  512. if err != nil {
  513. t.Fatal(err)
  514. }
  515. defer docker.Destroy(container)
  516. stdin, err := container.StdinPipe()
  517. stdout, err := container.StdoutPipe()
  518. defer stdin.Close()
  519. defer stdout.Close()
  520. if err := container.Start(); err != nil {
  521. t.Fatal(err)
  522. }
  523. io.WriteString(stdin, "hello world")
  524. stdin.Close()
  525. container.Wait()
  526. output, err := ioutil.ReadAll(stdout)
  527. if string(output) != "hello world" {
  528. t.Fatal(string(output))
  529. }
  530. }
  531. func TestEnv(t *testing.T) {
  532. docker, err := newTestDocker()
  533. if err != nil {
  534. t.Fatal(err)
  535. }
  536. defer nuke(docker)
  537. container, err := docker.Create(
  538. "env_test",
  539. "/usr/bin/env",
  540. []string{},
  541. GetTestImage(docker),
  542. &Config{},
  543. )
  544. if err != nil {
  545. t.Fatal(err)
  546. }
  547. defer docker.Destroy(container)
  548. stdout, err := container.StdoutPipe()
  549. if err != nil {
  550. t.Fatal(err)
  551. }
  552. defer stdout.Close()
  553. if err := container.Start(); err != nil {
  554. t.Fatal(err)
  555. }
  556. container.Wait()
  557. output, err := ioutil.ReadAll(stdout)
  558. if err != nil {
  559. t.Fatal(err)
  560. }
  561. actualEnv := strings.Split(string(output), "\n")
  562. if actualEnv[len(actualEnv)-1] == "" {
  563. actualEnv = actualEnv[:len(actualEnv)-1]
  564. }
  565. sort.Strings(actualEnv)
  566. goodEnv := []string{
  567. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  568. "HOME=/",
  569. }
  570. sort.Strings(goodEnv)
  571. if len(goodEnv) != len(actualEnv) {
  572. t.Fatalf("Wrong environment: should be %d variables, not: '%s'\n", len(goodEnv), strings.Join(actualEnv, ", "))
  573. }
  574. for i := range goodEnv {
  575. if actualEnv[i] != goodEnv[i] {
  576. t.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i])
  577. }
  578. }
  579. }
  580. func grepFile(t *testing.T, path string, pattern string) {
  581. f, err := os.Open(path)
  582. if err != nil {
  583. t.Fatal(err)
  584. }
  585. defer f.Close()
  586. r := bufio.NewReader(f)
  587. var (
  588. line string
  589. )
  590. err = nil
  591. for err == nil {
  592. line, err = r.ReadString('\n')
  593. if strings.Contains(line, pattern) == true {
  594. return
  595. }
  596. }
  597. t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path)
  598. }
  599. func TestLXCConfig(t *testing.T) {
  600. docker, err := newTestDocker()
  601. if err != nil {
  602. t.Fatal(err)
  603. }
  604. defer nuke(docker)
  605. // Memory is allocated randomly for testing
  606. rand.Seed(time.Now().UTC().UnixNano())
  607. memMin := 33554432
  608. memMax := 536870912
  609. mem := memMin + rand.Intn(memMax-memMin)
  610. container, err := docker.Create(
  611. "config_test",
  612. "/bin/true",
  613. []string{},
  614. GetTestImage(docker),
  615. &Config{
  616. Hostname: "foobar",
  617. Memory: int64(mem),
  618. },
  619. )
  620. if err != nil {
  621. t.Fatal(err)
  622. }
  623. defer docker.Destroy(container)
  624. container.generateLXCConfig()
  625. grepFile(t, container.lxcConfigPath, "lxc.utsname = foobar")
  626. grepFile(t, container.lxcConfigPath,
  627. fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
  628. grepFile(t, container.lxcConfigPath,
  629. fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2))
  630. }
  631. func BenchmarkRunSequencial(b *testing.B) {
  632. docker, err := newTestDocker()
  633. if err != nil {
  634. b.Fatal(err)
  635. }
  636. defer nuke(docker)
  637. for i := 0; i < b.N; i++ {
  638. container, err := docker.Create(
  639. fmt.Sprintf("bench_%v", i),
  640. "echo",
  641. []string{"-n", "foo"},
  642. GetTestImage(docker),
  643. &Config{},
  644. )
  645. if err != nil {
  646. b.Fatal(err)
  647. }
  648. defer docker.Destroy(container)
  649. output, err := container.Output()
  650. if err != nil {
  651. b.Fatal(err)
  652. }
  653. if string(output) != "foo" {
  654. b.Fatalf("Unexecpted output: %v", string(output))
  655. }
  656. if err := docker.Destroy(container); err != nil {
  657. b.Fatal(err)
  658. }
  659. }
  660. }
  661. func BenchmarkRunParallel(b *testing.B) {
  662. docker, err := newTestDocker()
  663. if err != nil {
  664. b.Fatal(err)
  665. }
  666. defer nuke(docker)
  667. var tasks []chan error
  668. for i := 0; i < b.N; i++ {
  669. complete := make(chan error)
  670. tasks = append(tasks, complete)
  671. go func(i int, complete chan error) {
  672. container, err := docker.Create(
  673. fmt.Sprintf("bench_%v", i),
  674. "echo",
  675. []string{"-n", "foo"},
  676. GetTestImage(docker),
  677. &Config{},
  678. )
  679. if err != nil {
  680. complete <- err
  681. return
  682. }
  683. defer docker.Destroy(container)
  684. if err := container.Start(); err != nil {
  685. complete <- err
  686. return
  687. }
  688. if err := container.WaitTimeout(15 * time.Second); err != nil {
  689. complete <- err
  690. return
  691. }
  692. // if string(output) != "foo" {
  693. // complete <- fmt.Errorf("Unexecpted output: %v", string(output))
  694. // }
  695. if err := docker.Destroy(container); err != nil {
  696. complete <- err
  697. return
  698. }
  699. complete <- nil
  700. }(i, complete)
  701. }
  702. var errors []error
  703. for _, task := range tasks {
  704. err := <-task
  705. if err != nil {
  706. errors = append(errors, err)
  707. }
  708. }
  709. if len(errors) > 0 {
  710. b.Fatal(errors)
  711. }
  712. }