// Create and mount filesystem. func NewTestCase(t *testing.T) *testCase { tc := &testCase{} tc.tester = t // Make sure system setting does not affect test. syscall.Umask(0) const name string = "hello.txt" const subdir string = "subdir" var err error tc.tmpDir, err = ioutil.TempDir("", "go-fuse") if err != nil { t.Fatalf("TempDir failed: %v", err) } tc.orig = tc.tmpDir + "/orig" tc.mnt = tc.tmpDir + "/mnt" tc.Mkdir(tc.orig, 0700) tc.Mkdir(tc.mnt, 0700) tc.mountFile = filepath.Join(tc.mnt, name) tc.mountSubdir = filepath.Join(tc.mnt, subdir) tc.origFile = filepath.Join(tc.orig, name) tc.origSubdir = filepath.Join(tc.orig, subdir) var pfs pathfs.FileSystem pfs = pathfs.NewLoopbackFileSystem(tc.orig) pfs = pathfs.NewLockingFileSystem(pfs) tc.pathFs = pathfs.NewPathNodeFs(pfs, &pathfs.PathNodeFsOptions{ ClientInodes: true}) tc.connector = nodefs.NewFileSystemConnector(tc.pathFs.Root(), &nodefs.Options{ EntryTimeout: testTtl, AttrTimeout: testTtl, NegativeTimeout: 0.0, Debug: VerboseTest(), }) tc.state, err = fuse.NewServer( fuse.NewRawFileSystem(tc.connector.RawFS()), tc.mnt, &fuse.MountOptions{ SingleThreaded: true, Debug: VerboseTest(), }) if err != nil { t.Fatal("NewServer:", err) } go tc.state.Serve() if err := tc.state.WaitMount(); err != nil { t.Fatal("WaitMount", err) } return tc }
// Create and mount filesystem. func NewTestCase(t *testing.T) *testCase { me := &testCase{} me.tester = t // Make sure system setting does not affect test. syscall.Umask(0) const name string = "hello.txt" const subdir string = "subdir" var err error me.tmpDir, err = ioutil.TempDir("", "go-fuse") if err != nil { t.Fatalf("TempDir failed: %v", err) } me.orig = me.tmpDir + "/orig" me.mnt = me.tmpDir + "/mnt" os.Mkdir(me.orig, 0700) os.Mkdir(me.mnt, 0700) me.mountFile = filepath.Join(me.mnt, name) me.mountSubdir = filepath.Join(me.mnt, subdir) me.origFile = filepath.Join(me.orig, name) me.origSubdir = filepath.Join(me.orig, subdir) var pfs pathfs.FileSystem pfs = pathfs.NewLoopbackFileSystem(me.orig) pfs = pathfs.NewLockingFileSystem(pfs) me.pathFs = pathfs.NewPathNodeFs(pfs, &pathfs.PathNodeFsOptions{ ClientInodes: true}) me.connector = nodefs.NewFileSystemConnector(me.pathFs.Root(), &nodefs.Options{ EntryTimeout: testTtl, AttrTimeout: testTtl, NegativeTimeout: 0.0, }) me.connector.SetDebug(VerboseTest()) me.state, err = fuse.NewServer( fuse.NewRawFileSystem(me.connector.RawFS()), me.mnt, &fuse.MountOptions{SingleThreaded: true}) if err != nil { t.Fatal("NewServer:", err) } me.state.SetDebug(VerboseTest()) // Unthreaded, but in background. go me.state.Serve() me.state.WaitMount() return me }
func TestFSetAttr(t *testing.T) { fSetAttrFs := &FSetAttrFs{ FileSystem: pathfs.NewDefaultFileSystem(), } fs := pathfs.NewLockingFileSystem(fSetAttrFs) dir, clean := setupFAttrTest(t, fs) defer func() { if clean != nil { clean() } }() fn := dir + "/file" f, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY, 0755) if err != nil { t.Fatalf("OpenFile failed: %v", err) } defer f.Close() fi, err := f.Stat() if err != nil { t.Fatalf("Stat failed: %v", err) } _, err = f.WriteString("hello") if err != nil { t.Fatalf("WriteString failed: %v", err) } code := syscall.Ftruncate(int(f.Fd()), 3) if code != nil { t.Error("truncate retval", os.NewSyscallError("Ftruncate", code)) } if a, status := fs.GetAttr("file", nil); !status.Ok() { t.Fatalf("GetAttr: status %v", status) } else if a.Size != 3 { t.Errorf("truncate: size %d, status %v", a.Size, status) } if err := f.Chmod(024); err != nil { t.Fatalf("Chmod failed: %v", err) } if a, status := fs.GetAttr("file", nil); !status.Ok() { t.Errorf("chmod: %v", status) } else if a.Mode&07777 != 024 { t.Errorf("getattr after chmod: %o", a.Mode&0777) } if err := os.Chtimes(fn, time.Unix(0, 100e3), time.Unix(0, 101e3)); err != nil { t.Fatalf("Chtimes failed: %v", err) } if a, status := fs.GetAttr("file", nil); !status.Ok() { t.Errorf("GetAttr: %v", status) } else if a.Atimensec != 100e3 || a.Mtimensec != 101e3 { t.Errorf("Utimens: atime %d != 100e3 mtime %d != 101e3", a.Atimensec, a.Mtimensec) } newFi, err := f.Stat() if err != nil { t.Fatalf("Stat failed: %v", err) } i1 := fuse.ToStatT(fi).Ino i2 := fuse.ToStatT(newFi).Ino if i1 != i2 { t.Errorf("f.Lstat().Ino = %d. Returned %d before.", i2, i1) } if code := syscall.Fsync(int(f.Fd())); code != nil { t.Error("Fsync failed:", os.NewSyscallError("Fsync", code)) } // Close the file, otherwise we can't unmount. f.Close() // Shutdown the FUSE FS so we can safely look at fSetAttrFs clean() clean = nil if !fSetAttrFs.file.FsyncCalled { t.Error("Fsync was not called") } }
func TestUnionFsDisappearing(t *testing.T) { // This init is like setupUfs, but we want access to the // writable Fs. wd, _ := ioutil.TempDir("", "") defer os.RemoveAll(wd) err := os.Mkdir(wd+"/mnt", 0700) if err != nil { t.Fatalf("Mkdir failed: %v", err) } err = os.Mkdir(wd+"/rw", 0700) if err != nil { t.Fatalf("Mkdir failed: %v", err) } os.Mkdir(wd+"/ro", 0700) if err != nil { t.Fatalf("Mkdir failed: %v", err) } wrFs := newDisappearingFS(pathfs.NewLoopbackFileSystem(wd+"/rw"), pathfs.NewLoopbackFileSystem("/dev/null")) var fses []pathfs.FileSystem fses = append(fses, pathfs.NewLockingFileSystem(wrFs)) fses = append(fses, pathfs.NewLoopbackFileSystem(wd+"/ro")) ufs, err := NewUnionFs(fses, testOpts) if err != nil { t.Fatalf("NewUnionFs: %v", err) } opts := &nodefs.Options{ EntryTimeout: entryTtl, AttrTimeout: entryTtl, NegativeTimeout: entryTtl, } nfs := pathfs.NewPathNodeFs(ufs, nil) state, _, err := nodefs.MountRoot(wd+"/mnt", nfs.Root(), opts) if err != nil { t.Fatalf("MountNodeFileSystem failed: %v", err) } defer state.Unmount() state.SetDebug(VerboseTest()) go state.Serve() err = ioutil.WriteFile(wd+"/ro/file", []byte("blabla"), 0644) if err != nil { t.Fatalf("WriteFile failed: %v", err) } setRecursiveWritable(t, wd+"/ro", false) err = os.Remove(wd + "/mnt/file") if err != nil { t.Fatalf("Remove failed: %v", err) } wrFs.visibleChan <- false time.Sleep((3 * entryTtl) / 2) _, err = ioutil.ReadDir(wd + "/mnt") if err == nil { t.Fatal("Readdir should have failed") } err = ioutil.WriteFile(wd+"/mnt/file2", []byte("blabla"), 0644) if err == nil { t.Fatal("write should have failed") } // Restore, and wait for caches to catch up. wrFs.visibleChan <- true time.Sleep((3 * entryTtl) / 2) _, err = ioutil.ReadDir(wd + "/mnt") if err != nil { t.Fatal("Readdir should succeed", err) } err = ioutil.WriteFile(wd+"/mnt/file2", []byte("blabla"), 0644) if err != nil { t.Fatal("write should succeed", err) } }
func TestFSetAttr(t *testing.T) { fs := pathfs.NewLockingFileSystem(&FSetAttrFs{ FileSystem: pathfs.NewDefaultFileSystem(), }) dir, clean := setupFAttrTest(t, fs) defer clean() fn := dir + "/file" f, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY, 0755) if err != nil { t.Fatalf("OpenFile failed: %v", err) } defer f.Close() fi, err := f.Stat() if err != nil { t.Fatalf("Stat failed: %v", err) } _, err = f.WriteString("hello") if err != nil { t.Fatalf("WriteString failed: %v", err) } code := syscall.Ftruncate(int(f.Fd()), 3) if code != nil { t.Error("truncate retval", os.NewSyscallError("Ftruncate", code)) } if a, status := fs.GetAttr("file", nil); !status.Ok() { t.Fatalf("GetAttr: status %v", status) } else if a.Size != 3 { t.Errorf("truncate: size %d, status %v", a.Size, status) } if err := f.Chmod(024); err != nil { t.Fatalf("Chmod failed: %v", err) } if a, status := fs.GetAttr("file", nil); !status.Ok() { t.Errorf("chmod: %v", status) } else if a.Mode&07777 != 024 { t.Errorf("getattr after chmod: %o", a.Mode&0777) } if err := os.Chtimes(fn, time.Unix(0, 100e3), time.Unix(0, 101e3)); err != nil { t.Fatalf("Chtimes failed: %v", err) } if a, status := fs.GetAttr("file", nil); !status.Ok() { t.Errorf("GetAttr: %v", status) } else if a.Atimensec != 100e3 || a.Mtimensec != 101e3 { t.Errorf("Utimens: atime %d != 100e3 mtime %d != 101e3", a.Atimensec, a.Mtimensec) } newFi, err := f.Stat() if err != nil { t.Fatalf("Stat failed: %v", err) } i1 := fuse.ToStatT(fi).Ino i2 := fuse.ToStatT(newFi).Ino if i1 != i2 { t.Errorf("f.Lstat().Ino = %d. Returned %d before.", i2, i1) } // TODO - test chown if run as root. }