testutil.go 8.3 KB

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