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