container_test.go 14 KB

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