github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/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, nil, 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(d.active["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(d.active["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(d.active["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 TestHardlinks(t *testing.T) { 642 // Copy 2 layers that have linked files to new layers and check if hardlink are preserved 643 d := newDriver(t) 644 defer os.RemoveAll(tmp) 645 defer d.Cleanup() 646 647 origFile := "test_file" 648 linkedFile := "linked_file" 649 650 if err := d.Create("source-1", "", ""); err != nil { 651 t.Fatal(err) 652 } 653 654 mountPath, err := d.Get("source-1", "") 655 if err != nil { 656 t.Fatal(err) 657 } 658 659 f, err := os.Create(path.Join(mountPath, origFile)) 660 if err != nil { 661 t.Fatal(err) 662 } 663 f.Close() 664 665 layerTar1, err := d.Diff("source-1", "") 666 if err != nil { 667 t.Fatal(err) 668 } 669 670 if err := d.Create("source-2", "source-1", ""); err != nil { 671 t.Fatal(err) 672 } 673 674 mountPath, err = d.Get("source-2", "") 675 if err != nil { 676 t.Fatal(err) 677 } 678 679 if err := os.Link(path.Join(mountPath, origFile), path.Join(mountPath, linkedFile)); err != nil { 680 t.Fatal(err) 681 } 682 683 layerTar2, err := d.Diff("source-2", "source-1") 684 if err != nil { 685 t.Fatal(err) 686 } 687 688 if err := d.Create("target-1", "", ""); err != nil { 689 t.Fatal(err) 690 } 691 692 if _, err := d.ApplyDiff("target-1", "", layerTar1); err != nil { 693 t.Fatal(err) 694 } 695 696 if err := d.Create("target-2", "target-1", ""); err != nil { 697 t.Fatal(err) 698 } 699 700 if _, err := d.ApplyDiff("target-2", "target-1", layerTar2); err != nil { 701 t.Fatal(err) 702 } 703 704 mountPath, err = d.Get("target-2", "") 705 if err != nil { 706 t.Fatal(err) 707 } 708 709 fi1, err := os.Lstat(path.Join(mountPath, origFile)) 710 if err != nil { 711 t.Fatal(err) 712 } 713 fi2, err := os.Lstat(path.Join(mountPath, linkedFile)) 714 if err != nil { 715 t.Fatal(err) 716 } 717 718 if !os.SameFile(fi1, fi2) { 719 t.Fatal("Target files are not linked") 720 } 721 } 722 723 func hash(c string) string { 724 h := sha256.New() 725 fmt.Fprint(h, c) 726 return hex.EncodeToString(h.Sum(nil)) 727 } 728 729 func testMountMoreThan42Layers(t *testing.T, mountPath string) { 730 if err := os.MkdirAll(mountPath, 0755); err != nil { 731 t.Fatal(err) 732 } 733 734 defer os.RemoveAll(mountPath) 735 d := testInit(mountPath, t).(*Driver) 736 defer d.Cleanup() 737 var last string 738 var expected int 739 740 for i := 1; i < 127; i++ { 741 expected++ 742 var ( 743 parent = fmt.Sprintf("%d", i-1) 744 current = fmt.Sprintf("%d", i) 745 ) 746 747 if parent == "0" { 748 parent = "" 749 } else { 750 parent = hash(parent) 751 } 752 current = hash(current) 753 754 if err := d.Create(current, parent, ""); err != nil { 755 t.Logf("Current layer %d", i) 756 t.Error(err) 757 } 758 point, err := d.Get(current, "") 759 if err != nil { 760 t.Logf("Current layer %d", i) 761 t.Error(err) 762 } 763 f, err := os.Create(path.Join(point, current)) 764 if err != nil { 765 t.Logf("Current layer %d", i) 766 t.Error(err) 767 } 768 f.Close() 769 770 if i%10 == 0 { 771 if err := os.Remove(path.Join(point, parent)); err != nil { 772 t.Logf("Current layer %d", i) 773 t.Error(err) 774 } 775 expected-- 776 } 777 last = current 778 } 779 780 // Perform the actual mount for the top most image 781 point, err := d.Get(last, "") 782 if err != nil { 783 t.Error(err) 784 } 785 files, err := ioutil.ReadDir(point) 786 if err != nil { 787 t.Error(err) 788 } 789 if len(files) != expected { 790 t.Errorf("Expected %d got %d", expected, len(files)) 791 } 792 } 793 794 func TestMountMoreThan42Layers(t *testing.T) { 795 os.RemoveAll(tmpOuter) 796 testMountMoreThan42Layers(t, tmp) 797 } 798 799 func TestMountMoreThan42LayersMatchingPathLength(t *testing.T) { 800 defer os.RemoveAll(tmpOuter) 801 zeroes := "0" 802 for { 803 // This finds a mount path so that when combined into aufs mount options 804 // 4096 byte boundary would be in between the paths or in permission 805 // section. For '/tmp' it will use '/tmp/aufs-tests/00000000/aufs' 806 mountPath := path.Join(tmpOuter, zeroes, "aufs") 807 pathLength := 77 + len(mountPath) 808 809 if mod := 4095 % pathLength; mod == 0 || mod > pathLength-2 { 810 t.Logf("Using path: %s", mountPath) 811 testMountMoreThan42Layers(t, mountPath) 812 return 813 } 814 zeroes += "0" 815 } 816 }