github.com/thy00/storage@v1.12.8/drivers/graphtest/graphtest_unix.go (about) 1 // +build linux freebsd solaris 2 3 package graphtest 4 5 import ( 6 "bytes" 7 "fmt" 8 "io/ioutil" 9 "math/rand" 10 "os" 11 "path" 12 "path/filepath" 13 "reflect" 14 "testing" 15 "unsafe" 16 17 "github.com/containers/storage/drivers" 18 "github.com/containers/storage/pkg/archive" 19 "github.com/containers/storage/pkg/stringid" 20 "github.com/docker/go-units" 21 "github.com/pkg/errors" 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 "golang.org/x/sys/unix" 25 ) 26 27 var ( 28 drv *Driver 29 ) 30 31 // Driver conforms to graphdriver.Driver interface and 32 // contains information such as root and reference count of the number of clients using it. 33 // This helps in testing drivers added into the framework. 34 type Driver struct { 35 graphdriver.Driver 36 root string 37 refCount int 38 } 39 40 func newDriver(t testing.TB, name string, options []string) *Driver { 41 root, err := ioutil.TempDir("", "storage-graphtest-") 42 require.NoError(t, err) 43 44 require.NoError(t, os.MkdirAll(root, 0755)) 45 d, err := graphdriver.GetDriver(name, graphdriver.Options{DriverOptions: options, Root: root}) 46 if err != nil { 47 t.Logf("graphdriver: %v\n", err) 48 cause := errors.Cause(err) 49 if cause == graphdriver.ErrNotSupported || cause == graphdriver.ErrPrerequisites || cause == graphdriver.ErrIncompatibleFS { 50 t.Skipf("Driver %s not supported", name) 51 } 52 t.Fatal(err) 53 } 54 return &Driver{d, root, 1} 55 } 56 57 func cleanup(t testing.TB, d *Driver) { 58 if err := drv.Cleanup(); err != nil { 59 t.Fatal(err) 60 } 61 os.RemoveAll(d.root) 62 } 63 64 // GetDriver create a new driver with given name or return an existing driver with the name updating the reference count. 65 func GetDriver(t testing.TB, name string, options ...string) graphdriver.Driver { 66 if drv == nil { 67 drv = newDriver(t, name, options) 68 } else { 69 drv.refCount++ 70 } 71 return drv 72 } 73 74 // PutDriver removes the driver if it is no longer used and updates the reference count. 75 func PutDriver(t testing.TB) { 76 if drv == nil { 77 t.Skip("No driver to put!") 78 } 79 drv.refCount-- 80 if drv.refCount == 0 { 81 cleanup(t, drv) 82 drv = nil 83 } 84 } 85 86 // DriverTestCreateEmpty creates a new image and verifies it is empty and the right metadata 87 func DriverTestCreateEmpty(t testing.TB, drivername string, driverOptions ...string) { 88 driver := GetDriver(t, drivername, driverOptions...) 89 defer PutDriver(t) 90 91 err := driver.Create("empty", "", nil) 92 require.NoError(t, err) 93 94 defer func() { 95 require.NoError(t, driver.Remove("empty")) 96 }() 97 98 if !driver.Exists("empty") { 99 t.Fatal("Newly created image doesn't exist") 100 } 101 102 dir, err := driver.Get("empty", graphdriver.MountOpts{}) 103 require.NoError(t, err) 104 105 verifyFile(t, dir, 0755|os.ModeDir, 0, 0) 106 107 // Verify that the directory is empty 108 fis, err := readDir(dir) 109 require.NoError(t, err) 110 assert.Len(t, fis, 0) 111 112 driver.Put("empty") 113 } 114 115 // DriverTestCreateBase create a base driver and verify. 116 func DriverTestCreateBase(t testing.TB, drivername string, driverOptions ...string) { 117 driver := GetDriver(t, drivername, driverOptions...) 118 defer PutDriver(t) 119 120 createBase(t, driver, "Base") 121 defer func() { 122 require.NoError(t, driver.Remove("Base")) 123 }() 124 verifyBase(t, driver, "Base") 125 } 126 127 // DriverTestCreateSnap Create a driver and snap and verify. 128 func DriverTestCreateSnap(t testing.TB, drivername string, driverOptions ...string) { 129 driver := GetDriver(t, drivername, driverOptions...) 130 defer PutDriver(t) 131 132 createBase(t, driver, "Base") 133 defer func() { 134 require.NoError(t, driver.Remove("Base")) 135 }() 136 137 err := driver.Create("Snap", "Base", nil) 138 require.NoError(t, err) 139 defer func() { 140 require.NoError(t, driver.Remove("Snap")) 141 }() 142 143 verifyBase(t, driver, "Snap") 144 } 145 146 // DriverTestCreateFromTemplate Create a driver and template of a snap and verifies its 147 // contents. 148 func DriverTestCreateFromTemplate(t testing.TB, drivername string, driverOptions ...string) { 149 driver := GetDriver(t, drivername, driverOptions...) 150 defer PutDriver(t) 151 152 createBase(t, driver, "Base") 153 defer func() { 154 require.NoError(t, driver.Remove("Base")) 155 }() 156 157 err := driver.Create("Snap", "Base", nil) 158 require.NoError(t, err) 159 defer func() { 160 require.NoError(t, driver.Remove("Snap")) 161 }() 162 163 content := []byte("test content") 164 if err := addFile(driver, "Snap", "testfile.txt", content); err != nil { 165 t.Fatal(err) 166 } 167 168 err = driver.CreateFromTemplate("FromTemplate", "Snap", nil, "Base", nil, nil, true) 169 require.NoError(t, err) 170 defer func() { 171 require.NoError(t, driver.Remove("FromTemplate")) 172 }() 173 174 err = driver.CreateFromTemplate("ROFromTemplate", "Snap", nil, "Base", nil, nil, false) 175 require.NoError(t, err) 176 defer func() { 177 require.NoError(t, driver.Remove("ROFromTemplate")) 178 }() 179 180 noChanges := []archive.Change{} 181 182 changes, err := driver.Changes("FromTemplate", nil, "Snap", nil, "") 183 if err != nil { 184 t.Fatal(err) 185 } 186 if err = checkChanges(noChanges, changes); err != nil { 187 t.Fatal(err) 188 } 189 190 changes, err = driver.Changes("ROFromTemplate", nil, "Snap", nil, "") 191 if err != nil { 192 t.Fatal(err) 193 } 194 if err = checkChanges(noChanges, changes); err != nil { 195 t.Fatal(err) 196 } 197 198 if err := checkFile(driver, "FromTemplate", "testfile.txt", content); err != nil { 199 t.Fatal(err) 200 } 201 if err := checkFile(driver, "ROFromTemplate", "testfile.txt", content); err != nil { 202 t.Fatal(err) 203 } 204 if err := checkFile(driver, "Snap", "testfile.txt", content); err != nil { 205 t.Fatal(err) 206 } 207 208 expectedChanges := []archive.Change{{ 209 Path: "/testfile.txt", 210 Kind: archive.ChangeAdd, 211 }} 212 213 changes, err = driver.Changes("Snap", nil, "Base", nil, "") 214 if err != nil { 215 t.Fatal(err) 216 } 217 if err = checkChanges(expectedChanges, changes); err != nil { 218 t.Fatal(err) 219 } 220 221 changes, err = driver.Changes("FromTemplate", nil, "Base", nil, "") 222 if err != nil { 223 t.Fatal(err) 224 } 225 if err = checkChanges(expectedChanges, changes); err != nil { 226 t.Fatal(err) 227 } 228 229 changes, err = driver.Changes("ROFromTemplate", nil, "Base", nil, "") 230 if err != nil { 231 t.Fatal(err) 232 } 233 if err = checkChanges(expectedChanges, changes); err != nil { 234 t.Fatal(err) 235 } 236 237 verifyBase(t, driver, "Base") 238 } 239 240 // DriverTestDeepLayerRead reads a file from a lower layer under a given number of layers 241 func DriverTestDeepLayerRead(t testing.TB, layerCount int, drivername string, driverOptions ...string) { 242 driver := GetDriver(t, drivername, driverOptions...) 243 defer PutDriver(t) 244 245 base := stringid.GenerateRandomID() 246 if err := driver.Create(base, "", nil); err != nil { 247 t.Fatal(err) 248 } 249 250 content := []byte("test content") 251 if err := addFile(driver, base, "testfile.txt", content); err != nil { 252 t.Fatal(err) 253 } 254 255 topLayer, err := addManyLayers(driver, base, layerCount) 256 if err != nil { 257 t.Fatal(err) 258 } 259 260 err = checkManyLayers(driver, topLayer, layerCount) 261 if err != nil { 262 t.Fatal(err) 263 } 264 265 if err := checkFile(driver, topLayer, "testfile.txt", content); err != nil { 266 t.Fatal(err) 267 } 268 } 269 270 // DriverTestDiffApply tests diffing and applying produces the same layer 271 func DriverTestDiffApply(t testing.TB, fileCount int, drivername string, driverOptions ...string) { 272 driver := GetDriver(t, drivername, driverOptions...) 273 defer PutDriver(t) 274 base := stringid.GenerateRandomID() 275 upper := stringid.GenerateRandomID() 276 deleteFile := "file-remove.txt" 277 deleteFileContent := []byte("This file should get removed in upper!") 278 deleteDir := "var/lib" 279 280 if err := driver.Create(base, "", nil); err != nil { 281 t.Fatal(err) 282 } 283 284 if err := addManyFiles(driver, base, fileCount, 3); err != nil { 285 t.Fatal(err) 286 } 287 288 if err := addFile(driver, base, deleteFile, deleteFileContent); err != nil { 289 t.Fatal(err) 290 } 291 292 if err := addDirectory(driver, base, deleteDir); err != nil { 293 t.Fatal(err) 294 } 295 296 if err := driver.Create(upper, base, nil); err != nil { 297 t.Fatal(err) 298 } 299 300 if err := addManyFiles(driver, upper, fileCount, 6); err != nil { 301 t.Fatal(err) 302 } 303 304 if err := removeAll(driver, upper, deleteFile, deleteDir); err != nil { 305 t.Fatal(err) 306 } 307 308 diffSize, err := driver.DiffSize(upper, nil, "", nil, "") 309 if err != nil { 310 t.Fatal(err) 311 } 312 313 diff := stringid.GenerateRandomID() 314 if err := driver.Create(diff, base, nil); err != nil { 315 t.Fatal(err) 316 } 317 318 if err := checkManyFiles(driver, diff, fileCount, 3); err != nil { 319 t.Fatal(err) 320 } 321 322 if err := checkFile(driver, diff, deleteFile, deleteFileContent); err != nil { 323 t.Fatal(err) 324 } 325 326 arch, err := driver.Diff(upper, nil, base, nil, "") 327 if err != nil { 328 t.Fatal(err) 329 } 330 331 buf := bytes.NewBuffer(nil) 332 if _, err := buf.ReadFrom(arch); err != nil { 333 t.Fatal(err) 334 } 335 if err := arch.Close(); err != nil { 336 t.Fatal(err) 337 } 338 339 applyDiffSize, err := driver.ApplyDiff(diff, nil, base, "", bytes.NewReader(buf.Bytes())) 340 if err != nil { 341 t.Fatal(err) 342 } 343 344 if applyDiffSize != diffSize { 345 t.Fatalf("Apply diff size different, got %d, expected %d", applyDiffSize, diffSize) 346 } 347 348 if err := checkManyFiles(driver, diff, fileCount, 6); err != nil { 349 t.Fatal(err) 350 } 351 352 if err := checkFileRemoved(driver, diff, deleteFile); err != nil { 353 t.Fatal(err) 354 } 355 356 if err := checkFileRemoved(driver, diff, deleteDir); err != nil { 357 t.Fatal(err) 358 } 359 } 360 361 // DriverTestChanges tests computed changes on a layer matches changes made 362 func DriverTestChanges(t testing.TB, drivername string, driverOptions ...string) { 363 driver := GetDriver(t, drivername, driverOptions...) 364 defer PutDriver(t) 365 base := stringid.GenerateRandomID() 366 upper := stringid.GenerateRandomID() 367 if err := driver.Create(base, "", nil); err != nil { 368 t.Fatal(err) 369 } 370 371 if err := addManyFiles(driver, base, 20, 3); err != nil { 372 t.Fatal(err) 373 } 374 375 if err := driver.Create(upper, base, nil); err != nil { 376 t.Fatal(err) 377 } 378 379 expectedChanges, err := changeManyFiles(driver, upper, 20, 6) 380 if err != nil { 381 t.Fatal(err) 382 } 383 384 changes, err := driver.Changes(upper, nil, base, nil, "") 385 if err != nil { 386 t.Fatal(err) 387 } 388 389 if err = checkChanges(expectedChanges, changes); err != nil { 390 t.Fatal(err) 391 } 392 } 393 394 func writeRandomFile(path string, size uint64) error { 395 buf := make([]int64, size/8) 396 397 r := rand.NewSource(0) 398 for i := range buf { 399 buf[i] = r.Int63() 400 } 401 402 // Cast to []byte 403 header := *(*reflect.SliceHeader)(unsafe.Pointer(&buf)) 404 header.Len *= 8 405 header.Cap *= 8 406 data := *(*[]byte)(unsafe.Pointer(&header)) 407 408 return ioutil.WriteFile(path, data, 0700) 409 } 410 411 // DriverTestSetQuota Create a driver and test setting quota. 412 func DriverTestSetQuota(t *testing.T, drivername string) { 413 driver := GetDriver(t, drivername) 414 defer PutDriver(t) 415 416 createBase(t, driver, "Base") 417 createOpts := &graphdriver.CreateOpts{} 418 createOpts.StorageOpt = make(map[string]string, 1) 419 createOpts.StorageOpt["size"] = "50M" 420 if err := driver.Create("zfsTest", "Base", createOpts); err != nil { 421 t.Fatal(err) 422 } 423 424 mountPath, err := driver.Get("zfsTest", graphdriver.MountOpts{}) 425 if err != nil { 426 t.Fatal(err) 427 } 428 429 quota := uint64(50 * units.MiB) 430 err = writeRandomFile(path.Join(mountPath, "file"), quota*2) 431 if pathError, ok := err.(*os.PathError); ok && pathError.Err != unix.EDQUOT { 432 t.Fatalf("expect write() to fail with %v, got %v", unix.EDQUOT, err) 433 } 434 435 } 436 437 // DriverTestEcho tests that we can diff a layer correctly, focusing on trouble spots that NaiveDiff doesn't have 438 func DriverTestEcho(t testing.TB, drivername string, driverOptions ...string) { 439 driver := GetDriver(t, drivername, driverOptions...) 440 defer PutDriver(t) 441 var err error 442 var root string 443 components := 10 444 445 for depth := 0; depth < components; depth++ { 446 base := stringid.GenerateRandomID() 447 second := stringid.GenerateRandomID() 448 third := stringid.GenerateRandomID() 449 450 if err := driver.Create(base, "", nil); err != nil { 451 t.Fatal(err) 452 } 453 454 if root, err = driver.Get(base, graphdriver.MountOpts{}); err != nil { 455 t.Fatal(err) 456 } 457 458 paths := []string{} 459 path := "/" 460 expectedChanges := []archive.Change{} 461 for i := 0; i < components-1; i++ { 462 path = filepath.Join(path, fmt.Sprintf("subdir%d", i+1)) 463 paths = append(paths, path) 464 if err = os.Mkdir(filepath.Join(root, path), 0700); err != nil { 465 t.Fatal(err) 466 } 467 expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeAdd, Path: path}) 468 } 469 path = filepath.Join(path, "file") 470 paths = append(paths, path) 471 if err = ioutil.WriteFile(filepath.Join(root, path), randomContent(128, int64(depth)), 0600); err != nil { 472 t.Fatal(err) 473 } 474 expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeAdd, Path: path}) 475 476 changes, err := driver.Changes(base, nil, "", nil, "") 477 if err != nil { 478 t.Fatal(err) 479 } 480 481 if err = checkChanges(expectedChanges, changes); err != nil { 482 t.Fatal(err) 483 } 484 485 if err := driver.Create(second, base, nil); err != nil { 486 t.Fatal(err) 487 } 488 489 if root, err = driver.Get(second, graphdriver.MountOpts{}); err != nil { 490 t.Fatal(err) 491 } 492 493 if err = os.RemoveAll(filepath.Join(root, paths[depth])); err != nil { 494 t.Fatal(err) 495 } 496 expectedChanges = []archive.Change{} 497 for i := 0; i < depth; i++ { 498 expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeModify, Path: paths[i]}) 499 } 500 expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeDelete, Path: paths[depth]}) 501 502 changes, err = driver.Changes(second, nil, base, nil, "") 503 if err != nil { 504 t.Fatal(err) 505 } 506 507 if err = checkChanges(expectedChanges, changes); err != nil { 508 t.Fatal(err) 509 } 510 511 if err = driver.Create(third, second, nil); err != nil { 512 t.Fatal(err) 513 } 514 515 if root, err = driver.Get(third, graphdriver.MountOpts{}); err != nil { 516 t.Fatal(err) 517 } 518 519 expectedChanges = []archive.Change{} 520 for i := 0; i < depth; i++ { 521 expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeModify, Path: paths[i]}) 522 } 523 for i := depth; i < components-1; i++ { 524 if err = os.Mkdir(filepath.Join(root, paths[i]), 0700); err != nil { 525 t.Fatal(err) 526 } 527 expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeAdd, Path: paths[i]}) 528 } 529 if err = ioutil.WriteFile(filepath.Join(root, paths[len(paths)-1]), randomContent(128, int64(depth)), 0600); err != nil { 530 t.Fatal(err) 531 } 532 expectedChanges = append(expectedChanges, archive.Change{Kind: archive.ChangeAdd, Path: paths[len(paths)-1]}) 533 534 changes, err = driver.Changes(third, nil, second, nil, "") 535 if err != nil { 536 t.Fatal(err) 537 } 538 539 if err = checkChanges(expectedChanges, changes); err != nil { 540 t.Fatal(err) 541 } 542 543 err = driver.Put(third) 544 if err != nil { 545 t.Fatal(err) 546 } 547 err = driver.Put(second) 548 if err != nil { 549 t.Fatal(err) 550 } 551 err = driver.Put(base) 552 if err != nil { 553 t.Fatal(err) 554 } 555 } 556 }