api_test.go 33 KB

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