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