testutil.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. package graphtest // import "github.com/docker/docker/daemon/graphdriver/graphtest"
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math/rand"
  6. "os"
  7. "sort"
  8. "github.com/containerd/continuity/driver"
  9. "github.com/docker/docker/daemon/graphdriver"
  10. "github.com/docker/docker/pkg/archive"
  11. "github.com/docker/docker/pkg/stringid"
  12. )
  13. func randomContent(size int, seed int64) []byte {
  14. s := rand.NewSource(seed)
  15. content := make([]byte, size)
  16. for i := 0; i < len(content); i += 7 {
  17. val := s.Int63()
  18. for j := 0; i+j < len(content) && j < 7; j++ {
  19. content[i+j] = byte(val)
  20. val >>= 8
  21. }
  22. }
  23. return content
  24. }
  25. func addFiles(drv graphdriver.Driver, layer string, seed int64) error {
  26. root, err := drv.Get(layer, "")
  27. if err != nil {
  28. return err
  29. }
  30. defer drv.Put(layer)
  31. if err := driver.WriteFile(root, root.Join(root.Path(), "file-a"), randomContent(64, seed), 0755); err != nil {
  32. return err
  33. }
  34. if err := root.MkdirAll(root.Join(root.Path(), "dir-b"), 0755); err != nil {
  35. return err
  36. }
  37. if err := driver.WriteFile(root, root.Join(root.Path(), "dir-b", "file-b"), randomContent(128, seed+1), 0755); err != nil {
  38. return err
  39. }
  40. return driver.WriteFile(root, root.Join(root.Path(), "file-c"), randomContent(128*128, seed+2), 0755)
  41. }
  42. func checkFile(drv graphdriver.Driver, layer, filename string, content []byte) error {
  43. root, err := drv.Get(layer, "")
  44. if err != nil {
  45. return err
  46. }
  47. defer drv.Put(layer)
  48. fileContent, err := driver.ReadFile(root, root.Join(root.Path(), filename))
  49. if err != nil {
  50. return err
  51. }
  52. if !bytes.Equal(fileContent, content) {
  53. return fmt.Errorf("mismatched file content %v, expecting %v", fileContent, content)
  54. }
  55. return nil
  56. }
  57. func addFile(drv graphdriver.Driver, layer, filename string, content []byte) error {
  58. root, err := drv.Get(layer, "")
  59. if err != nil {
  60. return err
  61. }
  62. defer drv.Put(layer)
  63. return driver.WriteFile(root, root.Join(root.Path(), filename), content, 0755)
  64. }
  65. func addDirectory(drv graphdriver.Driver, layer, dir string) error {
  66. root, err := drv.Get(layer, "")
  67. if err != nil {
  68. return err
  69. }
  70. defer drv.Put(layer)
  71. return root.MkdirAll(root.Join(root.Path(), dir), 0755)
  72. }
  73. func removeAll(drv graphdriver.Driver, layer string, names ...string) error {
  74. root, err := drv.Get(layer, "")
  75. if err != nil {
  76. return err
  77. }
  78. defer drv.Put(layer)
  79. for _, filename := range names {
  80. if err := root.RemoveAll(root.Join(root.Path(), filename)); err != nil {
  81. return err
  82. }
  83. }
  84. return nil
  85. }
  86. func checkFileRemoved(drv graphdriver.Driver, layer, filename string) error {
  87. root, err := drv.Get(layer, "")
  88. if err != nil {
  89. return err
  90. }
  91. defer drv.Put(layer)
  92. if _, err := root.Stat(root.Join(root.Path(), filename)); err == nil {
  93. return fmt.Errorf("file still exists: %s", root.Join(root.Path(), filename))
  94. } else if !os.IsNotExist(err) {
  95. return err
  96. }
  97. return nil
  98. }
  99. func addManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) error {
  100. root, err := drv.Get(layer, "")
  101. if err != nil {
  102. return err
  103. }
  104. defer drv.Put(layer)
  105. for i := 0; i < count; i += 100 {
  106. dir := root.Join(root.Path(), fmt.Sprintf("directory-%d", i))
  107. if err := root.MkdirAll(dir, 0755); err != nil {
  108. return err
  109. }
  110. for j := 0; i+j < count && j < 100; j++ {
  111. file := root.Join(dir, fmt.Sprintf("file-%d", i+j))
  112. if err := driver.WriteFile(root, file, randomContent(64, seed+int64(i+j)), 0755); err != nil {
  113. return err
  114. }
  115. }
  116. }
  117. return nil
  118. }
  119. func changeManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) ([]archive.Change, error) {
  120. root, err := drv.Get(layer, "")
  121. if err != nil {
  122. return nil, err
  123. }
  124. defer drv.Put(layer)
  125. var changes []archive.Change
  126. for i := 0; i < count; i += 100 {
  127. archiveRoot := fmt.Sprintf("/directory-%d", i)
  128. if err := root.MkdirAll(root.Join(root.Path(), archiveRoot), 0755); err != nil {
  129. return nil, err
  130. }
  131. for j := 0; i+j < count && j < 100; j++ {
  132. if j == 0 {
  133. changes = append(changes, archive.Change{
  134. Path: archiveRoot,
  135. Kind: archive.ChangeModify,
  136. })
  137. }
  138. var change archive.Change
  139. switch j % 3 {
  140. // Update file
  141. case 0:
  142. change.Path = root.Join(archiveRoot, fmt.Sprintf("file-%d", i+j))
  143. change.Kind = archive.ChangeModify
  144. if err := driver.WriteFile(root, root.Join(root.Path(), change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil {
  145. return nil, err
  146. }
  147. // Add file
  148. case 1:
  149. change.Path = root.Join(archiveRoot, fmt.Sprintf("file-%d-%d", seed, i+j))
  150. change.Kind = archive.ChangeAdd
  151. if err := driver.WriteFile(root, root.Join(root.Path(), change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil {
  152. return nil, err
  153. }
  154. // Remove file
  155. case 2:
  156. change.Path = root.Join(archiveRoot, fmt.Sprintf("file-%d", i+j))
  157. change.Kind = archive.ChangeDelete
  158. if err := root.Remove(root.Join(root.Path(), change.Path)); err != nil {
  159. return nil, err
  160. }
  161. }
  162. changes = append(changes, change)
  163. }
  164. }
  165. return changes, nil
  166. }
  167. func checkManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) error {
  168. root, err := drv.Get(layer, "")
  169. if err != nil {
  170. return err
  171. }
  172. defer drv.Put(layer)
  173. for i := 0; i < count; i += 100 {
  174. dir := root.Join(root.Path(), fmt.Sprintf("directory-%d", i))
  175. for j := 0; i+j < count && j < 100; j++ {
  176. file := root.Join(dir, fmt.Sprintf("file-%d", i+j))
  177. fileContent, err := driver.ReadFile(root, file)
  178. if err != nil {
  179. return err
  180. }
  181. content := randomContent(64, seed+int64(i+j))
  182. if !bytes.Equal(fileContent, content) {
  183. return fmt.Errorf("mismatched file content %v, expecting %v", fileContent, content)
  184. }
  185. }
  186. }
  187. return nil
  188. }
  189. type changeList []archive.Change
  190. func (c changeList) Less(i, j int) bool {
  191. if c[i].Path == c[j].Path {
  192. return c[i].Kind < c[j].Kind
  193. }
  194. return c[i].Path < c[j].Path
  195. }
  196. func (c changeList) Len() int { return len(c) }
  197. func (c changeList) Swap(i, j int) { c[j], c[i] = c[i], c[j] }
  198. func checkChanges(expected, actual []archive.Change) error {
  199. if len(expected) != len(actual) {
  200. return fmt.Errorf("unexpected number of changes, expected %d, got %d", len(expected), len(actual))
  201. }
  202. sort.Sort(changeList(expected))
  203. sort.Sort(changeList(actual))
  204. for i := range expected {
  205. if expected[i] != actual[i] {
  206. return fmt.Errorf("unexpected change, expecting %v, got %v", expected[i], actual[i])
  207. }
  208. }
  209. return nil
  210. }
  211. func addLayerFiles(drv graphdriver.Driver, layer, parent string, i int) error {
  212. root, err := drv.Get(layer, "")
  213. if err != nil {
  214. return err
  215. }
  216. defer drv.Put(layer)
  217. if err := driver.WriteFile(root, root.Join(root.Path(), "top-id"), []byte(layer), 0755); err != nil {
  218. return err
  219. }
  220. layerDir := root.Join(root.Path(), fmt.Sprintf("layer-%d", i))
  221. if err := root.MkdirAll(layerDir, 0755); err != nil {
  222. return err
  223. }
  224. if err := driver.WriteFile(root, root.Join(layerDir, "layer-id"), []byte(layer), 0755); err != nil {
  225. return err
  226. }
  227. return driver.WriteFile(root, root.Join(layerDir, "parent-id"), []byte(parent), 0755)
  228. }
  229. func addManyLayers(drv graphdriver.Driver, baseLayer string, count int) (string, error) {
  230. lastLayer := baseLayer
  231. for i := 1; i <= count; i++ {
  232. nextLayer := stringid.GenerateRandomID()
  233. if err := drv.Create(nextLayer, lastLayer, nil); err != nil {
  234. return "", err
  235. }
  236. if err := addLayerFiles(drv, nextLayer, lastLayer, i); err != nil {
  237. return "", err
  238. }
  239. lastLayer = nextLayer
  240. }
  241. return lastLayer, nil
  242. }
  243. func checkManyLayers(drv graphdriver.Driver, layer string, count int) error {
  244. root, err := drv.Get(layer, "")
  245. if err != nil {
  246. return err
  247. }
  248. defer drv.Put(layer)
  249. layerIDBytes, err := driver.ReadFile(root, root.Join(root.Path(), "top-id"))
  250. if err != nil {
  251. return err
  252. }
  253. if !bytes.Equal(layerIDBytes, []byte(layer)) {
  254. return fmt.Errorf("mismatched file content %v, expecting %v", layerIDBytes, []byte(layer))
  255. }
  256. for i := count; i > 0; i-- {
  257. layerDir := root.Join(root.Path(), fmt.Sprintf("layer-%d", i))
  258. thisLayerIDBytes, err := driver.ReadFile(root, root.Join(layerDir, "layer-id"))
  259. if err != nil {
  260. return err
  261. }
  262. if !bytes.Equal(thisLayerIDBytes, layerIDBytes) {
  263. return fmt.Errorf("mismatched file content %v, expecting %v", thisLayerIDBytes, layerIDBytes)
  264. }
  265. layerIDBytes, err = driver.ReadFile(root, root.Join(layerDir, "parent-id"))
  266. if err != nil {
  267. return err
  268. }
  269. }
  270. return nil
  271. }
  272. // readDir reads a directory just like driver.ReadDir()
  273. // then hides specific files (currently "lost+found")
  274. // so the tests don't "see" it
  275. func readDir(r driver.Driver, dir string) ([]os.FileInfo, error) {
  276. a, err := driver.ReadDir(r, dir)
  277. if err != nil {
  278. return nil, err
  279. }
  280. b := a[:0]
  281. for _, x := range a {
  282. if x.Name() != "lost+found" { // ext4 always have this dir
  283. b = append(b, x)
  284. }
  285. }
  286. return b, nil
  287. }