container_test.go 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237
  1. package docker
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "math/rand"
  8. "os"
  9. "path"
  10. "regexp"
  11. "sort"
  12. "strings"
  13. "testing"
  14. "time"
  15. )
  16. func TestIDFormat(t *testing.T) {
  17. runtime := mkRuntime(t)
  18. defer nuke(runtime)
  19. container1, err := NewBuilder(runtime).Create(
  20. &Config{
  21. Image: GetTestImage(runtime).ID,
  22. Cmd: []string{"/bin/sh", "-c", "echo hello world"},
  23. },
  24. )
  25. if err != nil {
  26. t.Fatal(err)
  27. }
  28. match, err := regexp.Match("^[0-9a-f]{64}$", []byte(container1.ID))
  29. if err != nil {
  30. t.Fatal(err)
  31. }
  32. if !match {
  33. t.Fatalf("Invalid container ID: %s", container1.ID)
  34. }
  35. }
  36. func TestMultipleAttachRestart(t *testing.T) {
  37. runtime := mkRuntime(t)
  38. defer nuke(runtime)
  39. container, err := NewBuilder(runtime).Create(
  40. &Config{
  41. Image: GetTestImage(runtime).ID,
  42. Cmd: []string{"/bin/sh", "-c",
  43. "i=1; while [ $i -le 5 ]; do i=`expr $i + 1`; echo hello; done"},
  44. },
  45. )
  46. if err != nil {
  47. t.Fatal(err)
  48. }
  49. defer runtime.Destroy(container)
  50. // Simulate 3 client attaching to the container and stop/restart
  51. stdout1, err := container.StdoutPipe()
  52. if err != nil {
  53. t.Fatal(err)
  54. }
  55. stdout2, err := container.StdoutPipe()
  56. if err != nil {
  57. t.Fatal(err)
  58. }
  59. stdout3, err := container.StdoutPipe()
  60. if err != nil {
  61. t.Fatal(err)
  62. }
  63. hostConfig := &HostConfig{}
  64. if err := container.Start(hostConfig); err != nil {
  65. t.Fatal(err)
  66. }
  67. l1, err := bufio.NewReader(stdout1).ReadString('\n')
  68. if err != nil {
  69. t.Fatal(err)
  70. }
  71. if strings.Trim(l1, " \r\n") != "hello" {
  72. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l1)
  73. }
  74. l2, err := bufio.NewReader(stdout2).ReadString('\n')
  75. if err != nil {
  76. t.Fatal(err)
  77. }
  78. if strings.Trim(l2, " \r\n") != "hello" {
  79. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l2)
  80. }
  81. l3, err := bufio.NewReader(stdout3).ReadString('\n')
  82. if err != nil {
  83. t.Fatal(err)
  84. }
  85. if strings.Trim(l3, " \r\n") != "hello" {
  86. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l3)
  87. }
  88. if err := container.Stop(10); err != nil {
  89. t.Fatal(err)
  90. }
  91. stdout1, err = container.StdoutPipe()
  92. if err != nil {
  93. t.Fatal(err)
  94. }
  95. stdout2, err = container.StdoutPipe()
  96. if err != nil {
  97. t.Fatal(err)
  98. }
  99. stdout3, err = container.StdoutPipe()
  100. if err != nil {
  101. t.Fatal(err)
  102. }
  103. if err := container.Start(hostConfig); err != nil {
  104. t.Fatal(err)
  105. }
  106. setTimeout(t, "Timeout reading from the process", 3*time.Second, func() {
  107. l1, err = bufio.NewReader(stdout1).ReadString('\n')
  108. if err != nil {
  109. t.Fatal(err)
  110. }
  111. if strings.Trim(l1, " \r\n") != "hello" {
  112. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l1)
  113. }
  114. l2, err = bufio.NewReader(stdout2).ReadString('\n')
  115. if err != nil {
  116. t.Fatal(err)
  117. }
  118. if strings.Trim(l2, " \r\n") != "hello" {
  119. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l2)
  120. }
  121. l3, err = bufio.NewReader(stdout3).ReadString('\n')
  122. if err != nil {
  123. t.Fatal(err)
  124. }
  125. if strings.Trim(l3, " \r\n") != "hello" {
  126. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l3)
  127. }
  128. })
  129. container.Wait()
  130. }
  131. func TestDiff(t *testing.T) {
  132. runtime := mkRuntime(t)
  133. defer nuke(runtime)
  134. builder := NewBuilder(runtime)
  135. // Create a container and remove a file
  136. container1, err := builder.Create(
  137. &Config{
  138. Image: GetTestImage(runtime).ID,
  139. Cmd: []string{"/bin/rm", "/etc/passwd"},
  140. },
  141. )
  142. if err != nil {
  143. t.Fatal(err)
  144. }
  145. defer runtime.Destroy(container1)
  146. if err := container1.Run(); err != nil {
  147. t.Fatal(err)
  148. }
  149. // Check the changelog
  150. c, err := container1.Changes()
  151. if err != nil {
  152. t.Fatal(err)
  153. }
  154. success := false
  155. for _, elem := range c {
  156. if elem.Path == "/etc/passwd" && elem.Kind == 2 {
  157. success = true
  158. }
  159. }
  160. if !success {
  161. t.Fatalf("/etc/passwd as been removed but is not present in the diff")
  162. }
  163. // Commit the container
  164. rwTar, err := container1.ExportRw()
  165. if err != nil {
  166. t.Error(err)
  167. }
  168. img, err := runtime.graph.Create(rwTar, container1, "unit test commited image - diff", "", nil)
  169. if err != nil {
  170. t.Error(err)
  171. }
  172. // Create a new container from the commited image
  173. container2, err := builder.Create(
  174. &Config{
  175. Image: img.ID,
  176. Cmd: []string{"cat", "/etc/passwd"},
  177. },
  178. )
  179. if err != nil {
  180. t.Fatal(err)
  181. }
  182. defer runtime.Destroy(container2)
  183. if err := container2.Run(); err != nil {
  184. t.Fatal(err)
  185. }
  186. // Check the changelog
  187. c, err = container2.Changes()
  188. if err != nil {
  189. t.Fatal(err)
  190. }
  191. for _, elem := range c {
  192. if elem.Path == "/etc/passwd" {
  193. t.Fatalf("/etc/passwd should not be present in the diff after commit.")
  194. }
  195. }
  196. // Create a new containere
  197. container3, err := builder.Create(
  198. &Config{
  199. Image: GetTestImage(runtime).ID,
  200. Cmd: []string{"rm", "/bin/httpd"},
  201. },
  202. )
  203. if err != nil {
  204. t.Fatal(err)
  205. }
  206. defer runtime.Destroy(container3)
  207. if err := container3.Run(); err != nil {
  208. t.Fatal(err)
  209. }
  210. // Check the changelog
  211. c, err = container3.Changes()
  212. if err != nil {
  213. t.Fatal(err)
  214. }
  215. success = false
  216. for _, elem := range c {
  217. if elem.Path == "/bin/httpd" && elem.Kind == 2 {
  218. success = true
  219. }
  220. }
  221. if !success {
  222. t.Fatalf("/bin/httpd should be present in the diff after commit.")
  223. }
  224. }
  225. func TestCommitAutoRun(t *testing.T) {
  226. runtime := mkRuntime(t)
  227. defer nuke(runtime)
  228. builder := NewBuilder(runtime)
  229. container1, err := builder.Create(
  230. &Config{
  231. Image: GetTestImage(runtime).ID,
  232. Cmd: []string{"/bin/sh", "-c", "echo hello > /world"},
  233. },
  234. )
  235. if err != nil {
  236. t.Fatal(err)
  237. }
  238. defer runtime.Destroy(container1)
  239. if container1.State.Running {
  240. t.Errorf("Container shouldn't be running")
  241. }
  242. if err := container1.Run(); err != nil {
  243. t.Fatal(err)
  244. }
  245. if container1.State.Running {
  246. t.Errorf("Container shouldn't be running")
  247. }
  248. rwTar, err := container1.ExportRw()
  249. if err != nil {
  250. t.Error(err)
  251. }
  252. img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "", &Config{Cmd: []string{"cat", "/world"}})
  253. if err != nil {
  254. t.Error(err)
  255. }
  256. // FIXME: Make a TestCommit that stops here and check docker.root/layers/img.id/world
  257. container2, err := builder.Create(
  258. &Config{
  259. Image: img.ID,
  260. },
  261. )
  262. if err != nil {
  263. t.Fatal(err)
  264. }
  265. defer runtime.Destroy(container2)
  266. stdout, err := container2.StdoutPipe()
  267. if err != nil {
  268. t.Fatal(err)
  269. }
  270. stderr, err := container2.StderrPipe()
  271. if err != nil {
  272. t.Fatal(err)
  273. }
  274. hostConfig := &HostConfig{}
  275. if err := container2.Start(hostConfig); err != nil {
  276. t.Fatal(err)
  277. }
  278. container2.Wait()
  279. output, err := ioutil.ReadAll(stdout)
  280. if err != nil {
  281. t.Fatal(err)
  282. }
  283. output2, err := ioutil.ReadAll(stderr)
  284. if err != nil {
  285. t.Fatal(err)
  286. }
  287. if err := stdout.Close(); err != nil {
  288. t.Fatal(err)
  289. }
  290. if err := stderr.Close(); err != nil {
  291. t.Fatal(err)
  292. }
  293. if string(output) != "hello\n" {
  294. t.Fatalf("Unexpected output. Expected %s, received: %s (err: %s)", "hello\n", output, output2)
  295. }
  296. }
  297. func TestCommitRun(t *testing.T) {
  298. runtime := mkRuntime(t)
  299. defer nuke(runtime)
  300. builder := NewBuilder(runtime)
  301. container1, err := builder.Create(
  302. &Config{
  303. Image: GetTestImage(runtime).ID,
  304. Cmd: []string{"/bin/sh", "-c", "echo hello > /world"},
  305. },
  306. )
  307. if err != nil {
  308. t.Fatal(err)
  309. }
  310. defer runtime.Destroy(container1)
  311. if container1.State.Running {
  312. t.Errorf("Container shouldn't be running")
  313. }
  314. if err := container1.Run(); err != nil {
  315. t.Fatal(err)
  316. }
  317. if container1.State.Running {
  318. t.Errorf("Container shouldn't be running")
  319. }
  320. rwTar, err := container1.ExportRw()
  321. if err != nil {
  322. t.Error(err)
  323. }
  324. img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "", nil)
  325. if err != nil {
  326. t.Error(err)
  327. }
  328. // FIXME: Make a TestCommit that stops here and check docker.root/layers/img.id/world
  329. container2, err := builder.Create(
  330. &Config{
  331. Image: img.ID,
  332. Cmd: []string{"cat", "/world"},
  333. },
  334. )
  335. if err != nil {
  336. t.Fatal(err)
  337. }
  338. defer runtime.Destroy(container2)
  339. stdout, err := container2.StdoutPipe()
  340. if err != nil {
  341. t.Fatal(err)
  342. }
  343. stderr, err := container2.StderrPipe()
  344. if err != nil {
  345. t.Fatal(err)
  346. }
  347. hostConfig := &HostConfig{}
  348. if err := container2.Start(hostConfig); err != nil {
  349. t.Fatal(err)
  350. }
  351. container2.Wait()
  352. output, err := ioutil.ReadAll(stdout)
  353. if err != nil {
  354. t.Fatal(err)
  355. }
  356. output2, err := ioutil.ReadAll(stderr)
  357. if err != nil {
  358. t.Fatal(err)
  359. }
  360. if err := stdout.Close(); err != nil {
  361. t.Fatal(err)
  362. }
  363. if err := stderr.Close(); err != nil {
  364. t.Fatal(err)
  365. }
  366. if string(output) != "hello\n" {
  367. t.Fatalf("Unexpected output. Expected %s, received: %s (err: %s)", "hello\n", output, output2)
  368. }
  369. }
  370. func TestStart(t *testing.T) {
  371. runtime := mkRuntime(t)
  372. defer nuke(runtime)
  373. container, err := NewBuilder(runtime).Create(
  374. &Config{
  375. Image: GetTestImage(runtime).ID,
  376. Memory: 33554432,
  377. CpuShares: 1000,
  378. Cmd: []string{"/bin/cat"},
  379. OpenStdin: true,
  380. },
  381. )
  382. if err != nil {
  383. t.Fatal(err)
  384. }
  385. defer runtime.Destroy(container)
  386. cStdin, err := container.StdinPipe()
  387. if err != nil {
  388. t.Fatal(err)
  389. }
  390. hostConfig := &HostConfig{}
  391. if err := container.Start(hostConfig); err != nil {
  392. t.Fatal(err)
  393. }
  394. // Give some time to the process to start
  395. container.WaitTimeout(500 * time.Millisecond)
  396. if !container.State.Running {
  397. t.Errorf("Container should be running")
  398. }
  399. if err := container.Start(hostConfig); err == nil {
  400. t.Fatalf("A running containter should be able to be started")
  401. }
  402. // Try to avoid the timeoout in destroy. Best effort, don't check error
  403. cStdin.Close()
  404. container.WaitTimeout(2 * time.Second)
  405. }
  406. func TestRun(t *testing.T) {
  407. runtime := mkRuntime(t)
  408. defer nuke(runtime)
  409. container, err := NewBuilder(runtime).Create(
  410. &Config{
  411. Image: GetTestImage(runtime).ID,
  412. Cmd: []string{"ls", "-al"},
  413. },
  414. )
  415. if err != nil {
  416. t.Fatal(err)
  417. }
  418. defer runtime.Destroy(container)
  419. if container.State.Running {
  420. t.Errorf("Container shouldn't be running")
  421. }
  422. if err := container.Run(); err != nil {
  423. t.Fatal(err)
  424. }
  425. if container.State.Running {
  426. t.Errorf("Container shouldn't be running")
  427. }
  428. }
  429. func TestOutput(t *testing.T) {
  430. runtime := mkRuntime(t)
  431. defer nuke(runtime)
  432. container, err := NewBuilder(runtime).Create(
  433. &Config{
  434. Image: GetTestImage(runtime).ID,
  435. Cmd: []string{"echo", "-n", "foobar"},
  436. },
  437. )
  438. if err != nil {
  439. t.Fatal(err)
  440. }
  441. defer runtime.Destroy(container)
  442. output, err := container.Output()
  443. if err != nil {
  444. t.Fatal(err)
  445. }
  446. if string(output) != "foobar" {
  447. t.Error(string(output))
  448. }
  449. }
  450. func TestKillDifferentUser(t *testing.T) {
  451. runtime := mkRuntime(t)
  452. defer nuke(runtime)
  453. container, err := NewBuilder(runtime).Create(&Config{
  454. Image: GetTestImage(runtime).ID,
  455. Cmd: []string{"tail", "-f", "/etc/resolv.conf"},
  456. User: "daemon",
  457. },
  458. )
  459. if err != nil {
  460. t.Fatal(err)
  461. }
  462. defer runtime.Destroy(container)
  463. if container.State.Running {
  464. t.Errorf("Container shouldn't be running")
  465. }
  466. hostConfig := &HostConfig{}
  467. if err := container.Start(hostConfig); err != nil {
  468. t.Fatal(err)
  469. }
  470. setTimeout(t, "Waiting for the container to be started timed out", 2 * time.Second, func() {
  471. for !container.State.Running {
  472. time.Sleep(10 * time.Millisecond)
  473. }
  474. })
  475. if err := container.Kill(); err != nil {
  476. t.Fatal(err)
  477. }
  478. if container.State.Running {
  479. t.Errorf("Container shouldn't be running")
  480. }
  481. container.Wait()
  482. if container.State.Running {
  483. t.Errorf("Container shouldn't be running")
  484. }
  485. // Try stopping twice
  486. if err := container.Kill(); err != nil {
  487. t.Fatal(err)
  488. }
  489. }
  490. // Test that creating a container with a volume doesn't crash. Regression test for #995.
  491. func TestCreateVolume(t *testing.T) {
  492. runtime := mkRuntime(t)
  493. defer nuke(runtime)
  494. config, hc, _, err := ParseRun([]string{"-v", "/var/lib/data", GetTestImage(runtime).ID, "echo", "hello", "world"}, nil)
  495. if err != nil {
  496. t.Fatal(err)
  497. }
  498. c, err := NewBuilder(runtime).Create(config)
  499. if err != nil {
  500. t.Fatal(err)
  501. }
  502. defer runtime.Destroy(c)
  503. if err := c.Start(hc); err != nil {
  504. t.Fatal(err)
  505. }
  506. c.WaitTimeout(500 * time.Millisecond)
  507. c.Wait()
  508. }
  509. func TestKill(t *testing.T) {
  510. runtime := mkRuntime(t)
  511. defer nuke(runtime)
  512. container, err := NewBuilder(runtime).Create(&Config{
  513. Image: GetTestImage(runtime).ID,
  514. Cmd: []string{"sleep", "2"},
  515. },
  516. )
  517. if err != nil {
  518. t.Fatal(err)
  519. }
  520. defer runtime.Destroy(container)
  521. if container.State.Running {
  522. t.Errorf("Container shouldn't be running")
  523. }
  524. hostConfig := &HostConfig{}
  525. if err := container.Start(hostConfig); err != nil {
  526. t.Fatal(err)
  527. }
  528. // Give some time to lxc to spawn the process
  529. container.WaitTimeout(500 * time.Millisecond)
  530. if !container.State.Running {
  531. t.Errorf("Container should be running")
  532. }
  533. if err := container.Kill(); err != nil {
  534. t.Fatal(err)
  535. }
  536. if container.State.Running {
  537. t.Errorf("Container shouldn't be running")
  538. }
  539. container.Wait()
  540. if container.State.Running {
  541. t.Errorf("Container shouldn't be running")
  542. }
  543. // Try stopping twice
  544. if err := container.Kill(); err != nil {
  545. t.Fatal(err)
  546. }
  547. }
  548. func TestExitCode(t *testing.T) {
  549. runtime := mkRuntime(t)
  550. defer nuke(runtime)
  551. builder := NewBuilder(runtime)
  552. trueContainer, err := builder.Create(&Config{
  553. Image: GetTestImage(runtime).ID,
  554. Cmd: []string{"/bin/true", ""},
  555. })
  556. if err != nil {
  557. t.Fatal(err)
  558. }
  559. defer runtime.Destroy(trueContainer)
  560. if err := trueContainer.Run(); err != nil {
  561. t.Fatal(err)
  562. }
  563. if trueContainer.State.ExitCode != 0 {
  564. t.Errorf("Unexpected exit code %d (expected 0)", trueContainer.State.ExitCode)
  565. }
  566. falseContainer, err := builder.Create(&Config{
  567. Image: GetTestImage(runtime).ID,
  568. Cmd: []string{"/bin/false", ""},
  569. })
  570. if err != nil {
  571. t.Fatal(err)
  572. }
  573. defer runtime.Destroy(falseContainer)
  574. if err := falseContainer.Run(); err != nil {
  575. t.Fatal(err)
  576. }
  577. if falseContainer.State.ExitCode != 1 {
  578. t.Errorf("Unexpected exit code %d (expected 1)", falseContainer.State.ExitCode)
  579. }
  580. }
  581. func TestRestart(t *testing.T) {
  582. runtime := mkRuntime(t)
  583. defer nuke(runtime)
  584. container, err := NewBuilder(runtime).Create(&Config{
  585. Image: GetTestImage(runtime).ID,
  586. Cmd: []string{"echo", "-n", "foobar"},
  587. },
  588. )
  589. if err != nil {
  590. t.Fatal(err)
  591. }
  592. defer runtime.Destroy(container)
  593. output, err := container.Output()
  594. if err != nil {
  595. t.Fatal(err)
  596. }
  597. if string(output) != "foobar" {
  598. t.Error(string(output))
  599. }
  600. // Run the container again and check the output
  601. output, err = container.Output()
  602. if err != nil {
  603. t.Fatal(err)
  604. }
  605. if string(output) != "foobar" {
  606. t.Error(string(output))
  607. }
  608. }
  609. func TestRestartStdin(t *testing.T) {
  610. runtime := mkRuntime(t)
  611. defer nuke(runtime)
  612. container, err := NewBuilder(runtime).Create(&Config{
  613. Image: GetTestImage(runtime).ID,
  614. Cmd: []string{"cat"},
  615. OpenStdin: true,
  616. },
  617. )
  618. if err != nil {
  619. t.Fatal(err)
  620. }
  621. defer runtime.Destroy(container)
  622. stdin, err := container.StdinPipe()
  623. if err != nil {
  624. t.Fatal(err)
  625. }
  626. stdout, err := container.StdoutPipe()
  627. if err != nil {
  628. t.Fatal(err)
  629. }
  630. hostConfig := &HostConfig{}
  631. if err := container.Start(hostConfig); err != nil {
  632. t.Fatal(err)
  633. }
  634. if _, err := io.WriteString(stdin, "hello world"); err != nil {
  635. t.Fatal(err)
  636. }
  637. if err := stdin.Close(); err != nil {
  638. t.Fatal(err)
  639. }
  640. container.Wait()
  641. output, err := ioutil.ReadAll(stdout)
  642. if err != nil {
  643. t.Fatal(err)
  644. }
  645. if err := stdout.Close(); err != nil {
  646. t.Fatal(err)
  647. }
  648. if string(output) != "hello world" {
  649. t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world", string(output))
  650. }
  651. // Restart and try again
  652. stdin, err = container.StdinPipe()
  653. if err != nil {
  654. t.Fatal(err)
  655. }
  656. stdout, err = container.StdoutPipe()
  657. if err != nil {
  658. t.Fatal(err)
  659. }
  660. if err := container.Start(hostConfig); err != nil {
  661. t.Fatal(err)
  662. }
  663. if _, err := io.WriteString(stdin, "hello world #2"); err != nil {
  664. t.Fatal(err)
  665. }
  666. if err := stdin.Close(); err != nil {
  667. t.Fatal(err)
  668. }
  669. container.Wait()
  670. output, err = ioutil.ReadAll(stdout)
  671. if err != nil {
  672. t.Fatal(err)
  673. }
  674. if err := stdout.Close(); err != nil {
  675. t.Fatal(err)
  676. }
  677. if string(output) != "hello world #2" {
  678. t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world #2", string(output))
  679. }
  680. }
  681. func TestUser(t *testing.T) {
  682. runtime := mkRuntime(t)
  683. defer nuke(runtime)
  684. builder := NewBuilder(runtime)
  685. // Default user must be root
  686. container, err := builder.Create(&Config{
  687. Image: GetTestImage(runtime).ID,
  688. Cmd: []string{"id"},
  689. },
  690. )
  691. if err != nil {
  692. t.Fatal(err)
  693. }
  694. defer runtime.Destroy(container)
  695. output, err := container.Output()
  696. if err != nil {
  697. t.Fatal(err)
  698. }
  699. if !strings.Contains(string(output), "uid=0(root) gid=0(root)") {
  700. t.Error(string(output))
  701. }
  702. // Set a username
  703. container, err = builder.Create(&Config{
  704. Image: GetTestImage(runtime).ID,
  705. Cmd: []string{"id"},
  706. User: "root",
  707. },
  708. )
  709. if err != nil {
  710. t.Fatal(err)
  711. }
  712. defer runtime.Destroy(container)
  713. output, err = container.Output()
  714. if err != nil || container.State.ExitCode != 0 {
  715. t.Fatal(err)
  716. }
  717. if !strings.Contains(string(output), "uid=0(root) gid=0(root)") {
  718. t.Error(string(output))
  719. }
  720. // Set a UID
  721. container, err = builder.Create(&Config{
  722. Image: GetTestImage(runtime).ID,
  723. Cmd: []string{"id"},
  724. User: "0",
  725. },
  726. )
  727. if err != nil || container.State.ExitCode != 0 {
  728. t.Fatal(err)
  729. }
  730. defer runtime.Destroy(container)
  731. output, err = container.Output()
  732. if err != nil || container.State.ExitCode != 0 {
  733. t.Fatal(err)
  734. }
  735. if !strings.Contains(string(output), "uid=0(root) gid=0(root)") {
  736. t.Error(string(output))
  737. }
  738. // Set a different user by uid
  739. container, err = builder.Create(&Config{
  740. Image: GetTestImage(runtime).ID,
  741. Cmd: []string{"id"},
  742. User: "1",
  743. },
  744. )
  745. if err != nil {
  746. t.Fatal(err)
  747. }
  748. defer runtime.Destroy(container)
  749. output, err = container.Output()
  750. if err != nil {
  751. t.Fatal(err)
  752. } else if container.State.ExitCode != 0 {
  753. t.Fatalf("Container exit code is invalid: %d\nOutput:\n%s\n", container.State.ExitCode, output)
  754. }
  755. if !strings.Contains(string(output), "uid=1(daemon) gid=1(daemon)") {
  756. t.Error(string(output))
  757. }
  758. // Set a different user by username
  759. container, err = builder.Create(&Config{
  760. Image: GetTestImage(runtime).ID,
  761. Cmd: []string{"id"},
  762. User: "daemon",
  763. },
  764. )
  765. if err != nil {
  766. t.Fatal(err)
  767. }
  768. defer runtime.Destroy(container)
  769. output, err = container.Output()
  770. if err != nil || container.State.ExitCode != 0 {
  771. t.Fatal(err)
  772. }
  773. if !strings.Contains(string(output), "uid=1(daemon) gid=1(daemon)") {
  774. t.Error(string(output))
  775. }
  776. }
  777. func TestMultipleContainers(t *testing.T) {
  778. runtime := mkRuntime(t)
  779. defer nuke(runtime)
  780. builder := NewBuilder(runtime)
  781. container1, err := builder.Create(&Config{
  782. Image: GetTestImage(runtime).ID,
  783. Cmd: []string{"sleep", "2"},
  784. },
  785. )
  786. if err != nil {
  787. t.Fatal(err)
  788. }
  789. defer runtime.Destroy(container1)
  790. container2, err := builder.Create(&Config{
  791. Image: GetTestImage(runtime).ID,
  792. Cmd: []string{"sleep", "2"},
  793. },
  794. )
  795. if err != nil {
  796. t.Fatal(err)
  797. }
  798. defer runtime.Destroy(container2)
  799. // Start both containers
  800. hostConfig := &HostConfig{}
  801. if err := container1.Start(hostConfig); err != nil {
  802. t.Fatal(err)
  803. }
  804. if err := container2.Start(hostConfig); err != nil {
  805. t.Fatal(err)
  806. }
  807. // Make sure they are running before trying to kill them
  808. container1.WaitTimeout(250 * time.Millisecond)
  809. container2.WaitTimeout(250 * time.Millisecond)
  810. // If we are here, both containers should be running
  811. if !container1.State.Running {
  812. t.Fatal("Container not running")
  813. }
  814. if !container2.State.Running {
  815. t.Fatal("Container not running")
  816. }
  817. // Kill them
  818. if err := container1.Kill(); err != nil {
  819. t.Fatal(err)
  820. }
  821. if err := container2.Kill(); err != nil {
  822. t.Fatal(err)
  823. }
  824. }
  825. func TestStdin(t *testing.T) {
  826. runtime := mkRuntime(t)
  827. defer nuke(runtime)
  828. container, err := NewBuilder(runtime).Create(&Config{
  829. Image: GetTestImage(runtime).ID,
  830. Cmd: []string{"cat"},
  831. OpenStdin: true,
  832. },
  833. )
  834. if err != nil {
  835. t.Fatal(err)
  836. }
  837. defer runtime.Destroy(container)
  838. stdin, err := container.StdinPipe()
  839. if err != nil {
  840. t.Fatal(err)
  841. }
  842. stdout, err := container.StdoutPipe()
  843. if err != nil {
  844. t.Fatal(err)
  845. }
  846. hostConfig := &HostConfig{}
  847. if err := container.Start(hostConfig); err != nil {
  848. t.Fatal(err)
  849. }
  850. defer stdin.Close()
  851. defer stdout.Close()
  852. if _, err := io.WriteString(stdin, "hello world"); err != nil {
  853. t.Fatal(err)
  854. }
  855. if err := stdin.Close(); err != nil {
  856. t.Fatal(err)
  857. }
  858. container.Wait()
  859. output, err := ioutil.ReadAll(stdout)
  860. if err != nil {
  861. t.Fatal(err)
  862. }
  863. if string(output) != "hello world" {
  864. t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world", string(output))
  865. }
  866. }
  867. func TestTty(t *testing.T) {
  868. runtime := mkRuntime(t)
  869. defer nuke(runtime)
  870. container, err := NewBuilder(runtime).Create(&Config{
  871. Image: GetTestImage(runtime).ID,
  872. Cmd: []string{"cat"},
  873. OpenStdin: true,
  874. },
  875. )
  876. if err != nil {
  877. t.Fatal(err)
  878. }
  879. defer runtime.Destroy(container)
  880. stdin, err := container.StdinPipe()
  881. if err != nil {
  882. t.Fatal(err)
  883. }
  884. stdout, err := container.StdoutPipe()
  885. if err != nil {
  886. t.Fatal(err)
  887. }
  888. hostConfig := &HostConfig{}
  889. if err := container.Start(hostConfig); err != nil {
  890. t.Fatal(err)
  891. }
  892. defer stdin.Close()
  893. defer stdout.Close()
  894. if _, err := io.WriteString(stdin, "hello world"); err != nil {
  895. t.Fatal(err)
  896. }
  897. if err := stdin.Close(); err != nil {
  898. t.Fatal(err)
  899. }
  900. container.Wait()
  901. output, err := ioutil.ReadAll(stdout)
  902. if err != nil {
  903. t.Fatal(err)
  904. }
  905. if string(output) != "hello world" {
  906. t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world", string(output))
  907. }
  908. }
  909. func TestEnv(t *testing.T) {
  910. runtime := mkRuntime(t)
  911. defer nuke(runtime)
  912. container, err := NewBuilder(runtime).Create(&Config{
  913. Image: GetTestImage(runtime).ID,
  914. Cmd: []string{"env"},
  915. },
  916. )
  917. if err != nil {
  918. t.Fatal(err)
  919. }
  920. defer runtime.Destroy(container)
  921. stdout, err := container.StdoutPipe()
  922. if err != nil {
  923. t.Fatal(err)
  924. }
  925. defer stdout.Close()
  926. hostConfig := &HostConfig{}
  927. if err := container.Start(hostConfig); err != nil {
  928. t.Fatal(err)
  929. }
  930. container.Wait()
  931. output, err := ioutil.ReadAll(stdout)
  932. if err != nil {
  933. t.Fatal(err)
  934. }
  935. actualEnv := strings.Split(string(output), "\n")
  936. if actualEnv[len(actualEnv)-1] == "" {
  937. actualEnv = actualEnv[:len(actualEnv)-1]
  938. }
  939. sort.Strings(actualEnv)
  940. goodEnv := []string{
  941. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  942. "HOME=/",
  943. }
  944. sort.Strings(goodEnv)
  945. if len(goodEnv) != len(actualEnv) {
  946. t.Fatalf("Wrong environment: should be %d variables, not: '%s'\n", len(goodEnv), strings.Join(actualEnv, ", "))
  947. }
  948. for i := range goodEnv {
  949. if actualEnv[i] != goodEnv[i] {
  950. t.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i])
  951. }
  952. }
  953. }
  954. func TestEntrypoint(t *testing.T) {
  955. runtime, err := newTestRuntime()
  956. if err != nil {
  957. t.Fatal(err)
  958. }
  959. defer nuke(runtime)
  960. container, err := NewBuilder(runtime).Create(
  961. &Config{
  962. Image: GetTestImage(runtime).ID,
  963. Entrypoint: []string{"/bin/echo"},
  964. Cmd: []string{"-n", "foobar"},
  965. },
  966. )
  967. if err != nil {
  968. t.Fatal(err)
  969. }
  970. defer runtime.Destroy(container)
  971. output, err := container.Output()
  972. if err != nil {
  973. t.Fatal(err)
  974. }
  975. if string(output) != "foobar" {
  976. t.Error(string(output))
  977. }
  978. }
  979. func grepFile(t *testing.T, path string, pattern string) {
  980. f, err := os.Open(path)
  981. if err != nil {
  982. t.Fatal(err)
  983. }
  984. defer f.Close()
  985. r := bufio.NewReader(f)
  986. var (
  987. line string
  988. )
  989. err = nil
  990. for err == nil {
  991. line, err = r.ReadString('\n')
  992. if strings.Contains(line, pattern) == true {
  993. return
  994. }
  995. }
  996. t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path)
  997. }
  998. func TestLXCConfig(t *testing.T) {
  999. runtime := mkRuntime(t)
  1000. defer nuke(runtime)
  1001. // Memory is allocated randomly for testing
  1002. rand.Seed(time.Now().UTC().UnixNano())
  1003. memMin := 33554432
  1004. memMax := 536870912
  1005. mem := memMin + rand.Intn(memMax-memMin)
  1006. // CPU shares as well
  1007. cpuMin := 100
  1008. cpuMax := 10000
  1009. cpu := cpuMin + rand.Intn(cpuMax-cpuMin)
  1010. container, err := NewBuilder(runtime).Create(&Config{
  1011. Image: GetTestImage(runtime).ID,
  1012. Cmd: []string{"/bin/true"},
  1013. Hostname: "foobar",
  1014. Memory: int64(mem),
  1015. CpuShares: int64(cpu),
  1016. },
  1017. )
  1018. if err != nil {
  1019. t.Fatal(err)
  1020. }
  1021. defer runtime.Destroy(container)
  1022. container.generateLXCConfig()
  1023. grepFile(t, container.lxcConfigPath(), "lxc.utsname = foobar")
  1024. grepFile(t, container.lxcConfigPath(),
  1025. fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
  1026. grepFile(t, container.lxcConfigPath(),
  1027. fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2))
  1028. }
  1029. func BenchmarkRunSequencial(b *testing.B) {
  1030. runtime, err := newTestRuntime()
  1031. if err != nil {
  1032. b.Fatal(err)
  1033. }
  1034. defer nuke(runtime)
  1035. for i := 0; i < b.N; i++ {
  1036. container, err := NewBuilder(runtime).Create(&Config{
  1037. Image: GetTestImage(runtime).ID,
  1038. Cmd: []string{"echo", "-n", "foo"},
  1039. },
  1040. )
  1041. if err != nil {
  1042. b.Fatal(err)
  1043. }
  1044. defer runtime.Destroy(container)
  1045. output, err := container.Output()
  1046. if err != nil {
  1047. b.Fatal(err)
  1048. }
  1049. if string(output) != "foo" {
  1050. b.Fatalf("Unexpected output: %s", output)
  1051. }
  1052. if err := runtime.Destroy(container); err != nil {
  1053. b.Fatal(err)
  1054. }
  1055. }
  1056. }
  1057. func BenchmarkRunParallel(b *testing.B) {
  1058. runtime, err := newTestRuntime()
  1059. if err != nil {
  1060. b.Fatal(err)
  1061. }
  1062. defer nuke(runtime)
  1063. var tasks []chan error
  1064. for i := 0; i < b.N; i++ {
  1065. complete := make(chan error)
  1066. tasks = append(tasks, complete)
  1067. go func(i int, complete chan error) {
  1068. container, err := NewBuilder(runtime).Create(&Config{
  1069. Image: GetTestImage(runtime).ID,
  1070. Cmd: []string{"echo", "-n", "foo"},
  1071. },
  1072. )
  1073. if err != nil {
  1074. complete <- err
  1075. return
  1076. }
  1077. defer runtime.Destroy(container)
  1078. hostConfig := &HostConfig{}
  1079. if err := container.Start(hostConfig); err != nil {
  1080. complete <- err
  1081. return
  1082. }
  1083. if err := container.WaitTimeout(15 * time.Second); err != nil {
  1084. complete <- err
  1085. return
  1086. }
  1087. // if string(output) != "foo" {
  1088. // complete <- fmt.Errorf("Unexecpted output: %v", string(output))
  1089. // }
  1090. if err := runtime.Destroy(container); err != nil {
  1091. complete <- err
  1092. return
  1093. }
  1094. complete <- nil
  1095. }(i, complete)
  1096. }
  1097. var errors []error
  1098. for _, task := range tasks {
  1099. err := <-task
  1100. if err != nil {
  1101. errors = append(errors, err)
  1102. }
  1103. }
  1104. if len(errors) > 0 {
  1105. b.Fatal(errors)
  1106. }
  1107. }
  1108. func tempDir(t *testing.T) string {
  1109. tmpDir, err := ioutil.TempDir("", "docker-test")
  1110. if err != nil {
  1111. t.Fatal(err)
  1112. }
  1113. return tmpDir
  1114. }
  1115. func TestBindMounts(t *testing.T) {
  1116. r := mkRuntime(t)
  1117. defer nuke(r)
  1118. tmpDir := tempDir(t)
  1119. defer os.RemoveAll(tmpDir)
  1120. writeFile(path.Join(tmpDir, "touch-me"), "", t)
  1121. // Test reading from a read-only bind mount
  1122. stdout, _ := runContainer(r, []string{"-b", fmt.Sprintf("%s:/tmp:ro", tmpDir), "_", "ls", "/tmp"}, t)
  1123. if !strings.Contains(stdout, "touch-me") {
  1124. t.Fatal("Container failed to read from bind mount")
  1125. }
  1126. // test writing to bind mount
  1127. runContainer(r, []string{"-b", fmt.Sprintf("%s:/tmp:rw", tmpDir), "_", "touch", "/tmp/holla"}, t)
  1128. readFile(path.Join(tmpDir, "holla"), t) // Will fail if the file doesn't exist
  1129. // test mounting to an illegal destination directory
  1130. if _, err := runContainer(r, []string{"-b", fmt.Sprintf("%s:.", tmpDir), "ls", "."}, nil); err == nil {
  1131. t.Fatal("Container bind mounted illegal directory")
  1132. }
  1133. }