graph_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. package docker
  2. import (
  3. "archive/tar"
  4. "bytes"
  5. "errors"
  6. "io"
  7. "io/ioutil"
  8. "os"
  9. "path"
  10. "testing"
  11. "time"
  12. )
  13. func TestInit(t *testing.T) {
  14. graph := tempGraph(t)
  15. defer os.RemoveAll(graph.Root)
  16. // Root should exist
  17. if _, err := os.Stat(graph.Root); err != nil {
  18. t.Fatal(err)
  19. }
  20. // All() should be empty
  21. if l, err := graph.All(); err != nil {
  22. t.Fatal(err)
  23. } else if len(l) != 0 {
  24. t.Fatalf("List() should return %d, not %d", 0, len(l))
  25. }
  26. }
  27. // Test that Register can be interrupted cleanly without side effects
  28. func TestInterruptedRegister(t *testing.T) {
  29. graph := tempGraph(t)
  30. defer os.RemoveAll(graph.Root)
  31. badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data
  32. image := &Image{
  33. Id: GenerateId(),
  34. Comment: "testing",
  35. Created: time.Now(),
  36. }
  37. go graph.Register(badArchive, image)
  38. time.Sleep(200 * time.Millisecond)
  39. w.CloseWithError(errors.New("But I'm not a tarball!")) // (Nobody's perfect, darling)
  40. if _, err := graph.Get(image.Id); err == nil {
  41. t.Fatal("Image should not exist after Register is interrupted")
  42. }
  43. // Registering the same image again should succeed if the first register was interrupted
  44. goodArchive, err := fakeTar()
  45. if err != nil {
  46. t.Fatal(err)
  47. }
  48. if err := graph.Register(goodArchive, image); err != nil {
  49. t.Fatal(err)
  50. }
  51. }
  52. // FIXME: Do more extensive tests (ex: create multiple, delete, recreate;
  53. // create multiple, check the amount of images and paths, etc..)
  54. func TestGraphCreate(t *testing.T) {
  55. graph := tempGraph(t)
  56. defer os.RemoveAll(graph.Root)
  57. archive, err := fakeTar()
  58. if err != nil {
  59. t.Fatal(err)
  60. }
  61. image, err := graph.Create(archive, nil, "Testing", "", nil)
  62. if err != nil {
  63. t.Fatal(err)
  64. }
  65. if err := ValidateId(image.Id); err != nil {
  66. t.Fatal(err)
  67. }
  68. if image.Comment != "Testing" {
  69. t.Fatalf("Wrong comment: should be '%s', not '%s'", "Testing", image.Comment)
  70. }
  71. if image.DockerVersion != VERSION {
  72. t.Fatalf("Wrong docker_version: should be '%s', not '%s'", VERSION, image.DockerVersion)
  73. }
  74. if images, err := graph.All(); err != nil {
  75. t.Fatal(err)
  76. } else if l := len(images); l != 1 {
  77. t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l)
  78. }
  79. }
  80. func TestRegister(t *testing.T) {
  81. graph := tempGraph(t)
  82. defer os.RemoveAll(graph.Root)
  83. archive, err := fakeTar()
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. image := &Image{
  88. Id: GenerateId(),
  89. Comment: "testing",
  90. Created: time.Now(),
  91. }
  92. err = graph.Register(archive, image)
  93. if err != nil {
  94. t.Fatal(err)
  95. }
  96. if images, err := graph.All(); err != nil {
  97. t.Fatal(err)
  98. } else if l := len(images); l != 1 {
  99. t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l)
  100. }
  101. if resultImg, err := graph.Get(image.Id); err != nil {
  102. t.Fatal(err)
  103. } else {
  104. if resultImg.Id != image.Id {
  105. t.Fatalf("Wrong image ID. Should be '%s', not '%s'", image.Id, resultImg.Id)
  106. }
  107. if resultImg.Comment != image.Comment {
  108. t.Fatalf("Wrong image comment. Should be '%s', not '%s'", image.Comment, resultImg.Comment)
  109. }
  110. }
  111. }
  112. func TestMount(t *testing.T) {
  113. graph := tempGraph(t)
  114. defer os.RemoveAll(graph.Root)
  115. archive, err := fakeTar()
  116. if err != nil {
  117. t.Fatal(err)
  118. }
  119. image, err := graph.Create(archive, nil, "Testing", "", nil)
  120. if err != nil {
  121. t.Fatal(err)
  122. }
  123. tmp, err := ioutil.TempDir("", "docker-test-graph-mount-")
  124. if err != nil {
  125. t.Fatal(err)
  126. }
  127. defer os.RemoveAll(tmp)
  128. rootfs := path.Join(tmp, "rootfs")
  129. if err := os.MkdirAll(rootfs, 0700); err != nil {
  130. t.Fatal(err)
  131. }
  132. rw := path.Join(tmp, "rw")
  133. if err := os.MkdirAll(rw, 0700); err != nil {
  134. t.Fatal(err)
  135. }
  136. if err := image.Mount(rootfs, rw); err != nil {
  137. t.Fatal(err)
  138. }
  139. // FIXME: test for mount contents
  140. defer func() {
  141. if err := Unmount(rootfs); err != nil {
  142. t.Error(err)
  143. }
  144. }()
  145. }
  146. // Test that an image can be deleted by its shorthand prefix
  147. func TestDeletePrefix(t *testing.T) {
  148. graph := tempGraph(t)
  149. defer os.RemoveAll(graph.Root)
  150. img := createTestImage(graph, t)
  151. if err := graph.Delete(TruncateId(img.Id)); err != nil {
  152. t.Fatal(err)
  153. }
  154. assertNImages(graph, t, 0)
  155. }
  156. func createTestImage(graph *Graph, t *testing.T) *Image {
  157. archive, err := fakeTar()
  158. if err != nil {
  159. t.Fatal(err)
  160. }
  161. img, err := graph.Create(archive, nil, "Test image", "", nil)
  162. if err != nil {
  163. t.Fatal(err)
  164. }
  165. return img
  166. }
  167. func TestDelete(t *testing.T) {
  168. graph := tempGraph(t)
  169. defer os.RemoveAll(graph.Root)
  170. archive, err := fakeTar()
  171. if err != nil {
  172. t.Fatal(err)
  173. }
  174. assertNImages(graph, t, 0)
  175. img, err := graph.Create(archive, nil, "Bla bla", "", nil)
  176. if err != nil {
  177. t.Fatal(err)
  178. }
  179. assertNImages(graph, t, 1)
  180. if err := graph.Delete(img.Id); err != nil {
  181. t.Fatal(err)
  182. }
  183. assertNImages(graph, t, 0)
  184. // Test 2 create (same name) / 1 delete
  185. img1, err := graph.Create(archive, nil, "Testing", "", nil)
  186. if err != nil {
  187. t.Fatal(err)
  188. }
  189. if _, err = graph.Create(archive, nil, "Testing", "", nil); err != nil {
  190. t.Fatal(err)
  191. }
  192. assertNImages(graph, t, 2)
  193. if err := graph.Delete(img1.Id); err != nil {
  194. t.Fatal(err)
  195. }
  196. assertNImages(graph, t, 1)
  197. // Test delete wrong name
  198. if err := graph.Delete("Not_foo"); err == nil {
  199. t.Fatalf("Deleting wrong ID should return an error")
  200. }
  201. assertNImages(graph, t, 1)
  202. // Test delete twice (pull -> rm -> pull -> rm)
  203. if err := graph.Register(archive, img1); err != nil {
  204. t.Fatal(err)
  205. }
  206. if err := graph.Delete(img1.Id); err != nil {
  207. t.Fatal(err)
  208. }
  209. assertNImages(graph, t, 1)
  210. }
  211. func assertNImages(graph *Graph, t *testing.T, n int) {
  212. if images, err := graph.All(); err != nil {
  213. t.Fatal(err)
  214. } else if actualN := len(images); actualN != n {
  215. t.Fatalf("Expected %d images, found %d", n, actualN)
  216. }
  217. }
  218. /*
  219. * HELPER FUNCTIONS
  220. */
  221. func tempGraph(t *testing.T) *Graph {
  222. tmp, err := ioutil.TempDir("", "docker-graph-")
  223. if err != nil {
  224. t.Fatal(err)
  225. }
  226. graph, err := NewGraph(tmp)
  227. if err != nil {
  228. t.Fatal(err)
  229. }
  230. return graph
  231. }
  232. func testArchive(t *testing.T) Archive {
  233. archive, err := fakeTar()
  234. if err != nil {
  235. t.Fatal(err)
  236. }
  237. return archive
  238. }
  239. func fakeTar() (io.Reader, error) {
  240. content := []byte("Hello world!\n")
  241. buf := new(bytes.Buffer)
  242. tw := tar.NewWriter(buf)
  243. for _, name := range []string{"/etc/postgres/postgres.conf", "/etc/passwd", "/var/log/postgres/postgres.conf"} {
  244. hdr := new(tar.Header)
  245. hdr.Size = int64(len(content))
  246. hdr.Name = name
  247. if err := tw.WriteHeader(hdr); err != nil {
  248. return nil, err
  249. }
  250. tw.Write([]byte(content))
  251. }
  252. tw.Close()
  253. return buf, nil
  254. }