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