github.com/afein/docker@v1.8.2/daemon/graphdriver/aufs/aufs_test.go (about) 1 // +build linux 2 3 package aufs 4 5 import ( 6 "crypto/sha256" 7 "encoding/hex" 8 "fmt" 9 "io/ioutil" 10 "os" 11 "path" 12 "testing" 13 14 "github.com/docker/docker/daemon/graphdriver" 15 "github.com/docker/docker/pkg/archive" 16 "github.com/docker/docker/pkg/reexec" 17 ) 18 19 var ( 20 tmpOuter = path.Join(os.TempDir(), "aufs-tests") 21 tmp = path.Join(tmpOuter, "aufs") 22 ) 23 24 func init() { 25 reexec.Init() 26 } 27 28 func testInit(dir string, t *testing.T) graphdriver.Driver { 29 d, err := Init(dir, nil) 30 if err != nil { 31 if err == graphdriver.ErrNotSupported { 32 t.Skip(err) 33 } else { 34 t.Fatal(err) 35 } 36 } 37 return d 38 } 39 40 func newDriver(t *testing.T) *Driver { 41 if err := os.MkdirAll(tmp, 0755); err != nil { 42 t.Fatal(err) 43 } 44 45 d := testInit(tmp, t) 46 return d.(*Driver) 47 } 48 49 func TestNewDriver(t *testing.T) { 50 if err := os.MkdirAll(tmp, 0755); err != nil { 51 t.Fatal(err) 52 } 53 54 d := testInit(tmp, t) 55 defer os.RemoveAll(tmp) 56 if d == nil { 57 t.Fatalf("Driver should not be nil") 58 } 59 } 60 61 func TestAufsString(t *testing.T) { 62 d := newDriver(t) 63 defer os.RemoveAll(tmp) 64 65 if d.String() != "aufs" { 66 t.Fatalf("Expected aufs got %s", d.String()) 67 } 68 } 69 70 func TestCreateDirStructure(t *testing.T) { 71 newDriver(t) 72 defer os.RemoveAll(tmp) 73 74 paths := []string{ 75 "mnt", 76 "layers", 77 "diff", 78 } 79 80 for _, p := range paths { 81 if _, err := os.Stat(path.Join(tmp, p)); err != nil { 82 t.Fatal(err) 83 } 84 } 85 } 86 87 // We should be able to create two drivers with the same dir structure 88 func TestNewDriverFromExistingDir(t *testing.T) { 89 if err := os.MkdirAll(tmp, 0755); err != nil { 90 t.Fatal(err) 91 } 92 93 testInit(tmp, t) 94 testInit(tmp, t) 95 os.RemoveAll(tmp) 96 } 97 98 func TestCreateNewDir(t *testing.T) { 99 d := newDriver(t) 100 defer os.RemoveAll(tmp) 101 102 if err := d.Create("1", ""); err != nil { 103 t.Fatal(err) 104 } 105 } 106 107 func TestCreateNewDirStructure(t *testing.T) { 108 d := newDriver(t) 109 defer os.RemoveAll(tmp) 110 111 if err := d.Create("1", ""); err != nil { 112 t.Fatal(err) 113 } 114 115 paths := []string{ 116 "mnt", 117 "diff", 118 "layers", 119 } 120 121 for _, p := range paths { 122 if _, err := os.Stat(path.Join(tmp, p, "1")); err != nil { 123 t.Fatal(err) 124 } 125 } 126 } 127 128 func TestRemoveImage(t *testing.T) { 129 d := newDriver(t) 130 defer os.RemoveAll(tmp) 131 132 if err := d.Create("1", ""); err != nil { 133 t.Fatal(err) 134 } 135 136 if err := d.Remove("1"); err != nil { 137 t.Fatal(err) 138 } 139 140 paths := []string{ 141 "mnt", 142 "diff", 143 "layers", 144 } 145 146 for _, p := range paths { 147 if _, err := os.Stat(path.Join(tmp, p, "1")); err == nil { 148 t.Fatalf("Error should not be nil because dirs with id 1 should be delted: %s", p) 149 } 150 } 151 } 152 153 func TestGetWithoutParent(t *testing.T) { 154 d := newDriver(t) 155 defer os.RemoveAll(tmp) 156 157 if err := d.Create("1", ""); err != nil { 158 t.Fatal(err) 159 } 160 161 diffPath, err := d.Get("1", "") 162 if err != nil { 163 t.Fatal(err) 164 } 165 expected := path.Join(tmp, "diff", "1") 166 if diffPath != expected { 167 t.Fatalf("Expected path %s got %s", expected, diffPath) 168 } 169 } 170 171 func TestCleanupWithNoDirs(t *testing.T) { 172 d := newDriver(t) 173 defer os.RemoveAll(tmp) 174 175 if err := d.Cleanup(); err != nil { 176 t.Fatal(err) 177 } 178 } 179 180 func TestCleanupWithDir(t *testing.T) { 181 d := newDriver(t) 182 defer os.RemoveAll(tmp) 183 184 if err := d.Create("1", ""); err != nil { 185 t.Fatal(err) 186 } 187 188 if err := d.Cleanup(); err != nil { 189 t.Fatal(err) 190 } 191 } 192 193 func TestMountedFalseResponse(t *testing.T) { 194 d := newDriver(t) 195 defer os.RemoveAll(tmp) 196 197 if err := d.Create("1", ""); err != nil { 198 t.Fatal(err) 199 } 200 201 response, err := d.mounted("1") 202 if err != nil { 203 t.Fatal(err) 204 } 205 206 if response != false { 207 t.Fatalf("Response if dir id 1 is mounted should be false") 208 } 209 } 210 211 func TestMountedTrueReponse(t *testing.T) { 212 d := newDriver(t) 213 defer os.RemoveAll(tmp) 214 defer d.Cleanup() 215 216 if err := d.Create("1", ""); err != nil { 217 t.Fatal(err) 218 } 219 if err := d.Create("2", "1"); err != nil { 220 t.Fatal(err) 221 } 222 223 _, err := d.Get("2", "") 224 if err != nil { 225 t.Fatal(err) 226 } 227 228 response, err := d.mounted("2") 229 if err != nil { 230 t.Fatal(err) 231 } 232 233 if response != true { 234 t.Fatalf("Response if dir id 2 is mounted should be true") 235 } 236 } 237 238 func TestMountWithParent(t *testing.T) { 239 d := newDriver(t) 240 defer os.RemoveAll(tmp) 241 242 if err := d.Create("1", ""); err != nil { 243 t.Fatal(err) 244 } 245 if err := d.Create("2", "1"); err != nil { 246 t.Fatal(err) 247 } 248 249 defer func() { 250 if err := d.Cleanup(); err != nil { 251 t.Fatal(err) 252 } 253 }() 254 255 mntPath, err := d.Get("2", "") 256 if err != nil { 257 t.Fatal(err) 258 } 259 if mntPath == "" { 260 t.Fatal("mntPath should not be empty string") 261 } 262 263 expected := path.Join(tmp, "mnt", "2") 264 if mntPath != expected { 265 t.Fatalf("Expected %s got %s", expected, mntPath) 266 } 267 } 268 269 func TestRemoveMountedDir(t *testing.T) { 270 d := newDriver(t) 271 defer os.RemoveAll(tmp) 272 273 if err := d.Create("1", ""); err != nil { 274 t.Fatal(err) 275 } 276 if err := d.Create("2", "1"); err != nil { 277 t.Fatal(err) 278 } 279 280 defer func() { 281 if err := d.Cleanup(); err != nil { 282 t.Fatal(err) 283 } 284 }() 285 286 mntPath, err := d.Get("2", "") 287 if err != nil { 288 t.Fatal(err) 289 } 290 if mntPath == "" { 291 t.Fatal("mntPath should not be empty string") 292 } 293 294 mounted, err := d.mounted("2") 295 if err != nil { 296 t.Fatal(err) 297 } 298 299 if !mounted { 300 t.Fatalf("Dir id 2 should be mounted") 301 } 302 303 if err := d.Remove("2"); err != nil { 304 t.Fatal(err) 305 } 306 } 307 308 func TestCreateWithInvalidParent(t *testing.T) { 309 d := newDriver(t) 310 defer os.RemoveAll(tmp) 311 312 if err := d.Create("1", "docker"); err == nil { 313 t.Fatalf("Error should not be nil with parent does not exist") 314 } 315 } 316 317 func TestGetDiff(t *testing.T) { 318 d := newDriver(t) 319 defer os.RemoveAll(tmp) 320 321 if err := d.Create("1", ""); err != nil { 322 t.Fatal(err) 323 } 324 325 diffPath, err := d.Get("1", "") 326 if err != nil { 327 t.Fatal(err) 328 } 329 330 // Add a file to the diff path with a fixed size 331 size := int64(1024) 332 333 f, err := os.Create(path.Join(diffPath, "test_file")) 334 if err != nil { 335 t.Fatal(err) 336 } 337 if err := f.Truncate(size); err != nil { 338 t.Fatal(err) 339 } 340 f.Close() 341 342 a, err := d.Diff("1", "") 343 if err != nil { 344 t.Fatal(err) 345 } 346 if a == nil { 347 t.Fatalf("Archive should not be nil") 348 } 349 } 350 351 func TestChanges(t *testing.T) { 352 d := newDriver(t) 353 defer os.RemoveAll(tmp) 354 355 if err := d.Create("1", ""); err != nil { 356 t.Fatal(err) 357 } 358 if err := d.Create("2", "1"); err != nil { 359 t.Fatal(err) 360 } 361 362 defer func() { 363 if err := d.Cleanup(); err != nil { 364 t.Fatal(err) 365 } 366 }() 367 368 mntPoint, err := d.Get("2", "") 369 if err != nil { 370 t.Fatal(err) 371 } 372 373 // Create a file to save in the mountpoint 374 f, err := os.Create(path.Join(mntPoint, "test.txt")) 375 if err != nil { 376 t.Fatal(err) 377 } 378 379 if _, err := f.WriteString("testline"); err != nil { 380 t.Fatal(err) 381 } 382 if err := f.Close(); err != nil { 383 t.Fatal(err) 384 } 385 386 changes, err := d.Changes("2", "") 387 if err != nil { 388 t.Fatal(err) 389 } 390 if len(changes) != 1 { 391 t.Fatalf("Dir 2 should have one change from parent got %d", len(changes)) 392 } 393 change := changes[0] 394 395 expectedPath := "/test.txt" 396 if change.Path != expectedPath { 397 t.Fatalf("Expected path %s got %s", expectedPath, change.Path) 398 } 399 400 if change.Kind != archive.ChangeAdd { 401 t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind) 402 } 403 404 if err := d.Create("3", "2"); err != nil { 405 t.Fatal(err) 406 } 407 mntPoint, err = d.Get("3", "") 408 if err != nil { 409 t.Fatal(err) 410 } 411 412 // Create a file to save in the mountpoint 413 f, err = os.Create(path.Join(mntPoint, "test2.txt")) 414 if err != nil { 415 t.Fatal(err) 416 } 417 418 if _, err := f.WriteString("testline"); err != nil { 419 t.Fatal(err) 420 } 421 if err := f.Close(); err != nil { 422 t.Fatal(err) 423 } 424 425 changes, err = d.Changes("3", "") 426 if err != nil { 427 t.Fatal(err) 428 } 429 430 if len(changes) != 1 { 431 t.Fatalf("Dir 2 should have one change from parent got %d", len(changes)) 432 } 433 change = changes[0] 434 435 expectedPath = "/test2.txt" 436 if change.Path != expectedPath { 437 t.Fatalf("Expected path %s got %s", expectedPath, change.Path) 438 } 439 440 if change.Kind != archive.ChangeAdd { 441 t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind) 442 } 443 } 444 445 func TestDiffSize(t *testing.T) { 446 d := newDriver(t) 447 defer os.RemoveAll(tmp) 448 449 if err := d.Create("1", ""); err != nil { 450 t.Fatal(err) 451 } 452 453 diffPath, err := d.Get("1", "") 454 if err != nil { 455 t.Fatal(err) 456 } 457 458 // Add a file to the diff path with a fixed size 459 size := int64(1024) 460 461 f, err := os.Create(path.Join(diffPath, "test_file")) 462 if err != nil { 463 t.Fatal(err) 464 } 465 if err := f.Truncate(size); err != nil { 466 t.Fatal(err) 467 } 468 s, err := f.Stat() 469 if err != nil { 470 t.Fatal(err) 471 } 472 size = s.Size() 473 if err := f.Close(); err != nil { 474 t.Fatal(err) 475 } 476 477 diffSize, err := d.DiffSize("1", "") 478 if err != nil { 479 t.Fatal(err) 480 } 481 if diffSize != size { 482 t.Fatalf("Expected size to be %d got %d", size, diffSize) 483 } 484 } 485 486 func TestChildDiffSize(t *testing.T) { 487 d := newDriver(t) 488 defer os.RemoveAll(tmp) 489 defer d.Cleanup() 490 491 if err := d.Create("1", ""); err != nil { 492 t.Fatal(err) 493 } 494 495 diffPath, err := d.Get("1", "") 496 if err != nil { 497 t.Fatal(err) 498 } 499 500 // Add a file to the diff path with a fixed size 501 size := int64(1024) 502 503 f, err := os.Create(path.Join(diffPath, "test_file")) 504 if err != nil { 505 t.Fatal(err) 506 } 507 if err := f.Truncate(size); err != nil { 508 t.Fatal(err) 509 } 510 s, err := f.Stat() 511 if err != nil { 512 t.Fatal(err) 513 } 514 size = s.Size() 515 if err := f.Close(); err != nil { 516 t.Fatal(err) 517 } 518 519 diffSize, err := d.DiffSize("1", "") 520 if err != nil { 521 t.Fatal(err) 522 } 523 if diffSize != size { 524 t.Fatalf("Expected size to be %d got %d", size, diffSize) 525 } 526 527 if err := d.Create("2", "1"); err != nil { 528 t.Fatal(err) 529 } 530 531 diffSize, err = d.DiffSize("2", "") 532 if err != nil { 533 t.Fatal(err) 534 } 535 // The diff size for the child should be zero 536 if diffSize != 0 { 537 t.Fatalf("Expected size to be %d got %d", 0, diffSize) 538 } 539 } 540 541 func TestExists(t *testing.T) { 542 d := newDriver(t) 543 defer os.RemoveAll(tmp) 544 defer d.Cleanup() 545 546 if err := d.Create("1", ""); err != nil { 547 t.Fatal(err) 548 } 549 550 if d.Exists("none") { 551 t.Fatal("id name should not exist in the driver") 552 } 553 554 if !d.Exists("1") { 555 t.Fatal("id 1 should exist in the driver") 556 } 557 } 558 559 func TestStatus(t *testing.T) { 560 d := newDriver(t) 561 defer os.RemoveAll(tmp) 562 defer d.Cleanup() 563 564 if err := d.Create("1", ""); err != nil { 565 t.Fatal(err) 566 } 567 568 status := d.Status() 569 if status == nil || len(status) == 0 { 570 t.Fatal("Status should not be nil or empty") 571 } 572 rootDir := status[0] 573 dirs := status[2] 574 if rootDir[0] != "Root Dir" { 575 t.Fatalf("Expected Root Dir got %s", rootDir[0]) 576 } 577 if rootDir[1] != d.rootPath() { 578 t.Fatalf("Expected %s got %s", d.rootPath(), rootDir[1]) 579 } 580 if dirs[0] != "Dirs" { 581 t.Fatalf("Expected Dirs got %s", dirs[0]) 582 } 583 if dirs[1] != "1" { 584 t.Fatalf("Expected 1 got %s", dirs[1]) 585 } 586 } 587 588 func TestApplyDiff(t *testing.T) { 589 d := newDriver(t) 590 defer os.RemoveAll(tmp) 591 defer d.Cleanup() 592 593 if err := d.Create("1", ""); err != nil { 594 t.Fatal(err) 595 } 596 597 diffPath, err := d.Get("1", "") 598 if err != nil { 599 t.Fatal(err) 600 } 601 602 // Add a file to the diff path with a fixed size 603 size := int64(1024) 604 605 f, err := os.Create(path.Join(diffPath, "test_file")) 606 if err != nil { 607 t.Fatal(err) 608 } 609 if err := f.Truncate(size); err != nil { 610 t.Fatal(err) 611 } 612 f.Close() 613 614 diff, err := d.Diff("1", "") 615 if err != nil { 616 t.Fatal(err) 617 } 618 619 if err := d.Create("2", ""); err != nil { 620 t.Fatal(err) 621 } 622 if err := d.Create("3", "2"); err != nil { 623 t.Fatal(err) 624 } 625 626 if err := d.applyDiff("3", diff); err != nil { 627 t.Fatal(err) 628 } 629 630 // Ensure that the file is in the mount point for id 3 631 632 mountPoint, err := d.Get("3", "") 633 if err != nil { 634 t.Fatal(err) 635 } 636 if _, err := os.Stat(path.Join(mountPoint, "test_file")); err != nil { 637 t.Fatal(err) 638 } 639 } 640 641 func hash(c string) string { 642 h := sha256.New() 643 fmt.Fprint(h, c) 644 return hex.EncodeToString(h.Sum(nil)) 645 } 646 647 func testMountMoreThan42Layers(t *testing.T, mountPath string) { 648 if err := os.MkdirAll(mountPath, 0755); err != nil { 649 t.Fatal(err) 650 } 651 652 defer os.RemoveAll(mountPath) 653 d := testInit(mountPath, t).(*Driver) 654 defer d.Cleanup() 655 var last string 656 var expected int 657 658 for i := 1; i < 127; i++ { 659 expected++ 660 var ( 661 parent = fmt.Sprintf("%d", i-1) 662 current = fmt.Sprintf("%d", i) 663 ) 664 665 if parent == "0" { 666 parent = "" 667 } else { 668 parent = hash(parent) 669 } 670 current = hash(current) 671 672 if err := d.Create(current, parent); err != nil { 673 t.Logf("Current layer %d", i) 674 t.Error(err) 675 } 676 point, err := d.Get(current, "") 677 if err != nil { 678 t.Logf("Current layer %d", i) 679 t.Error(err) 680 } 681 f, err := os.Create(path.Join(point, current)) 682 if err != nil { 683 t.Logf("Current layer %d", i) 684 t.Error(err) 685 } 686 f.Close() 687 688 if i%10 == 0 { 689 if err := os.Remove(path.Join(point, parent)); err != nil { 690 t.Logf("Current layer %d", i) 691 t.Error(err) 692 } 693 expected-- 694 } 695 last = current 696 } 697 698 // Perform the actual mount for the top most image 699 point, err := d.Get(last, "") 700 if err != nil { 701 t.Error(err) 702 } 703 files, err := ioutil.ReadDir(point) 704 if err != nil { 705 t.Error(err) 706 } 707 if len(files) != expected { 708 t.Errorf("Expected %d got %d", expected, len(files)) 709 } 710 } 711 712 func TestMountMoreThan42Layers(t *testing.T) { 713 os.RemoveAll(tmpOuter) 714 testMountMoreThan42Layers(t, tmp) 715 } 716 717 func TestMountMoreThan42LayersMatchingPathLength(t *testing.T) { 718 defer os.RemoveAll(tmpOuter) 719 zeroes := "0" 720 for { 721 // This finds a mount path so that when combined into aufs mount options 722 // 4096 byte boundary would be in between the paths or in permission 723 // section. For '/tmp' it will use '/tmp/aufs-tests/00000000/aufs' 724 mountPath := path.Join(tmpOuter, zeroes, "aufs") 725 pathLength := 77 + len(mountPath) 726 727 if mod := 4095 % pathLength; mod == 0 || mod > pathLength-2 { 728 t.Logf("Using path: %s", mountPath) 729 testMountMoreThan42Layers(t, mountPath) 730 return 731 } 732 zeroes += "0" 733 } 734 }