api_test.go 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. package docker
  2. import (
  3. "bufio"
  4. "bytes"
  5. "encoding/json"
  6. "fmt"
  7. "github.com/dotcloud/docker/api"
  8. "github.com/dotcloud/docker/dockerversion"
  9. "github.com/dotcloud/docker/engine"
  10. "github.com/dotcloud/docker/image"
  11. "github.com/dotcloud/docker/runconfig"
  12. "github.com/dotcloud/docker/runtime"
  13. "github.com/dotcloud/docker/utils"
  14. "github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
  15. "io"
  16. "io/ioutil"
  17. "net"
  18. "net/http"
  19. "net/http/httptest"
  20. "strings"
  21. "testing"
  22. "time"
  23. )
  24. func TestGetVersion(t *testing.T) {
  25. eng := NewTestEngine(t)
  26. defer mkRuntimeFromEngine(eng, t).Nuke()
  27. var err error
  28. r := httptest.NewRecorder()
  29. req, err := http.NewRequest("GET", "/version", nil)
  30. if err != nil {
  31. t.Fatal(err)
  32. }
  33. // FIXME getting the version should require an actual running Server
  34. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  35. t.Fatal(err)
  36. }
  37. assertHttpNotError(r, t)
  38. out := engine.NewOutput()
  39. v, err := out.AddEnv()
  40. if err != nil {
  41. t.Fatal(err)
  42. }
  43. if _, err := io.Copy(out, r.Body); err != nil {
  44. t.Fatal(err)
  45. }
  46. out.Close()
  47. expected := dockerversion.VERSION
  48. if result := v.Get("Version"); result != expected {
  49. t.Errorf("Expected version %s, %s found", expected, result)
  50. }
  51. expected = "application/json"
  52. if result := r.HeaderMap.Get("Content-Type"); result != expected {
  53. t.Errorf("Expected Content-Type %s, %s found", expected, result)
  54. }
  55. }
  56. func TestGetInfo(t *testing.T) {
  57. eng := NewTestEngine(t)
  58. defer mkRuntimeFromEngine(eng, t).Nuke()
  59. job := eng.Job("images")
  60. initialImages, err := job.Stdout.AddListTable()
  61. if err != nil {
  62. t.Fatal(err)
  63. }
  64. if err := job.Run(); err != nil {
  65. t.Fatal(err)
  66. }
  67. req, err := http.NewRequest("GET", "/info", nil)
  68. if err != nil {
  69. t.Fatal(err)
  70. }
  71. r := httptest.NewRecorder()
  72. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  73. t.Fatal(err)
  74. }
  75. assertHttpNotError(r, t)
  76. out := engine.NewOutput()
  77. i, err := out.AddEnv()
  78. if err != nil {
  79. t.Fatal(err)
  80. }
  81. if _, err := io.Copy(out, r.Body); err != nil {
  82. t.Fatal(err)
  83. }
  84. out.Close()
  85. if images := i.GetInt("Images"); images != initialImages.Len() {
  86. t.Errorf("Expected images: %d, %d found", initialImages.Len(), images)
  87. }
  88. expected := "application/json"
  89. if result := r.HeaderMap.Get("Content-Type"); result != expected {
  90. t.Errorf("Expected Content-Type %s, %s found", expected, result)
  91. }
  92. }
  93. func TestGetEvents(t *testing.T) {
  94. eng := NewTestEngine(t)
  95. srv := mkServerFromEngine(eng, t)
  96. // FIXME: we might not need runtime, why not simply nuke
  97. // the engine?
  98. runtime := mkRuntimeFromEngine(eng, t)
  99. defer nuke(runtime)
  100. var events []*utils.JSONMessage
  101. for _, parts := range [][3]string{
  102. {"fakeaction", "fakeid", "fakeimage"},
  103. {"fakeaction2", "fakeid", "fakeimage"},
  104. } {
  105. action, id, from := parts[0], parts[1], parts[2]
  106. ev := srv.LogEvent(action, id, from)
  107. events = append(events, ev)
  108. }
  109. req, err := http.NewRequest("GET", "/events?since=1", nil)
  110. if err != nil {
  111. t.Fatal(err)
  112. }
  113. r := httptest.NewRecorder()
  114. setTimeout(t, "", 500*time.Millisecond, func() {
  115. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  116. t.Fatal(err)
  117. }
  118. assertHttpNotError(r, t)
  119. })
  120. dec := json.NewDecoder(r.Body)
  121. for i := 0; i < 2; i++ {
  122. var jm utils.JSONMessage
  123. if err := dec.Decode(&jm); err == io.EOF {
  124. break
  125. } else if err != nil {
  126. t.Fatal(err)
  127. }
  128. if jm != *events[i] {
  129. t.Fatalf("Event received it different than expected")
  130. }
  131. }
  132. }
  133. func TestGetImagesJSON(t *testing.T) {
  134. eng := NewTestEngine(t)
  135. defer mkRuntimeFromEngine(eng, t).Nuke()
  136. job := eng.Job("images")
  137. initialImages, err := job.Stdout.AddListTable()
  138. if err != nil {
  139. t.Fatal(err)
  140. }
  141. if err := job.Run(); err != nil {
  142. t.Fatal(err)
  143. }
  144. req, err := http.NewRequest("GET", "/images/json?all=0", nil)
  145. if err != nil {
  146. t.Fatal(err)
  147. }
  148. r := httptest.NewRecorder()
  149. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  150. t.Fatal(err)
  151. }
  152. assertHttpNotError(r, t)
  153. images := engine.NewTable("Created", 0)
  154. if _, err := images.ReadListFrom(r.Body.Bytes()); err != nil {
  155. t.Fatal(err)
  156. }
  157. if images.Len() != initialImages.Len() {
  158. t.Errorf("Expected %d image, %d found", initialImages.Len(), images.Len())
  159. }
  160. found := false
  161. for _, img := range images.Data {
  162. if strings.Contains(img.GetList("RepoTags")[0], unitTestImageName) {
  163. found = true
  164. break
  165. }
  166. }
  167. if !found {
  168. t.Errorf("Expected image %s, %+v found", unitTestImageName, images)
  169. }
  170. r2 := httptest.NewRecorder()
  171. // all=1
  172. initialImages = getAllImages(eng, t)
  173. req2, err := http.NewRequest("GET", "/images/json?all=true", nil)
  174. if err != nil {
  175. t.Fatal(err)
  176. }
  177. if err := api.ServeRequest(eng, api.APIVERSION, r2, req2); err != nil {
  178. t.Fatal(err)
  179. }
  180. assertHttpNotError(r2, t)
  181. images2 := engine.NewTable("Id", 0)
  182. if _, err := images2.ReadListFrom(r2.Body.Bytes()); err != nil {
  183. t.Fatal(err)
  184. }
  185. if images2.Len() != initialImages.Len() {
  186. t.Errorf("Expected %d image, %d found", initialImages.Len(), images2.Len())
  187. }
  188. found = false
  189. for _, img := range images2.Data {
  190. if img.Get("Id") == unitTestImageID {
  191. found = true
  192. break
  193. }
  194. }
  195. if !found {
  196. t.Errorf("Retrieved image Id differs, expected %s, received %+v", unitTestImageID, images2)
  197. }
  198. r3 := httptest.NewRecorder()
  199. // filter=a
  200. req3, err := http.NewRequest("GET", "/images/json?filter=aaaaaaaaaa", nil)
  201. if err != nil {
  202. t.Fatal(err)
  203. }
  204. if err := api.ServeRequest(eng, api.APIVERSION, r3, req3); err != nil {
  205. t.Fatal(err)
  206. }
  207. assertHttpNotError(r3, t)
  208. images3 := engine.NewTable("Id", 0)
  209. if _, err := images3.ReadListFrom(r3.Body.Bytes()); err != nil {
  210. t.Fatal(err)
  211. }
  212. if images3.Len() != 0 {
  213. t.Errorf("Expected 0 image, %d found", images3.Len())
  214. }
  215. }
  216. func TestGetImagesHistory(t *testing.T) {
  217. eng := NewTestEngine(t)
  218. defer mkRuntimeFromEngine(eng, t).Nuke()
  219. r := httptest.NewRecorder()
  220. req, err := http.NewRequest("GET", fmt.Sprintf("/images/%s/history", unitTestImageName), nil)
  221. if err != nil {
  222. t.Fatal(err)
  223. }
  224. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  225. t.Fatal(err)
  226. }
  227. assertHttpNotError(r, t)
  228. outs := engine.NewTable("Created", 0)
  229. if _, err := outs.ReadListFrom(r.Body.Bytes()); err != nil {
  230. t.Fatal(err)
  231. }
  232. if len(outs.Data) != 1 {
  233. t.Errorf("Expected 1 line, %d found", len(outs.Data))
  234. }
  235. }
  236. func TestGetImagesByName(t *testing.T) {
  237. eng := NewTestEngine(t)
  238. defer mkRuntimeFromEngine(eng, t).Nuke()
  239. req, err := http.NewRequest("GET", "/images/"+unitTestImageName+"/json", nil)
  240. if err != nil {
  241. t.Fatal(err)
  242. }
  243. r := httptest.NewRecorder()
  244. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  245. t.Fatal(err)
  246. }
  247. assertHttpNotError(r, t)
  248. img := &image.Image{}
  249. if err := json.Unmarshal(r.Body.Bytes(), img); err != nil {
  250. t.Fatal(err)
  251. }
  252. if img.ID != unitTestImageID {
  253. t.Errorf("Error inspecting image")
  254. }
  255. }
  256. func TestGetContainersJSON(t *testing.T) {
  257. eng := NewTestEngine(t)
  258. defer mkRuntimeFromEngine(eng, t).Nuke()
  259. job := eng.Job("containers")
  260. job.SetenvBool("all", true)
  261. outs, err := job.Stdout.AddTable()
  262. if err != nil {
  263. t.Fatal(err)
  264. }
  265. if err := job.Run(); err != nil {
  266. t.Fatal(err)
  267. }
  268. beginLen := len(outs.Data)
  269. containerID := createTestContainer(eng, &runconfig.Config{
  270. Image: unitTestImageID,
  271. Cmd: []string{"echo", "test"},
  272. }, t)
  273. if containerID == "" {
  274. t.Fatalf("Received empty container ID")
  275. }
  276. req, err := http.NewRequest("GET", "/containers/json?all=1", nil)
  277. if err != nil {
  278. t.Fatal(err)
  279. }
  280. r := httptest.NewRecorder()
  281. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  282. t.Fatal(err)
  283. }
  284. assertHttpNotError(r, t)
  285. containers := engine.NewTable("", 0)
  286. if _, err := containers.ReadListFrom(r.Body.Bytes()); err != nil {
  287. t.Fatal(err)
  288. }
  289. if len(containers.Data) != beginLen+1 {
  290. t.Fatalf("Expected %d container, %d found (started with: %d)", beginLen+1, len(containers.Data), beginLen)
  291. }
  292. if id := containers.Data[0].Get("Id"); id != containerID {
  293. t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", containerID, id)
  294. }
  295. }
  296. func TestGetContainersExport(t *testing.T) {
  297. eng := NewTestEngine(t)
  298. defer mkRuntimeFromEngine(eng, t).Nuke()
  299. // Create a container and remove a file
  300. containerID := createTestContainer(eng,
  301. &runconfig.Config{
  302. Image: unitTestImageID,
  303. Cmd: []string{"touch", "/test"},
  304. },
  305. t,
  306. )
  307. containerRun(eng, containerID, t)
  308. r := httptest.NewRecorder()
  309. req, err := http.NewRequest("GET", "/containers/"+containerID+"/export", nil)
  310. if err != nil {
  311. t.Fatal(err)
  312. }
  313. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  314. t.Fatal(err)
  315. }
  316. assertHttpNotError(r, t)
  317. if r.Code != http.StatusOK {
  318. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  319. }
  320. found := false
  321. for tarReader := tar.NewReader(r.Body); ; {
  322. h, err := tarReader.Next()
  323. if err != nil {
  324. if err == io.EOF {
  325. break
  326. }
  327. t.Fatal(err)
  328. }
  329. if h.Name == "test" {
  330. found = true
  331. break
  332. }
  333. }
  334. if !found {
  335. t.Fatalf("The created test file has not been found in the exported image")
  336. }
  337. }
  338. func TestSaveImageAndThenLoad(t *testing.T) {
  339. eng := NewTestEngine(t)
  340. defer mkRuntimeFromEngine(eng, t).Nuke()
  341. // save image
  342. r := httptest.NewRecorder()
  343. req, err := http.NewRequest("GET", "/images/"+unitTestImageID+"/get", nil)
  344. if err != nil {
  345. t.Fatal(err)
  346. }
  347. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  348. t.Fatal(err)
  349. }
  350. if r.Code != http.StatusOK {
  351. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  352. }
  353. tarball := r.Body
  354. // delete the image
  355. r = httptest.NewRecorder()
  356. req, err = http.NewRequest("DELETE", "/images/"+unitTestImageID, nil)
  357. if err != nil {
  358. t.Fatal(err)
  359. }
  360. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  361. t.Fatal(err)
  362. }
  363. if r.Code != http.StatusOK {
  364. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  365. }
  366. // make sure there is no image
  367. r = httptest.NewRecorder()
  368. req, err = http.NewRequest("GET", "/images/"+unitTestImageID+"/get", nil)
  369. if err != nil {
  370. t.Fatal(err)
  371. }
  372. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  373. t.Fatal(err)
  374. }
  375. if r.Code != http.StatusNotFound {
  376. t.Fatalf("%d NotFound expected, received %d\n", http.StatusNotFound, r.Code)
  377. }
  378. // load the image
  379. r = httptest.NewRecorder()
  380. req, err = http.NewRequest("POST", "/images/load", tarball)
  381. if err != nil {
  382. t.Fatal(err)
  383. }
  384. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  385. t.Fatal(err)
  386. }
  387. if r.Code != http.StatusOK {
  388. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  389. }
  390. // finally make sure the image is there
  391. r = httptest.NewRecorder()
  392. req, err = http.NewRequest("GET", "/images/"+unitTestImageID+"/get", nil)
  393. if err != nil {
  394. t.Fatal(err)
  395. }
  396. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  397. t.Fatal(err)
  398. }
  399. if r.Code != http.StatusOK {
  400. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  401. }
  402. }
  403. func TestGetContainersChanges(t *testing.T) {
  404. eng := NewTestEngine(t)
  405. defer mkRuntimeFromEngine(eng, t).Nuke()
  406. // Create a container and remove a file
  407. containerID := createTestContainer(eng,
  408. &runconfig.Config{
  409. Image: unitTestImageID,
  410. Cmd: []string{"/bin/rm", "/etc/passwd"},
  411. },
  412. t,
  413. )
  414. containerRun(eng, containerID, t)
  415. r := httptest.NewRecorder()
  416. req, err := http.NewRequest("GET", "/containers/"+containerID+"/changes", nil)
  417. if err != nil {
  418. t.Fatal(err)
  419. }
  420. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  421. t.Fatal(err)
  422. }
  423. assertHttpNotError(r, t)
  424. outs := engine.NewTable("", 0)
  425. if _, err := outs.ReadListFrom(r.Body.Bytes()); err != nil {
  426. t.Fatal(err)
  427. }
  428. // Check the changelog
  429. success := false
  430. for _, elem := range outs.Data {
  431. if elem.Get("Path") == "/etc/passwd" && elem.GetInt("Kind") == 2 {
  432. success = true
  433. }
  434. }
  435. if !success {
  436. t.Fatalf("/etc/passwd as been removed but is not present in the diff")
  437. }
  438. }
  439. func TestGetContainersTop(t *testing.T) {
  440. eng := NewTestEngine(t)
  441. defer mkRuntimeFromEngine(eng, t).Nuke()
  442. containerID := createTestContainer(eng,
  443. &runconfig.Config{
  444. Image: unitTestImageID,
  445. Cmd: []string{"/bin/sh", "-c", "cat"},
  446. OpenStdin: true,
  447. },
  448. t,
  449. )
  450. defer func() {
  451. // Make sure the process dies before destroying runtime
  452. containerKill(eng, containerID, t)
  453. containerWait(eng, containerID, t)
  454. }()
  455. startContainer(eng, containerID, t)
  456. setTimeout(t, "Waiting for the container to be started timed out", 10*time.Second, func() {
  457. for {
  458. if containerRunning(eng, containerID, t) {
  459. break
  460. }
  461. time.Sleep(10 * time.Millisecond)
  462. }
  463. })
  464. if !containerRunning(eng, containerID, t) {
  465. t.Fatalf("Container should be running")
  466. }
  467. // Make sure sh spawn up cat
  468. setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
  469. in, out := containerAttach(eng, containerID, t)
  470. if err := assertPipe("hello\n", "hello", out, in, 150); err != nil {
  471. t.Fatal(err)
  472. }
  473. })
  474. r := httptest.NewRecorder()
  475. req, err := http.NewRequest("GET", "/containers/"+containerID+"/top?ps_args=aux", nil)
  476. if err != nil {
  477. t.Fatal(err)
  478. }
  479. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  480. t.Fatal(err)
  481. }
  482. assertHttpNotError(r, t)
  483. var procs engine.Env
  484. if err := procs.Decode(r.Body); err != nil {
  485. t.Fatal(err)
  486. }
  487. if len(procs.GetList("Titles")) != 11 {
  488. t.Fatalf("Expected 11 titles, found %d.", len(procs.GetList("Titles")))
  489. }
  490. if procs.GetList("Titles")[0] != "USER" || procs.GetList("Titles")[10] != "COMMAND" {
  491. t.Fatalf("Expected Titles[0] to be USER and Titles[10] to be COMMAND, found %s and %s.", procs.GetList("Titles")[0], procs.GetList("Titles")[10])
  492. }
  493. processes := [][]string{}
  494. if err := procs.GetJson("Processes", &processes); err != nil {
  495. t.Fatal(err)
  496. }
  497. if len(processes) != 2 {
  498. t.Fatalf("Expected 2 processes, found %d.", len(processes))
  499. }
  500. if processes[0][10] != "/bin/sh -c cat" {
  501. t.Fatalf("Expected `/bin/sh -c cat`, found %s.", processes[0][10])
  502. }
  503. if processes[1][10] != "/bin/sh -c cat" {
  504. t.Fatalf("Expected `/bin/sh -c cat`, found %s.", processes[1][10])
  505. }
  506. }
  507. func TestGetContainersByName(t *testing.T) {
  508. eng := NewTestEngine(t)
  509. defer mkRuntimeFromEngine(eng, t).Nuke()
  510. // Create a container and remove a file
  511. containerID := createTestContainer(eng,
  512. &runconfig.Config{
  513. Image: unitTestImageID,
  514. Cmd: []string{"echo", "test"},
  515. },
  516. t,
  517. )
  518. r := httptest.NewRecorder()
  519. req, err := http.NewRequest("GET", "/containers/"+containerID+"/json", nil)
  520. if err != nil {
  521. t.Fatal(err)
  522. }
  523. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  524. t.Fatal(err)
  525. }
  526. assertHttpNotError(r, t)
  527. outContainer := &runtime.Container{}
  528. if err := json.Unmarshal(r.Body.Bytes(), outContainer); err != nil {
  529. t.Fatal(err)
  530. }
  531. if outContainer.ID != containerID {
  532. t.Fatalf("Wrong containers retrieved. Expected %s, received %s", containerID, outContainer.ID)
  533. }
  534. }
  535. func TestPostCommit(t *testing.T) {
  536. eng := NewTestEngine(t)
  537. defer mkRuntimeFromEngine(eng, t).Nuke()
  538. srv := mkServerFromEngine(eng, t)
  539. // Create a container and remove a file
  540. containerID := createTestContainer(eng,
  541. &runconfig.Config{
  542. Image: unitTestImageID,
  543. Cmd: []string{"touch", "/test"},
  544. },
  545. t,
  546. )
  547. containerRun(eng, containerID, t)
  548. req, err := http.NewRequest("POST", "/commit?repo=testrepo&testtag=tag&container="+containerID, bytes.NewReader([]byte{}))
  549. if err != nil {
  550. t.Fatal(err)
  551. }
  552. r := httptest.NewRecorder()
  553. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  554. t.Fatal(err)
  555. }
  556. assertHttpNotError(r, t)
  557. if r.Code != http.StatusCreated {
  558. t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
  559. }
  560. var env engine.Env
  561. if err := env.Decode(r.Body); err != nil {
  562. t.Fatal(err)
  563. }
  564. if _, err := srv.ImageInspect(env.Get("Id")); err != nil {
  565. t.Fatalf("The image has not been committed")
  566. }
  567. }
  568. func TestPostContainersCreate(t *testing.T) {
  569. eng := NewTestEngine(t)
  570. defer mkRuntimeFromEngine(eng, t).Nuke()
  571. configJSON, err := json.Marshal(&runconfig.Config{
  572. Image: unitTestImageID,
  573. Memory: 33554432,
  574. Cmd: []string{"touch", "/test"},
  575. })
  576. if err != nil {
  577. t.Fatal(err)
  578. }
  579. req, err := http.NewRequest("POST", "/containers/create", bytes.NewReader(configJSON))
  580. if err != nil {
  581. t.Fatal(err)
  582. }
  583. r := httptest.NewRecorder()
  584. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  585. t.Fatal(err)
  586. }
  587. assertHttpNotError(r, t)
  588. if r.Code != http.StatusCreated {
  589. t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
  590. }
  591. var apiRun engine.Env
  592. if err := apiRun.Decode(r.Body); err != nil {
  593. t.Fatal(err)
  594. }
  595. containerID := apiRun.Get("Id")
  596. containerAssertExists(eng, containerID, t)
  597. containerRun(eng, containerID, t)
  598. if !containerFileExists(eng, containerID, "test", t) {
  599. t.Fatal("Test file was not created")
  600. }
  601. }
  602. func TestPostContainersKill(t *testing.T) {
  603. eng := NewTestEngine(t)
  604. defer mkRuntimeFromEngine(eng, t).Nuke()
  605. containerID := createTestContainer(eng,
  606. &runconfig.Config{
  607. Image: unitTestImageID,
  608. Cmd: []string{"/bin/cat"},
  609. OpenStdin: true,
  610. },
  611. t,
  612. )
  613. startContainer(eng, containerID, t)
  614. // Give some time to the process to start
  615. containerWaitTimeout(eng, containerID, t)
  616. if !containerRunning(eng, containerID, t) {
  617. t.Errorf("Container should be running")
  618. }
  619. r := httptest.NewRecorder()
  620. req, err := http.NewRequest("POST", "/containers/"+containerID+"/kill", bytes.NewReader([]byte{}))
  621. if err != nil {
  622. t.Fatal(err)
  623. }
  624. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  625. t.Fatal(err)
  626. }
  627. assertHttpNotError(r, t)
  628. if r.Code != http.StatusNoContent {
  629. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  630. }
  631. if containerRunning(eng, containerID, t) {
  632. t.Fatalf("The container hasn't been killed")
  633. }
  634. }
  635. func TestPostContainersRestart(t *testing.T) {
  636. eng := NewTestEngine(t)
  637. defer mkRuntimeFromEngine(eng, t).Nuke()
  638. containerID := createTestContainer(eng,
  639. &runconfig.Config{
  640. Image: unitTestImageID,
  641. Cmd: []string{"/bin/top"},
  642. OpenStdin: true,
  643. },
  644. t,
  645. )
  646. startContainer(eng, containerID, t)
  647. // Give some time to the process to start
  648. containerWaitTimeout(eng, containerID, t)
  649. if !containerRunning(eng, containerID, t) {
  650. t.Errorf("Container should be running")
  651. }
  652. req, err := http.NewRequest("POST", "/containers/"+containerID+"/restart?t=1", bytes.NewReader([]byte{}))
  653. if err != nil {
  654. t.Fatal(err)
  655. }
  656. r := httptest.NewRecorder()
  657. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  658. t.Fatal(err)
  659. }
  660. assertHttpNotError(r, t)
  661. if r.Code != http.StatusNoContent {
  662. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  663. }
  664. // Give some time to the process to restart
  665. containerWaitTimeout(eng, containerID, t)
  666. if !containerRunning(eng, containerID, t) {
  667. t.Fatalf("Container should be running")
  668. }
  669. containerKill(eng, containerID, t)
  670. }
  671. func TestPostContainersStart(t *testing.T) {
  672. eng := NewTestEngine(t)
  673. defer mkRuntimeFromEngine(eng, t).Nuke()
  674. containerID := createTestContainer(
  675. eng,
  676. &runconfig.Config{
  677. Image: unitTestImageID,
  678. Cmd: []string{"/bin/cat"},
  679. OpenStdin: true,
  680. },
  681. t,
  682. )
  683. hostConfigJSON, err := json.Marshal(&runconfig.HostConfig{})
  684. req, err := http.NewRequest("POST", "/containers/"+containerID+"/start", bytes.NewReader(hostConfigJSON))
  685. if err != nil {
  686. t.Fatal(err)
  687. }
  688. req.Header.Set("Content-Type", "application/json")
  689. r := httptest.NewRecorder()
  690. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  691. t.Fatal(err)
  692. }
  693. assertHttpNotError(r, t)
  694. if r.Code != http.StatusNoContent {
  695. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  696. }
  697. containerAssertExists(eng, containerID, t)
  698. // Give some time to the process to start
  699. // FIXME: use Wait once it's available as a job
  700. containerWaitTimeout(eng, containerID, t)
  701. if !containerRunning(eng, containerID, t) {
  702. t.Errorf("Container should be running")
  703. }
  704. r = httptest.NewRecorder()
  705. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  706. t.Fatal(err)
  707. }
  708. // Starting an already started container should return an error
  709. // FIXME: verify a precise error code. There is a possible bug here
  710. // which causes this to return 404 even though the container exists.
  711. assertHttpError(r, t)
  712. containerAssertExists(eng, containerID, t)
  713. containerKill(eng, containerID, t)
  714. }
  715. // Expected behaviour: using / as a bind mount source should throw an error
  716. func TestRunErrorBindMountRootSource(t *testing.T) {
  717. eng := NewTestEngine(t)
  718. defer mkRuntimeFromEngine(eng, t).Nuke()
  719. containerID := createTestContainer(
  720. eng,
  721. &runconfig.Config{
  722. Image: unitTestImageID,
  723. Cmd: []string{"/bin/cat"},
  724. OpenStdin: true,
  725. },
  726. t,
  727. )
  728. hostConfigJSON, err := json.Marshal(&runconfig.HostConfig{
  729. Binds: []string{"/:/tmp"},
  730. })
  731. req, err := http.NewRequest("POST", "/containers/"+containerID+"/start", bytes.NewReader(hostConfigJSON))
  732. if err != nil {
  733. t.Fatal(err)
  734. }
  735. req.Header.Set("Content-Type", "application/json")
  736. r := httptest.NewRecorder()
  737. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  738. t.Fatal(err)
  739. }
  740. if r.Code != http.StatusInternalServerError {
  741. containerKill(eng, containerID, t)
  742. t.Fatal("should have failed to run when using / as a source for the bind mount")
  743. }
  744. }
  745. func TestPostContainersStop(t *testing.T) {
  746. eng := NewTestEngine(t)
  747. defer mkRuntimeFromEngine(eng, t).Nuke()
  748. containerID := createTestContainer(eng,
  749. &runconfig.Config{
  750. Image: unitTestImageID,
  751. Cmd: []string{"/bin/top"},
  752. OpenStdin: true,
  753. },
  754. t,
  755. )
  756. startContainer(eng, containerID, t)
  757. // Give some time to the process to start
  758. containerWaitTimeout(eng, containerID, t)
  759. if !containerRunning(eng, containerID, t) {
  760. t.Errorf("Container should be running")
  761. }
  762. // Note: as it is a POST request, it requires a body.
  763. req, err := http.NewRequest("POST", "/containers/"+containerID+"/stop?t=1", bytes.NewReader([]byte{}))
  764. if err != nil {
  765. t.Fatal(err)
  766. }
  767. r := httptest.NewRecorder()
  768. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  769. t.Fatal(err)
  770. }
  771. assertHttpNotError(r, t)
  772. if r.Code != http.StatusNoContent {
  773. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  774. }
  775. if containerRunning(eng, containerID, t) {
  776. t.Fatalf("The container hasn't been stopped")
  777. }
  778. }
  779. func TestPostContainersWait(t *testing.T) {
  780. eng := NewTestEngine(t)
  781. defer mkRuntimeFromEngine(eng, t).Nuke()
  782. containerID := createTestContainer(eng,
  783. &runconfig.Config{
  784. Image: unitTestImageID,
  785. Cmd: []string{"/bin/sleep", "1"},
  786. OpenStdin: true,
  787. },
  788. t,
  789. )
  790. startContainer(eng, containerID, t)
  791. setTimeout(t, "Wait timed out", 3*time.Second, func() {
  792. r := httptest.NewRecorder()
  793. req, err := http.NewRequest("POST", "/containers/"+containerID+"/wait", bytes.NewReader([]byte{}))
  794. if err != nil {
  795. t.Fatal(err)
  796. }
  797. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  798. t.Fatal(err)
  799. }
  800. assertHttpNotError(r, t)
  801. var apiWait engine.Env
  802. if err := apiWait.Decode(r.Body); err != nil {
  803. t.Fatal(err)
  804. }
  805. if apiWait.GetInt("StatusCode") != 0 {
  806. t.Fatalf("Non zero exit code for sleep: %d\n", apiWait.GetInt("StatusCode"))
  807. }
  808. })
  809. if containerRunning(eng, containerID, t) {
  810. t.Fatalf("The container should be stopped after wait")
  811. }
  812. }
  813. func TestPostContainersAttach(t *testing.T) {
  814. eng := NewTestEngine(t)
  815. defer mkRuntimeFromEngine(eng, t).Nuke()
  816. containerID := createTestContainer(eng,
  817. &runconfig.Config{
  818. Image: unitTestImageID,
  819. Cmd: []string{"/bin/cat"},
  820. OpenStdin: true,
  821. },
  822. t,
  823. )
  824. // Start the process
  825. startContainer(eng, containerID, t)
  826. stdin, stdinPipe := io.Pipe()
  827. stdout, stdoutPipe := io.Pipe()
  828. // Try to avoid the timeout in destroy. Best effort, don't check error
  829. defer func() {
  830. closeWrap(stdin, stdinPipe, stdout, stdoutPipe)
  831. containerKill(eng, containerID, t)
  832. }()
  833. // Attach to it
  834. c1 := make(chan struct{})
  835. go func() {
  836. defer close(c1)
  837. r := &hijackTester{
  838. ResponseRecorder: httptest.NewRecorder(),
  839. in: stdin,
  840. out: stdoutPipe,
  841. }
  842. req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{}))
  843. if err != nil {
  844. t.Fatal(err)
  845. }
  846. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  847. t.Fatal(err)
  848. }
  849. assertHttpNotError(r.ResponseRecorder, t)
  850. }()
  851. // Acknowledge hijack
  852. setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
  853. stdout.Read([]byte{})
  854. stdout.Read(make([]byte, 4096))
  855. })
  856. setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
  857. if err := assertPipe("hello\n", string([]byte{1, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 150); err != nil {
  858. t.Fatal(err)
  859. }
  860. })
  861. // Close pipes (client disconnects)
  862. if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
  863. t.Fatal(err)
  864. }
  865. // Wait for attach to finish, the client disconnected, therefore, Attach finished his job
  866. setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() {
  867. <-c1
  868. })
  869. // We closed stdin, expect /bin/cat to still be running
  870. // Wait a little bit to make sure container.monitor() did his thing
  871. containerWaitTimeout(eng, containerID, t)
  872. // Try to avoid the timeout in destroy. Best effort, don't check error
  873. cStdin, _ := containerAttach(eng, containerID, t)
  874. cStdin.Close()
  875. containerWait(eng, containerID, t)
  876. }
  877. func TestPostContainersAttachStderr(t *testing.T) {
  878. eng := NewTestEngine(t)
  879. defer mkRuntimeFromEngine(eng, t).Nuke()
  880. containerID := createTestContainer(eng,
  881. &runconfig.Config{
  882. Image: unitTestImageID,
  883. Cmd: []string{"/bin/sh", "-c", "/bin/cat >&2"},
  884. OpenStdin: true,
  885. },
  886. t,
  887. )
  888. // Start the process
  889. startContainer(eng, containerID, t)
  890. stdin, stdinPipe := io.Pipe()
  891. stdout, stdoutPipe := io.Pipe()
  892. // Try to avoid the timeout in destroy. Best effort, don't check error
  893. defer func() {
  894. closeWrap(stdin, stdinPipe, stdout, stdoutPipe)
  895. containerKill(eng, containerID, t)
  896. }()
  897. // Attach to it
  898. c1 := make(chan struct{})
  899. go func() {
  900. defer close(c1)
  901. r := &hijackTester{
  902. ResponseRecorder: httptest.NewRecorder(),
  903. in: stdin,
  904. out: stdoutPipe,
  905. }
  906. req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{}))
  907. if err != nil {
  908. t.Fatal(err)
  909. }
  910. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  911. t.Fatal(err)
  912. }
  913. assertHttpNotError(r.ResponseRecorder, t)
  914. }()
  915. // Acknowledge hijack
  916. setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
  917. stdout.Read([]byte{})
  918. stdout.Read(make([]byte, 4096))
  919. })
  920. setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
  921. if err := assertPipe("hello\n", string([]byte{2, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 150); err != nil {
  922. t.Fatal(err)
  923. }
  924. })
  925. // Close pipes (client disconnects)
  926. if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
  927. t.Fatal(err)
  928. }
  929. // Wait for attach to finish, the client disconnected, therefore, Attach finished his job
  930. setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() {
  931. <-c1
  932. })
  933. // We closed stdin, expect /bin/cat to still be running
  934. // Wait a little bit to make sure container.monitor() did his thing
  935. containerWaitTimeout(eng, containerID, t)
  936. // Try to avoid the timeout in destroy. Best effort, don't check error
  937. cStdin, _ := containerAttach(eng, containerID, t)
  938. cStdin.Close()
  939. containerWait(eng, containerID, t)
  940. }
  941. // FIXME: Test deleting running container
  942. // FIXME: Test deleting container with volume
  943. // FIXME: Test deleting volume in use by other container
  944. func TestDeleteContainers(t *testing.T) {
  945. eng := NewTestEngine(t)
  946. defer mkRuntimeFromEngine(eng, t).Nuke()
  947. containerID := createTestContainer(eng,
  948. &runconfig.Config{
  949. Image: unitTestImageID,
  950. Cmd: []string{"touch", "/test"},
  951. },
  952. t,
  953. )
  954. req, err := http.NewRequest("DELETE", "/containers/"+containerID, nil)
  955. if err != nil {
  956. t.Fatal(err)
  957. }
  958. r := httptest.NewRecorder()
  959. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  960. t.Fatal(err)
  961. }
  962. assertHttpNotError(r, t)
  963. if r.Code != http.StatusNoContent {
  964. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  965. }
  966. containerAssertNotExists(eng, containerID, t)
  967. }
  968. func TestOptionsRoute(t *testing.T) {
  969. eng := NewTestEngine(t)
  970. defer mkRuntimeFromEngine(eng, t).Nuke()
  971. r := httptest.NewRecorder()
  972. req, err := http.NewRequest("OPTIONS", "/", nil)
  973. if err != nil {
  974. t.Fatal(err)
  975. }
  976. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  977. t.Fatal(err)
  978. }
  979. assertHttpNotError(r, t)
  980. if r.Code != http.StatusOK {
  981. t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
  982. }
  983. }
  984. func TestGetEnabledCors(t *testing.T) {
  985. eng := NewTestEngine(t)
  986. defer mkRuntimeFromEngine(eng, t).Nuke()
  987. r := httptest.NewRecorder()
  988. req, err := http.NewRequest("GET", "/version", nil)
  989. if err != nil {
  990. t.Fatal(err)
  991. }
  992. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  993. t.Fatal(err)
  994. }
  995. assertHttpNotError(r, t)
  996. if r.Code != http.StatusOK {
  997. t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
  998. }
  999. allowOrigin := r.Header().Get("Access-Control-Allow-Origin")
  1000. allowHeaders := r.Header().Get("Access-Control-Allow-Headers")
  1001. allowMethods := r.Header().Get("Access-Control-Allow-Methods")
  1002. if allowOrigin != "*" {
  1003. t.Errorf("Expected header Access-Control-Allow-Origin to be \"*\", %s found.", allowOrigin)
  1004. }
  1005. if allowHeaders != "Origin, X-Requested-With, Content-Type, Accept" {
  1006. t.Errorf("Expected header Access-Control-Allow-Headers to be \"Origin, X-Requested-With, Content-Type, Accept\", %s found.", allowHeaders)
  1007. }
  1008. if allowMethods != "GET, POST, DELETE, PUT, OPTIONS" {
  1009. t.Errorf("Expected hearder Access-Control-Allow-Methods to be \"GET, POST, DELETE, PUT, OPTIONS\", %s found.", allowMethods)
  1010. }
  1011. }
  1012. func TestDeleteImages(t *testing.T) {
  1013. eng := NewTestEngine(t)
  1014. //we expect errors, so we disable stderr
  1015. eng.Stderr = ioutil.Discard
  1016. defer mkRuntimeFromEngine(eng, t).Nuke()
  1017. initialImages := getImages(eng, t, true, "")
  1018. if err := eng.Job("tag", unitTestImageName, "test", "test").Run(); err != nil {
  1019. t.Fatal(err)
  1020. }
  1021. images := getImages(eng, t, true, "")
  1022. if len(images.Data[0].GetList("RepoTags")) != len(initialImages.Data[0].GetList("RepoTags"))+1 {
  1023. t.Errorf("Expected %d images, %d found", len(initialImages.Data[0].GetList("RepoTags"))+1, len(images.Data[0].GetList("RepoTags")))
  1024. }
  1025. req, err := http.NewRequest("DELETE", "/images/"+unitTestImageID, nil)
  1026. if err != nil {
  1027. t.Fatal(err)
  1028. }
  1029. r := httptest.NewRecorder()
  1030. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  1031. t.Fatal(err)
  1032. }
  1033. if r.Code != http.StatusConflict {
  1034. t.Fatalf("Expected http status 409-conflict, got %v", r.Code)
  1035. }
  1036. req2, err := http.NewRequest("DELETE", "/images/test:test", nil)
  1037. if err != nil {
  1038. t.Fatal(err)
  1039. }
  1040. r2 := httptest.NewRecorder()
  1041. if err := api.ServeRequest(eng, api.APIVERSION, r2, req2); err != nil {
  1042. t.Fatal(err)
  1043. }
  1044. assertHttpNotError(r2, t)
  1045. if r2.Code != http.StatusOK {
  1046. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  1047. }
  1048. outs := engine.NewTable("Created", 0)
  1049. if _, err := outs.ReadListFrom(r2.Body.Bytes()); err != nil {
  1050. t.Fatal(err)
  1051. }
  1052. if len(outs.Data) != 1 {
  1053. t.Fatalf("Expected %d event (untagged), got %d", 1, len(outs.Data))
  1054. }
  1055. images = getImages(eng, t, false, "")
  1056. if images.Len() != initialImages.Len() {
  1057. t.Errorf("Expected %d image, %d found", initialImages.Len(), images.Len())
  1058. }
  1059. }
  1060. func TestPostContainersCopy(t *testing.T) {
  1061. eng := NewTestEngine(t)
  1062. defer mkRuntimeFromEngine(eng, t).Nuke()
  1063. // Create a container and remove a file
  1064. containerID := createTestContainer(eng,
  1065. &runconfig.Config{
  1066. Image: unitTestImageID,
  1067. Cmd: []string{"touch", "/test.txt"},
  1068. },
  1069. t,
  1070. )
  1071. containerRun(eng, containerID, t)
  1072. r := httptest.NewRecorder()
  1073. var copyData engine.Env
  1074. copyData.Set("Resource", "/test.txt")
  1075. copyData.Set("HostPath", ".")
  1076. jsonData := bytes.NewBuffer(nil)
  1077. if err := copyData.Encode(jsonData); err != nil {
  1078. t.Fatal(err)
  1079. }
  1080. req, err := http.NewRequest("POST", "/containers/"+containerID+"/copy", jsonData)
  1081. if err != nil {
  1082. t.Fatal(err)
  1083. }
  1084. req.Header.Add("Content-Type", "application/json")
  1085. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  1086. t.Fatal(err)
  1087. }
  1088. assertHttpNotError(r, t)
  1089. if r.Code != http.StatusOK {
  1090. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  1091. }
  1092. found := false
  1093. for tarReader := tar.NewReader(r.Body); ; {
  1094. h, err := tarReader.Next()
  1095. if err != nil {
  1096. if err == io.EOF {
  1097. break
  1098. }
  1099. t.Fatal(err)
  1100. }
  1101. if h.Name == "test.txt" {
  1102. found = true
  1103. break
  1104. }
  1105. }
  1106. if !found {
  1107. t.Fatalf("The created test file has not been found in the copied output")
  1108. }
  1109. }
  1110. func TestPostContainersCopyWhenContainerNotFound(t *testing.T) {
  1111. eng := NewTestEngine(t)
  1112. defer mkRuntimeFromEngine(eng, t).Nuke()
  1113. r := httptest.NewRecorder()
  1114. var copyData engine.Env
  1115. copyData.Set("Resource", "/test.txt")
  1116. copyData.Set("HostPath", ".")
  1117. jsonData := bytes.NewBuffer(nil)
  1118. if err := copyData.Encode(jsonData); err != nil {
  1119. t.Fatal(err)
  1120. }
  1121. req, err := http.NewRequest("POST", "/containers/id_not_found/copy", jsonData)
  1122. if err != nil {
  1123. t.Fatal(err)
  1124. }
  1125. req.Header.Add("Content-Type", "application/json")
  1126. if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  1127. t.Fatal(err)
  1128. }
  1129. if r.Code != http.StatusNotFound {
  1130. t.Fatalf("404 expected for id_not_found Container, received %v", r.Code)
  1131. }
  1132. }
  1133. // Mocked types for tests
  1134. type NopConn struct {
  1135. io.ReadCloser
  1136. io.Writer
  1137. }
  1138. func (c *NopConn) LocalAddr() net.Addr { return nil }
  1139. func (c *NopConn) RemoteAddr() net.Addr { return nil }
  1140. func (c *NopConn) SetDeadline(t time.Time) error { return nil }
  1141. func (c *NopConn) SetReadDeadline(t time.Time) error { return nil }
  1142. func (c *NopConn) SetWriteDeadline(t time.Time) error { return nil }
  1143. type hijackTester struct {
  1144. *httptest.ResponseRecorder
  1145. in io.ReadCloser
  1146. out io.Writer
  1147. }
  1148. func (t *hijackTester) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  1149. bufrw := bufio.NewReadWriter(bufio.NewReader(t.in), bufio.NewWriter(t.out))
  1150. conn := &NopConn{
  1151. ReadCloser: t.in,
  1152. Writer: t.out,
  1153. }
  1154. return conn, bufrw, nil
  1155. }