diff --git a/tests/sharedstorage/sharedstorage_test.go b/tests/sharedstorage/sharedstorage_test.go index d2230a0..0fe7838 100644 --- a/tests/sharedstorage/sharedstorage_test.go +++ b/tests/sharedstorage/sharedstorage_test.go @@ -2,7 +2,10 @@ package sharedstorage import ( + "fmt" + "os" "testing" + "time" "golang.org/x/sys/unix" @@ -11,11 +14,43 @@ import ( var flagSharestorage bool +const cacheTime = time.Second + func TestMain(m *testing.M) { + ret := 0 flagSharestorage = false - m.Run() + ret += m.Run() flagSharestorage = true - m.Run() + ret += m.Run() + os.Exit(ret) +} + +type testCase struct { + t *testing.T + + cipherdir string + mnt1 string + mnt2 string +} + +func newTestCase(t *testing.T) *testCase { + tc := testCase{} + tc.cipherdir = test_helpers.InitFS(t) + tc.mnt1 = tc.cipherdir + ".mnt1" + tc.mnt2 = tc.cipherdir + ".mnt2" + mountSharedstorage(t, tc.cipherdir, tc.mnt1) + mountSharedstorage(t, tc.cipherdir, tc.mnt2) + t.Logf("newTestCase: sharedstorage=%v cipherdir=%q", flagSharestorage, tc.cipherdir) + return &tc +} + +func (tc *testCase) cleanup() { + for _, mnt := range []string{tc.mnt1, tc.mnt2} { + err := test_helpers.UnmountErr(mnt) + if err != nil { + tc.t.Error(err) + } + } } // mountSharedstorage mounts `cipherdir` on `mnt` with or without the @@ -28,34 +63,78 @@ func mountSharedstorage(t *testing.T, cipherdir string, mnt string) { test_helpers.MountOrFatal(t, cipherdir, mnt, args...) } -func TestUnlink(t *testing.T) { - cipherdir := test_helpers.InitFS(t) - mnt1 := cipherdir + ".mnt1" - mnt2 := cipherdir + ".mnt2" - mountSharedstorage(t, cipherdir, mnt1) - defer test_helpers.UnmountPanic(mnt1) - mountSharedstorage(t, cipherdir, mnt2) - defer test_helpers.UnmountPanic(mnt2) +func TestDirUnlink(t *testing.T) { + tc := newTestCase(t) + defer tc.cleanup() // Create dir via mnt1 - if err := unix.Mkdir(mnt1+"/foo", 0700); err != nil { + if err := unix.Mkdir(tc.mnt1+"/foo", 0700); err != nil { t.Fatal(err) } // Replace dir with file via mnt2 - if err := unix.Rmdir(mnt2 + "/foo"); err != nil { + if err := unix.Rmdir(tc.mnt2 + "/foo"); err != nil { t.Fatal(err) } - if fd, err := unix.Creat(mnt2+"/foo", 0600); err != nil { + if fd, err := unix.Creat(tc.mnt2+"/foo", 0600); err != nil { t.Fatal(err) } else { unix.Close(fd) } // Try to unlink via mnt1 - if err := unix.Unlink(mnt1 + "/foo"); err != nil { + if err := unix.Unlink(tc.mnt1 + "/foo"); err != nil { + // Must work with -sharedstorage if flagSharestorage { t.Fatal(err) } else { - t.Logf("Unlink failed as expected: errno %d / %v", err, err) + // Must always work after cache timeout + time.Sleep(cacheTime) + if err := unix.Unlink(tc.mnt1 + "/foo"); err != nil { + t.Fatal(err) + } } } } + +// TestStaleHardlinks always failed before +// https://review.gerrithub.io/c/hanwen/go-fuse/+/513646/2 +func TestStaleHardlinks(t *testing.T) { + tc := newTestCase(t) + defer tc.cleanup() + + link0 := tc.mnt1 + "/link0" + if fd, err := unix.Creat(link0, 0600); err != nil { + t.Fatal(err) + } else { + unix.Close(fd) + } + // Create hardlinks via mnt1 + for i := 1; i < 20; i++ { + linki := fmt.Sprintf(tc.mnt1+"/link%d", i) + if err := unix.Link(link0, linki); err != nil { + t.Fatal(err) + } + } + // Delete hardlinks via mnt2 + for i := 1; i < 20; i++ { + linki := fmt.Sprintf(tc.mnt2+"/link%d", i) + if err := unix.Unlink(linki); err != nil { + t.Fatal(err) + } + } + // Open link0 via mnt1 + fd, err := unix.Open(link0, unix.O_RDONLY, 0) + if err != nil { + // Must work with -sharedstorage + if flagSharestorage { + t.Fatal(err) + } else { + // Must always work after cache timeout + time.Sleep(cacheTime) + fd, err = unix.Open(link0, unix.O_RDONLY, 0) + if err != nil { + t.Fatal(err) + } + } + } + unix.Close(fd) +}