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