From 750cdc951fac729993ae5eaa9deb26b4a2061d0a Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 15 Feb 2017 06:50:43 +0000 Subject: [PATCH] snapshotter: add more assertion Signed-off-by: Akihiro Suda --- archive/tar_test.go | 16 ++++----- fs/diff_test.go | 8 ++--- fs/fstest/compare.go | 16 +++++++++ fs/fstest/file.go | 12 +++++-- snapshot/snapshotter.go | 79 ++++++++++++++++++++++++++++------------- 5 files changed, 92 insertions(+), 39 deletions(-) diff --git a/archive/tar_test.go b/archive/tar_test.go index 1245baa..8b9ee8d 100644 --- a/archive/tar_test.go +++ b/archive/tar_test.go @@ -56,15 +56,15 @@ func TestDiffApply(t *testing.T) { fstest.CreateFile("/home/derek/.zshrc", []byte("#ZSH is just better\n"), 0640), ), fstest.Apply( - fstest.RemoveFile("/etc/badfile"), + fstest.Remove("/etc/badfile"), fstest.Rename("/home/derek", "/home/notderek"), ), fstest.Apply( - fstest.RemoveFile("/usr"), - fstest.RemoveFile("/etc/hosts.allow"), + fstest.RemoveAll("/usr"), + fstest.Remove("/etc/hosts.allow"), ), fstest.Apply( - fstest.RemoveFile("/home"), + fstest.RemoveAll("/home"), fstest.CreateDir("/home/derek", 0700), fstest.CreateFile("/home/derek/.bashrc", []byte("#not going away\n"), 0640), // "/etc/hosts" must be touched to be hardlinked in same layer @@ -92,14 +92,14 @@ func TestDiffApplyDeletion(t *testing.T) { fstest.CreateFile("/test/b", []byte{}, 0644), fstest.CreateDir("/test/otherdir", 0755), fstest.CreateFile("/test/otherdir/.empty", []byte{}, 0644), - fstest.RemoveFile("/lib"), + fstest.RemoveAll("/lib"), fstest.CreateDir("/lib", 0700), fstest.CreateFile("/lib/not-hidden", []byte{}, 0644), ), fstest.Apply( - fstest.RemoveFile("/test/a"), - fstest.RemoveFile("/test/b"), - fstest.RemoveFile("/test/otherdir"), + fstest.Remove("/test/a"), + fstest.Remove("/test/b"), + fstest.RemoveAll("/test/otherdir"), fstest.CreateFile("/lib/newfile", []byte{}, 0644), ), } diff --git a/fs/diff_test.go b/fs/diff_test.go index 9267799..bee0044 100644 --- a/fs/diff_test.go +++ b/fs/diff_test.go @@ -33,7 +33,7 @@ func TestSimpleDiff(t *testing.T) { fstest.CreateFile("/etc/profile", []byte("PATH=/usr/bin"), 0666), fstest.CreateDir("/root", 0700), fstest.CreateFile("/root/.bashrc", []byte("PATH=/usr/sbin:/usr/bin"), 0644), - fstest.RemoveFile("/etc/unexpected"), + fstest.Remove("/etc/unexpected"), ) diff := []testChange{ Modify("/etc/hosts"), @@ -57,7 +57,7 @@ func TestDirectoryReplace(t *testing.T) { ) l2 := fstest.Apply( fstest.CreateFile("/dir1/f11", []byte("#New file here"), 0644), - fstest.RemoveFile("/dir1/f2"), + fstest.RemoveAll("/dir1/f2"), fstest.CreateFile("/dir1/f2", []byte("Now file"), 0666), ) diff := []testChange{ @@ -77,7 +77,7 @@ func TestRemoveDirectoryTree(t *testing.T) { fstest.CreateFile("/dir1/dir2/f2", []byte("f2"), 0644), ) l2 := fstest.Apply( - fstest.RemoveFile("/dir1"), + fstest.RemoveAll("/dir1"), ) diff := []testChange{ Delete("/dir1"), @@ -93,7 +93,7 @@ func TestFileReplace(t *testing.T) { fstest.CreateFile("/dir1", []byte("a file, not a directory"), 0644), ) l2 := fstest.Apply( - fstest.RemoveFile("/dir1"), + fstest.Remove("/dir1"), fstest.CreateDir("/dir1/dir2", 0755), fstest.CreateFile("/dir1/dir2/f1", []byte("also a file"), 0644), ) diff --git a/fs/fstest/compare.go b/fs/fstest/compare.go index 84781b3..a569d69 100644 --- a/fs/fstest/compare.go +++ b/fs/fstest/compare.go @@ -1,6 +1,9 @@ package fstest import ( + "io/ioutil" + "os" + "github.com/pkg/errors" "github.com/stevvooe/continuity" ) @@ -35,3 +38,16 @@ func CheckDirectoryEqual(d1, d2 string) error { return nil } + +// CheckDirectoryEqualWithApplier compares directory against applier +func CheckDirectoryEqualWithApplier(root string, a Applier) error { + applied, err := ioutil.TempDir("", "fstest") + if err != nil { + return err + } + defer os.RemoveAll(applied) + if err := a.Apply(applied); err != nil { + return err + } + return CheckDirectoryEqual(applied, root) +} diff --git a/fs/fstest/file.go b/fs/fstest/file.go index fab4f68..7af6edf 100644 --- a/fs/fstest/file.go +++ b/fs/fstest/file.go @@ -37,8 +37,16 @@ func CreateFile(name string, content []byte, perm os.FileMode) Applier { }) } -// RemoveFile returns a file applier which removes the provided file name -func RemoveFile(name string) Applier { +// Remove returns a file applier which removes the provided file name +func Remove(name string) Applier { + return applyFn(func(root string) error { + return os.Remove(filepath.Join(root, name)) + }) +} + +// RemoveAll returns a file applier which removes the provided file name +// as in os.RemoveAll +func RemoveAll(name string) Applier { return applyFn(func(root string) error { return os.RemoveAll(filepath.Join(root, name)) }) diff --git a/snapshot/snapshotter.go b/snapshot/snapshotter.go index e3402aa..03d40e8 100644 --- a/snapshot/snapshotter.go +++ b/snapshot/snapshotter.go @@ -5,9 +5,11 @@ import ( "io/ioutil" "os" "path/filepath" + "syscall" "testing" "github.com/docker/containerd" + "github.com/docker/containerd/fs/fstest" "github.com/docker/containerd/testutil" "github.com/stretchr/testify/assert" ) @@ -225,6 +227,8 @@ func SnapshotterSuite(t *testing.T, name string, snapshotterFn func(root string) func makeTest(t *testing.T, name string, snapshotterFn func(root string) (Snapshotter, func(), error), fn func(t *testing.T, snapshotter Snapshotter, work string)) func(t *testing.T) { return func(t *testing.T) { + oldumask := syscall.Umask(0) + defer syscall.Umask(oldumask) // Make two directories: a snapshotter root and a play area for the tests: // // /tmp @@ -261,14 +265,29 @@ func makeTest(t *testing.T, name string, snapshotterFn func(root string) (Snapsh // checkSnapshotterBasic tests the basic workflow of a snapshot snapshotter. func checkSnapshotterBasic(t *testing.T, snapshotter Snapshotter, work string) { ctx := context.TODO() + + initialApplier := fstest.Apply( + fstest.CreateFile("/foo", []byte("foo\n"), 0777), + fstest.CreateDir("/a", 0755), + fstest.CreateDir("/a/b", 0755), + fstest.CreateDir("/a/b/c", 0755), + ) + + diffApplier := fstest.Apply( + fstest.CreateFile("/bar", []byte("bar\n"), 0777), + // also, change content of foo to bar + fstest.CreateFile("/foo", []byte("bar\n"), 0777), + fstest.RemoveAll("/a/b"), + ) + preparing := filepath.Join(work, "preparing") if err := os.MkdirAll(preparing, 0777); err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } mounts, err := snapshotter.Prepare(ctx, preparing, "") if err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } if len(mounts) < 1 { @@ -276,26 +295,22 @@ func checkSnapshotterBasic(t *testing.T, snapshotter Snapshotter, work string) { } if err := containerd.MountAll(mounts, preparing); err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } defer testutil.Unmount(t, preparing) - if err := ioutil.WriteFile(filepath.Join(preparing, "foo"), []byte("foo\n"), 0777); err != nil { - t.Fatal(err) - } - - if err := os.MkdirAll(filepath.Join(preparing, "a", "b", "c"), 0755); err != nil { - t.Fatal(err) + if err := initialApplier.Apply(preparing); err != nil { + t.Fatalf("failure reason: %+v", err) } committed := filepath.Join(work, "committed") if err := snapshotter.Commit(ctx, committed, preparing); err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } si, err := snapshotter.Stat(ctx, committed) if err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } assert.Equal(t, "", si.Parent) @@ -303,29 +318,24 @@ func checkSnapshotterBasic(t *testing.T, snapshotter Snapshotter, work string) { next := filepath.Join(work, "nextlayer") if err := os.MkdirAll(next, 0777); err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } mounts, err = snapshotter.Prepare(ctx, next, committed) if err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } if err := containerd.MountAll(mounts, next); err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } defer testutil.Unmount(t, next) - if err := ioutil.WriteFile(filepath.Join(next, "bar"), []byte("bar\n"), 0777); err != nil { - t.Fatal(err) + if err := fstest.CheckDirectoryEqualWithApplier(next, initialApplier); err != nil { + t.Fatalf("failure reason: %+v", err) } - // also, change content of foo to bar - if err := ioutil.WriteFile(filepath.Join(next, "foo"), []byte("bar\n"), 0777); err != nil { - t.Fatal(err) - } - - if err := os.RemoveAll(filepath.Join(next, "a", "b")); err != nil { - t.Log(err) + if err := diffApplier.Apply(next); err != nil { + t.Fatalf("failure reason: %+v", err) } ni, err := snapshotter.Stat(ctx, next) @@ -338,12 +348,12 @@ func checkSnapshotterBasic(t *testing.T, snapshotter Snapshotter, work string) { nextCommitted := filepath.Join(work, "committed-next") if err := snapshotter.Commit(ctx, nextCommitted, next); err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } si2, err := snapshotter.Stat(ctx, nextCommitted) if err != nil { - t.Fatal(err) + t.Fatalf("failure reason: %+v", err) } assert.Equal(t, committed, si2.Parent) @@ -360,4 +370,23 @@ func checkSnapshotterBasic(t *testing.T, snapshotter Snapshotter, work string) { })) assert.Equal(t, expected, walked) + + nextnext := filepath.Join(work, "nextnextlayer") + if err := os.MkdirAll(nextnext, 0777); err != nil { + t.Fatalf("failure reason: %+v", err) + } + + mounts, err = snapshotter.View(ctx, nextnext, nextCommitted) + if err != nil { + t.Fatalf("failure reason: %+v", err) + } + if err := containerd.MountAll(mounts, nextnext); err != nil { + t.Fatalf("failure reason: %+v", err) + } + defer testutil.Unmount(t, nextnext) + + if err := fstest.CheckDirectoryEqualWithApplier(nextnext, + fstest.Apply(initialApplier, diffApplier)); err != nil { + t.Fatalf("failure reason: %+v", err) + } }