container_test.go 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238
  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. // Give some time to lxc to spawn the process (setuid might take some time)
  471. container.WaitTimeout(500 * time.Millisecond)
  472. if !container.State.Running {
  473. t.Errorf("Container should be running")
  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{"/usr/bin/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. }