graph_test.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package docker
  2. import (
  3. "errors"
  4. "github.com/docker/docker/daemon/graphdriver"
  5. "github.com/docker/docker/dockerversion"
  6. "github.com/docker/docker/graph"
  7. "github.com/docker/docker/image"
  8. "github.com/docker/docker/pkg/archive"
  9. "github.com/docker/docker/utils"
  10. "io"
  11. "io/ioutil"
  12. "os"
  13. "path"
  14. "testing"
  15. "time"
  16. )
  17. func TestMount(t *testing.T) {
  18. graph, driver := tempGraph(t)
  19. defer os.RemoveAll(graph.Root)
  20. defer driver.Cleanup()
  21. archive, err := fakeTar()
  22. if err != nil {
  23. t.Fatal(err)
  24. }
  25. image, err := graph.Create(archive, "", "", "Testing", "", nil, nil)
  26. if err != nil {
  27. t.Fatal(err)
  28. }
  29. tmp, err := ioutil.TempDir("", "docker-test-graph-mount-")
  30. if err != nil {
  31. t.Fatal(err)
  32. }
  33. defer os.RemoveAll(tmp)
  34. rootfs := path.Join(tmp, "rootfs")
  35. if err := os.MkdirAll(rootfs, 0700); err != nil {
  36. t.Fatal(err)
  37. }
  38. rw := path.Join(tmp, "rw")
  39. if err := os.MkdirAll(rw, 0700); err != nil {
  40. t.Fatal(err)
  41. }
  42. if _, err := driver.Get(image.ID, ""); err != nil {
  43. t.Fatal(err)
  44. }
  45. }
  46. func TestInit(t *testing.T) {
  47. graph, _ := tempGraph(t)
  48. defer nukeGraph(graph)
  49. // Root should exist
  50. if _, err := os.Stat(graph.Root); err != nil {
  51. t.Fatal(err)
  52. }
  53. // Map() should be empty
  54. if l, err := graph.Map(); err != nil {
  55. t.Fatal(err)
  56. } else if len(l) != 0 {
  57. t.Fatalf("len(Map()) should return %d, not %d", 0, len(l))
  58. }
  59. }
  60. // Test that Register can be interrupted cleanly without side effects
  61. func TestInterruptedRegister(t *testing.T) {
  62. graph, _ := tempGraph(t)
  63. defer nukeGraph(graph)
  64. badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data
  65. image := &image.Image{
  66. ID: utils.GenerateRandomID(),
  67. Comment: "testing",
  68. Created: time.Now(),
  69. }
  70. w.CloseWithError(errors.New("But I'm not a tarball!")) // (Nobody's perfect, darling)
  71. graph.Register(image, badArchive)
  72. if _, err := graph.Get(image.ID); err == nil {
  73. t.Fatal("Image should not exist after Register is interrupted")
  74. }
  75. // Registering the same image again should succeed if the first register was interrupted
  76. goodArchive, err := fakeTar()
  77. if err != nil {
  78. t.Fatal(err)
  79. }
  80. if err := graph.Register(image, goodArchive); err != nil {
  81. t.Fatal(err)
  82. }
  83. }
  84. // FIXME: Do more extensive tests (ex: create multiple, delete, recreate;
  85. // create multiple, check the amount of images and paths, etc..)
  86. func TestGraphCreate(t *testing.T) {
  87. graph, _ := tempGraph(t)
  88. defer nukeGraph(graph)
  89. archive, err := fakeTar()
  90. if err != nil {
  91. t.Fatal(err)
  92. }
  93. img, err := graph.Create(archive, "", "", "Testing", "", nil, nil)
  94. if err != nil {
  95. t.Fatal(err)
  96. }
  97. if err := utils.ValidateID(img.ID); err != nil {
  98. t.Fatal(err)
  99. }
  100. if img.Comment != "Testing" {
  101. t.Fatalf("Wrong comment: should be '%s', not '%s'", "Testing", img.Comment)
  102. }
  103. if img.DockerVersion != dockerversion.VERSION {
  104. t.Fatalf("Wrong docker_version: should be '%s', not '%s'", dockerversion.VERSION, img.DockerVersion)
  105. }
  106. images, err := graph.Map()
  107. if err != nil {
  108. t.Fatal(err)
  109. } else if l := len(images); l != 1 {
  110. t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l)
  111. }
  112. if images[img.ID] == nil {
  113. t.Fatalf("Could not find image with id %s", img.ID)
  114. }
  115. }
  116. func TestRegister(t *testing.T) {
  117. graph, _ := tempGraph(t)
  118. defer nukeGraph(graph)
  119. archive, err := fakeTar()
  120. if err != nil {
  121. t.Fatal(err)
  122. }
  123. image := &image.Image{
  124. ID: utils.GenerateRandomID(),
  125. Comment: "testing",
  126. Created: time.Now(),
  127. }
  128. err = graph.Register(image, archive)
  129. if err != nil {
  130. t.Fatal(err)
  131. }
  132. if images, err := graph.Map(); err != nil {
  133. t.Fatal(err)
  134. } else if l := len(images); l != 1 {
  135. t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l)
  136. }
  137. if resultImg, err := graph.Get(image.ID); err != nil {
  138. t.Fatal(err)
  139. } else {
  140. if resultImg.ID != image.ID {
  141. t.Fatalf("Wrong image ID. Should be '%s', not '%s'", image.ID, resultImg.ID)
  142. }
  143. if resultImg.Comment != image.Comment {
  144. t.Fatalf("Wrong image comment. Should be '%s', not '%s'", image.Comment, resultImg.Comment)
  145. }
  146. }
  147. }
  148. // Test that an image can be deleted by its shorthand prefix
  149. func TestDeletePrefix(t *testing.T) {
  150. graph, _ := tempGraph(t)
  151. defer nukeGraph(graph)
  152. img := createTestImage(graph, t)
  153. if err := graph.Delete(utils.TruncateID(img.ID)); err != nil {
  154. t.Fatal(err)
  155. }
  156. assertNImages(graph, t, 0)
  157. }
  158. func createTestImage(graph *graph.Graph, t *testing.T) *image.Image {
  159. archive, err := fakeTar()
  160. if err != nil {
  161. t.Fatal(err)
  162. }
  163. img, err := graph.Create(archive, "", "", "Test image", "", nil, nil)
  164. if err != nil {
  165. t.Fatal(err)
  166. }
  167. return img
  168. }
  169. func TestDelete(t *testing.T) {
  170. graph, _ := tempGraph(t)
  171. defer nukeGraph(graph)
  172. archive, err := fakeTar()
  173. if err != nil {
  174. t.Fatal(err)
  175. }
  176. assertNImages(graph, t, 0)
  177. img, err := graph.Create(archive, "", "", "Bla bla", "", nil, nil)
  178. if err != nil {
  179. t.Fatal(err)
  180. }
  181. assertNImages(graph, t, 1)
  182. if err := graph.Delete(img.ID); err != nil {
  183. t.Fatal(err)
  184. }
  185. assertNImages(graph, t, 0)
  186. archive, err = fakeTar()
  187. if err != nil {
  188. t.Fatal(err)
  189. }
  190. // Test 2 create (same name) / 1 delete
  191. img1, err := graph.Create(archive, "", "", "Testing", "", nil, nil)
  192. if err != nil {
  193. t.Fatal(err)
  194. }
  195. archive, err = fakeTar()
  196. if err != nil {
  197. t.Fatal(err)
  198. }
  199. if _, err = graph.Create(archive, "", "", "Testing", "", nil, nil); err != nil {
  200. t.Fatal(err)
  201. }
  202. assertNImages(graph, t, 2)
  203. if err := graph.Delete(img1.ID); err != nil {
  204. t.Fatal(err)
  205. }
  206. assertNImages(graph, t, 1)
  207. // Test delete wrong name
  208. if err := graph.Delete("Not_foo"); err == nil {
  209. t.Fatalf("Deleting wrong ID should return an error")
  210. }
  211. assertNImages(graph, t, 1)
  212. archive, err = fakeTar()
  213. if err != nil {
  214. t.Fatal(err)
  215. }
  216. // Test delete twice (pull -> rm -> pull -> rm)
  217. if err := graph.Register(img1, archive); err != nil {
  218. t.Fatal(err)
  219. }
  220. if err := graph.Delete(img1.ID); err != nil {
  221. t.Fatal(err)
  222. }
  223. assertNImages(graph, t, 1)
  224. }
  225. func TestByParent(t *testing.T) {
  226. archive1, _ := fakeTar()
  227. archive2, _ := fakeTar()
  228. archive3, _ := fakeTar()
  229. graph, _ := tempGraph(t)
  230. defer nukeGraph(graph)
  231. parentImage := &image.Image{
  232. ID: utils.GenerateRandomID(),
  233. Comment: "parent",
  234. Created: time.Now(),
  235. Parent: "",
  236. }
  237. childImage1 := &image.Image{
  238. ID: utils.GenerateRandomID(),
  239. Comment: "child1",
  240. Created: time.Now(),
  241. Parent: parentImage.ID,
  242. }
  243. childImage2 := &image.Image{
  244. ID: utils.GenerateRandomID(),
  245. Comment: "child2",
  246. Created: time.Now(),
  247. Parent: parentImage.ID,
  248. }
  249. _ = graph.Register(parentImage, archive1)
  250. _ = graph.Register(childImage1, archive2)
  251. _ = graph.Register(childImage2, archive3)
  252. byParent, err := graph.ByParent()
  253. if err != nil {
  254. t.Fatal(err)
  255. }
  256. numChildren := len(byParent[parentImage.ID])
  257. if numChildren != 2 {
  258. t.Fatalf("Expected 2 children, found %d", numChildren)
  259. }
  260. }
  261. /*
  262. * HELPER FUNCTIONS
  263. */
  264. func assertNImages(graph *graph.Graph, t *testing.T, n int) {
  265. if images, err := graph.Map(); err != nil {
  266. t.Fatal(err)
  267. } else if actualN := len(images); actualN != n {
  268. t.Fatalf("Expected %d images, found %d", n, actualN)
  269. }
  270. }
  271. func tempGraph(t *testing.T) (*graph.Graph, graphdriver.Driver) {
  272. tmp, err := ioutil.TempDir("", "docker-graph-")
  273. if err != nil {
  274. t.Fatal(err)
  275. }
  276. driver, err := graphdriver.New(tmp, nil)
  277. if err != nil {
  278. t.Fatal(err)
  279. }
  280. graph, err := graph.NewGraph(tmp, driver)
  281. if err != nil {
  282. t.Fatal(err)
  283. }
  284. return graph, driver
  285. }
  286. func nukeGraph(graph *graph.Graph) {
  287. graph.Driver().Cleanup()
  288. os.RemoveAll(graph.Root)
  289. }
  290. func testArchive(t *testing.T) archive.Archive {
  291. archive, err := fakeTar()
  292. if err != nil {
  293. t.Fatal(err)
  294. }
  295. return archive
  296. }