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"
22 tmpOuter = path.Join(os.TempDir(), "aufs-tests")
23 tmp = path.Join(tmpOuter, "aufs")
30 func testInit(dir string, t testing.TB) graphdriver.Driver {
31 d, err := Init(dir, nil, nil, nil)
33 if err == graphdriver.ErrNotSupported {
42 func newDriver(t testing.TB) *Driver {
43 if err := os.MkdirAll(tmp, 0755); err != nil {
51 func TestNewDriver(t *testing.T) {
52 if err := os.MkdirAll(tmp, 0755); err != nil {
57 defer os.RemoveAll(tmp)
59 t.Fatal("Driver should not be nil")
63 func TestAufsString(t *testing.T) {
65 defer os.RemoveAll(tmp)
67 if d.String() != "aufs" {
68 t.Fatalf("Expected aufs got %s", d.String())
72 func TestCreateDirStructure(t *testing.T) {
74 defer os.RemoveAll(tmp)
82 for _, p := range paths {
83 if _, err := os.Stat(path.Join(tmp, p)); err != nil {
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 {
100 func TestCreateNewDir(t *testing.T) {
102 defer os.RemoveAll(tmp)
104 if err := d.Create("1", "", nil); err != nil {
109 func TestCreateNewDirStructure(t *testing.T) {
111 defer os.RemoveAll(tmp)
113 if err := d.Create("1", "", nil); err != nil {
123 for _, p := range paths {
124 if _, err := os.Stat(path.Join(tmp, p, "1")); err != nil {
130 func TestRemoveImage(t *testing.T) {
132 defer os.RemoveAll(tmp)
134 if err := d.Create("1", "", nil); err != nil {
138 if err := d.Remove("1"); err != nil {
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)
155 func TestGetWithoutParent(t *testing.T) {
157 defer os.RemoveAll(tmp)
159 if err := d.Create("1", "", nil); err != nil {
163 diffPath, err := d.Get("1", "")
167 expected := path.Join(tmp, "diff", "1")
168 if diffPath != expected {
169 t.Fatalf("Expected path %s got %s", expected, diffPath)
173 func TestCleanupWithNoDirs(t *testing.T) {
175 defer os.RemoveAll(tmp)
177 if err := d.Cleanup(); err != nil {
182 func TestCleanupWithDir(t *testing.T) {
184 defer os.RemoveAll(tmp)
186 if err := d.Create("1", "", nil); err != nil {
190 if err := d.Cleanup(); err != nil {
195 func TestMountedFalseResponse(t *testing.T) {
197 defer os.RemoveAll(tmp)
199 if err := d.Create("1", "", nil); err != nil {
203 response, err := d.mounted(d.getDiffPath("1"))
208 if response != false {
209 t.Fatal("Response if dir id 1 is mounted should be false")
213 func TestMountedTrueResponse(t *testing.T) {
215 defer os.RemoveAll(tmp)
218 if err := d.Create("1", "", nil); err != nil {
221 if err := d.Create("2", "1", nil); err != nil {
225 _, err := d.Get("2", "")
230 response, err := d.mounted(d.pathCache["2"])
235 if response != true {
236 t.Fatal("Response if dir id 2 is mounted should be true")
240 func TestMountWithParent(t *testing.T) {
242 defer os.RemoveAll(tmp)
244 if err := d.Create("1", "", nil); err != nil {
247 if err := d.Create("2", "1", nil); err != nil {
252 if err := d.Cleanup(); err != nil {
257 mntPath, err := d.Get("2", "")
262 t.Fatal("mntPath should not be empty string")
265 expected := path.Join(tmp, "mnt", "2")
266 if mntPath != expected {
267 t.Fatalf("Expected %s got %s", expected, mntPath)
271 func TestRemoveMountedDir(t *testing.T) {
273 defer os.RemoveAll(tmp)
275 if err := d.Create("1", "", nil); err != nil {
278 if err := d.Create("2", "1", nil); err != nil {
283 if err := d.Cleanup(); err != nil {
288 mntPath, err := d.Get("2", "")
293 t.Fatal("mntPath should not be empty string")
296 mounted, err := d.mounted(d.pathCache["2"])
302 t.Fatal("Dir id 2 should be mounted")
305 if err := d.Remove("2"); err != nil {
310 func TestCreateWithInvalidParent(t *testing.T) {
312 defer os.RemoveAll(tmp)
314 if err := d.Create("1", "docker", nil); err == nil {
315 t.Fatal("Error should not be nil with parent does not exist")
319 func TestGetDiff(t *testing.T) {
321 defer os.RemoveAll(tmp)
323 if err := d.CreateReadWrite("1", "", nil); err != nil {
327 diffPath, err := d.Get("1", "")
332 // Add a file to the diff path with a fixed size
335 f, err := os.Create(path.Join(diffPath, "test_file"))
339 if err := f.Truncate(size); err != nil {
344 a, err := d.Diff("1", "")
349 t.Fatal("Archive should not be nil")
353 func TestChanges(t *testing.T) {
355 defer os.RemoveAll(tmp)
357 if err := d.Create("1", "", nil); err != nil {
361 if err := d.CreateReadWrite("2", "1", nil); err != nil {
366 if err := d.Cleanup(); err != nil {
371 mntPoint, err := d.Get("2", "")
376 // Create a file to save in the mountpoint
377 f, err := os.Create(path.Join(mntPoint, "test.txt"))
382 if _, err := f.WriteString("testline"); err != nil {
385 if err := f.Close(); err != nil {
389 changes, err := d.Changes("2", "")
393 if len(changes) != 1 {
394 t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
398 expectedPath := "/test.txt"
399 if change.Path != expectedPath {
400 t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
403 if change.Kind != archive.ChangeAdd {
404 t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
407 if err := d.CreateReadWrite("3", "2", nil); err != nil {
410 mntPoint, err = d.Get("3", "")
415 // Create a file to save in the mountpoint
416 f, err = os.Create(path.Join(mntPoint, "test2.txt"))
421 if _, err := f.WriteString("testline"); err != nil {
424 if err := f.Close(); err != nil {
428 changes, err = d.Changes("3", "2")
433 if len(changes) != 1 {
434 t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
438 expectedPath = "/test2.txt"
439 if change.Path != expectedPath {
440 t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
443 if change.Kind != archive.ChangeAdd {
444 t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
448 func TestDiffSize(t *testing.T) {
450 defer os.RemoveAll(tmp)
452 if err := d.CreateReadWrite("1", "", nil); err != nil {
456 diffPath, err := d.Get("1", "")
461 // Add a file to the diff path with a fixed size
464 f, err := os.Create(path.Join(diffPath, "test_file"))
468 if err := f.Truncate(size); err != nil {
476 if err := f.Close(); err != nil {
480 diffSize, err := d.DiffSize("1", "")
484 if diffSize != size {
485 t.Fatalf("Expected size to be %d got %d", size, diffSize)
489 func TestChildDiffSize(t *testing.T) {
491 defer os.RemoveAll(tmp)
494 if err := d.CreateReadWrite("1", "", nil); err != nil {
498 diffPath, err := d.Get("1", "")
503 // Add a file to the diff path with a fixed size
506 f, err := os.Create(path.Join(diffPath, "test_file"))
510 if err := f.Truncate(size); err != nil {
518 if err := f.Close(); err != nil {
522 diffSize, err := d.DiffSize("1", "")
526 if diffSize != size {
527 t.Fatalf("Expected size to be %d got %d", size, diffSize)
530 if err := d.Create("2", "1", nil); err != nil {
534 diffSize, err = d.DiffSize("2", "1")
538 // The diff size for the child should be zero
540 t.Fatalf("Expected size to be %d got %d", 0, diffSize)
544 func TestExists(t *testing.T) {
546 defer os.RemoveAll(tmp)
549 if err := d.Create("1", "", nil); err != nil {
553 if d.Exists("none") {
554 t.Fatal("id none should not exist in the driver")
558 t.Fatal("id 1 should exist in the driver")
562 func TestStatus(t *testing.T) {
564 defer os.RemoveAll(tmp)
567 if err := d.Create("1", "", nil); err != nil {
572 if status == nil || len(status) == 0 {
573 t.Fatal("Status should not be nil or empty")
577 if rootDir[0] != "Root Dir" {
578 t.Fatalf("Expected Root Dir got %s", rootDir[0])
580 if rootDir[1] != d.rootPath() {
581 t.Fatalf("Expected %s got %s", d.rootPath(), rootDir[1])
583 if dirs[0] != "Dirs" {
584 t.Fatalf("Expected Dirs got %s", dirs[0])
587 t.Fatalf("Expected 1 got %s", dirs[1])
591 func TestApplyDiff(t *testing.T) {
593 defer os.RemoveAll(tmp)
596 if err := d.CreateReadWrite("1", "", nil); err != nil {
600 diffPath, err := d.Get("1", "")
605 // Add a file to the diff path with a fixed size
608 f, err := os.Create(path.Join(diffPath, "test_file"))
612 if err := f.Truncate(size); err != nil {
617 diff, err := d.Diff("1", "")
622 if err := d.Create("2", "", nil); err != nil {
625 if err := d.Create("3", "2", nil); err != nil {
629 if err := d.applyDiff("3", diff); err != nil {
633 // Ensure that the file is in the mount point for id 3
635 mountPoint, err := d.Get("3", "")
639 if _, err := os.Stat(path.Join(mountPoint, "test_file")); err != nil {
644 func hash(c string) string {
647 return hex.EncodeToString(h.Sum(nil))
650 func testMountMoreThan42Layers(t *testing.T, mountPath string) {
651 if err := os.MkdirAll(mountPath, 0755); err != nil {
655 defer os.RemoveAll(mountPath)
656 d := testInit(mountPath, t).(*Driver)
661 for i := 1; i < 127; i++ {
664 parent = fmt.Sprintf("%d", i-1)
665 current = fmt.Sprintf("%d", i)
671 parent = hash(parent)
673 current = hash(current)
675 if err := d.CreateReadWrite(current, parent, nil); err != nil {
676 t.Logf("Current layer %d", i)
679 point, err := d.Get(current, "")
681 t.Logf("Current layer %d", i)
684 f, err := os.Create(path.Join(point, current))
686 t.Logf("Current layer %d", i)
692 if err := os.Remove(path.Join(point, parent)); err != nil {
693 t.Logf("Current layer %d", i)
701 // Perform the actual mount for the top most image
702 point, err := d.Get(last, "")
706 files, err := ioutil.ReadDir(point)
710 if len(files) != expected {
711 t.Errorf("Expected %d got %d", expected, len(files))
715 func TestMountMoreThan42Layers(t *testing.T) {
716 os.RemoveAll(tmpOuter)
717 testMountMoreThan42Layers(t, tmp)
720 func TestMountMoreThan42LayersMatchingPathLength(t *testing.T) {
721 defer os.RemoveAll(tmpOuter)
724 // This finds a mount path so that when combined into aufs mount options
725 // 4096 byte boundary would be in between the paths or in permission
726 // section. For '/tmp' it will use '/tmp/aufs-tests/00000000/aufs'
727 mountPath := path.Join(tmpOuter, zeroes, "aufs")
728 pathLength := 77 + len(mountPath)
730 if mod := 4095 % pathLength; mod == 0 || mod > pathLength-2 {
731 t.Logf("Using path: %s", mountPath)
732 testMountMoreThan42Layers(t, mountPath)
739 func BenchmarkConcurrentAccess(b *testing.B) {
744 defer os.RemoveAll(tmp)
748 // create a bunch of ids
750 for i := 0; i < numConcurrent; i++ {
751 ids = append(ids, stringid.GenerateNonCryptoID())
754 if err := d.Create(ids[0], "", nil); err != nil {
758 if err := d.Create(ids[1], ids[0], nil); err != nil {
763 ids = append(ids[2:])
765 chErr := make(chan error, numConcurrent)
766 var outerGroup sync.WaitGroup
767 outerGroup.Add(len(ids))
770 // here's the actual bench
771 for _, id := range ids {
773 defer outerGroup.Done()
774 if err := d.Create(id, parent, nil); err != nil {
775 b.Logf("Create %s failed", id)
779 var innerGroup sync.WaitGroup
780 for i := 0; i < b.N; i++ {
796 for err := range chErr {