Commit 0155dffe authored by Adam H. Leventhal's avatar Adam H. Leventhal Committed by Han-Wen Nienhuys

Fixed all tests on Darwin

Fixed handling of ENOSYS in unionfs.
parent bddfd80b
...@@ -104,8 +104,7 @@ go-fuse works somewhat on OSX. Known limitations: ...@@ -104,8 +104,7 @@ go-fuse works somewhat on OSX. Known limitations:
* OSX has trouble with concurrent reads from the FUSE device, leading * OSX has trouble with concurrent reads from the FUSE device, leading
to performance concerns. to performance concerns.
* A bunch of tests under fuse/test/ fail, and the functionality they * Tests are expected to pass; report any failure as a bug!
test for OSX is likely broken.
CREDITS CREDITS
......
...@@ -17,11 +17,12 @@ func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut { ...@@ -17,11 +17,12 @@ func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut {
if err == nil { if err == nil {
return &fuse.StatfsOut{ return &fuse.StatfsOut{
Blocks: s.Blocks, Blocks: s.Blocks,
Bsize: uint32(s.Bsize),
Bfree: s.Bfree, Bfree: s.Bfree,
Bavail: s.Bavail, Bavail: s.Bavail,
Files: s.Files, Files: s.Files,
Ffree: s.Ffree, Ffree: s.Ffree,
Bsize: uint32(s.Iosize), // Iosize translates to Bsize: the optimal transfer size.
Frsize: s.Bsize, // Bsize translates to Frsize: the minimum transfer size.
} }
} }
return nil return nil
...@@ -58,6 +59,6 @@ func (fs *loopbackFileSystem) Utimens(path string, a *time.Time, m *time.Time, c ...@@ -58,6 +59,6 @@ func (fs *loopbackFileSystem) Utimens(path string, a *time.Time, m *time.Time, c
tv[1] = timeToTimeval(m) tv[1] = timeToTimeval(m)
} }
err := syscall.Utimes(path, tv) err := syscall.Utimes(fs.GetPath(path), tv)
return fuse.ToStatus(err) return fuse.ToStatus(err)
} }
...@@ -10,9 +10,15 @@ import ( ...@@ -10,9 +10,15 @@ import (
func clearStatfs(s *syscall.Statfs_t) { func clearStatfs(s *syscall.Statfs_t) {
empty := syscall.Statfs_t{} empty := syscall.Statfs_t{}
s.Type = 0
s.Fsid = empty.Fsid // FUSE can only set the following fields.
// s.Spare = empty.Spare empty.Blocks = s.Blocks
// TODO - figure out what this is for. empty.Bfree = s.Bfree
s.Flags = 0 empty.Bavail = s.Bavail
empty.Files = s.Files
empty.Ffree = s.Ffree
empty.Iosize = s.Iosize
empty.Bsize = s.Bsize
// Clear out the rest.
*s = empty
} }
...@@ -301,40 +301,33 @@ func (fs *autoUnionFs) GetXAttr(name string, attr string, context *fuse.Context) ...@@ -301,40 +301,33 @@ func (fs *autoUnionFs) GetXAttr(name string, attr string, context *fuse.Context)
} }
func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr, fuse.Status) { func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
if path == "" || path == _CONFIG || path == _STATUS {
a := &fuse.Attr{ a := &fuse.Attr{
Mode: fuse.S_IFDIR | 0755, Owner: *fuse.CurrentOwner(),
} }
if path == "" || path == _CONFIG || path == _STATUS {
a.Mode = fuse.S_IFDIR | 0755
return a, fuse.OK return a, fuse.OK
} }
if path == filepath.Join(_STATUS, _VERSION) { if path == filepath.Join(_STATUS, _VERSION) {
a := &fuse.Attr{ a.Mode = fuse.S_IFREG | 0644
Mode: fuse.S_IFREG | 0644, a.Size = uint64(len(fs.options.Version))
Size: uint64(len(fs.options.Version)),
}
return a, fuse.OK return a, fuse.OK
} }
if path == filepath.Join(_STATUS, _DEBUG) { if path == filepath.Join(_STATUS, _DEBUG) {
a := &fuse.Attr{ a.Mode = fuse.S_IFREG | 0644
Mode: fuse.S_IFREG | 0644, a.Size = uint64(len(fs.DebugData()))
Size: uint64(len(fs.DebugData())),
}
return a, fuse.OK return a, fuse.OK
} }
if path == filepath.Join(_STATUS, _ROOT) { if path == filepath.Join(_STATUS, _ROOT) {
a := &fuse.Attr{ a.Mode = syscall.S_IFLNK | 0644
Mode: syscall.S_IFLNK | 0644,
}
return a, fuse.OK return a, fuse.OK
} }
if path == filepath.Join(_CONFIG, _SCAN_CONFIG) { if path == filepath.Join(_CONFIG, _SCAN_CONFIG) {
a := &fuse.Attr{ a.Mode = fuse.S_IFREG | 0644
Mode: fuse.S_IFREG | 0644,
}
return a, fuse.OK return a, fuse.OK
} }
comps := strings.Split(path, string(filepath.Separator)) comps := strings.Split(path, string(filepath.Separator))
...@@ -346,9 +339,7 @@ func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr, ...@@ -346,9 +339,7 @@ func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr,
return nil, fuse.ENOENT return nil, fuse.ENOENT
} }
a := &fuse.Attr{ a.Mode = syscall.S_IFLNK | 0644
Mode: syscall.S_IFLNK | 0644,
}
return a, fuse.OK return a, fuse.OK
} }
......
...@@ -23,6 +23,7 @@ var testAOpts = AutoUnionFsOptions{ ...@@ -23,6 +23,7 @@ var testAOpts = AutoUnionFsOptions{
EntryTimeout: entryTtl, EntryTimeout: entryTtl,
AttrTimeout: entryTtl, AttrTimeout: entryTtl,
NegativeTimeout: 0, NegativeTimeout: 0,
Debug: VerboseTest(),
}, },
HideReadonly: true, HideReadonly: true,
Version: "version", Version: "version",
...@@ -39,7 +40,7 @@ func WriteFile(t *testing.T, name string, contents string) { ...@@ -39,7 +40,7 @@ func WriteFile(t *testing.T, name string, contents string) {
} }
} }
func setup(t *testing.T) (workdir string, cleanup func()) { func setup(t *testing.T) (workdir string, server *fuse.Server, cleanup func()) {
wd, _ := ioutil.TempDir("", "") wd, _ := ioutil.TempDir("", "")
err := os.Mkdir(wd+"/mnt", 0700) err := os.Mkdir(wd+"/mnt", 0700)
if err != nil { if err != nil {
...@@ -66,15 +67,16 @@ func setup(t *testing.T) (workdir string, cleanup func()) { ...@@ -66,15 +67,16 @@ func setup(t *testing.T) (workdir string, cleanup func()) {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
go state.Serve() go state.Serve()
state.WaitMount()
return wd, func() { return wd, state, func() {
state.Unmount() state.Unmount()
os.RemoveAll(wd) os.RemoveAll(wd)
} }
} }
func TestDebug(t *testing.T) { func TestDebug(t *testing.T) {
wd, clean := setup(t) wd, _, clean := setup(t)
defer clean() defer clean()
c, err := ioutil.ReadFile(wd + "/mnt/status/debug") c, err := ioutil.ReadFile(wd + "/mnt/status/debug")
...@@ -87,7 +89,7 @@ func TestDebug(t *testing.T) { ...@@ -87,7 +89,7 @@ func TestDebug(t *testing.T) {
} }
func TestVersion(t *testing.T) { func TestVersion(t *testing.T) {
wd, clean := setup(t) wd, _, clean := setup(t)
defer clean() defer clean()
c, err := ioutil.ReadFile(wd + "/mnt/status/gounionfs_version") c, err := ioutil.ReadFile(wd + "/mnt/status/gounionfs_version")
...@@ -100,7 +102,7 @@ func TestVersion(t *testing.T) { ...@@ -100,7 +102,7 @@ func TestVersion(t *testing.T) {
} }
func TestAutoFsSymlink(t *testing.T) { func TestAutoFsSymlink(t *testing.T) {
wd, clean := setup(t) wd, server, clean := setup(t)
defer clean() defer clean()
err := os.Mkdir(wd+"/store/backing1", 0755) err := os.Mkdir(wd+"/store/backing1", 0755)
...@@ -142,15 +144,23 @@ func TestAutoFsSymlink(t *testing.T) { ...@@ -142,15 +144,23 @@ func TestAutoFsSymlink(t *testing.T) {
t.Error("error writing:", err) t.Error("error writing:", err)
} }
// If FUSE supports invalid inode notifications we expect this node to be gone. Otherwise we'll just make sure that it's not reachable.
if server.KernelSettings().SupportsNotify(fuse.NOTIFY_INVAL_INODE) {
fi, _ = os.Lstat(wd + "/mnt/manual1") fi, _ = os.Lstat(wd + "/mnt/manual1")
if fi != nil { if fi != nil {
t.Error("Should not have file:", fi) t.Error("Should not have file:", fi)
} }
} else {
_, err = ioutil.ReadDir(wd + "/mnt/config") entries, err = ioutil.ReadDir(wd + "/mnt")
if err != nil { if err != nil {
t.Fatalf("ReadDir failed: %v", err) t.Fatalf("ReadDir failed: %v", err)
} }
for _, e := range entries {
if e.Name() == "manual1" {
t.Error("Should not have entry: ", e)
}
}
}
_, err = os.Lstat(wd + "/mnt/backing1/file1") _, err = os.Lstat(wd + "/mnt/backing1/file1")
if err != nil { if err != nil {
...@@ -159,7 +169,7 @@ func TestAutoFsSymlink(t *testing.T) { ...@@ -159,7 +169,7 @@ func TestAutoFsSymlink(t *testing.T) {
} }
func TestDetectSymlinkedDirectories(t *testing.T) { func TestDetectSymlinkedDirectories(t *testing.T) {
wd, clean := setup(t) wd, _, clean := setup(t)
defer clean() defer clean()
err := os.Mkdir(wd+"/backing1", 0755) err := os.Mkdir(wd+"/backing1", 0755)
...@@ -190,7 +200,7 @@ func TestDetectSymlinkedDirectories(t *testing.T) { ...@@ -190,7 +200,7 @@ func TestDetectSymlinkedDirectories(t *testing.T) {
} }
func TestExplicitScan(t *testing.T) { func TestExplicitScan(t *testing.T) {
wd, clean := setup(t) wd, _, clean := setup(t)
defer clean() defer clean()
err := os.Mkdir(wd+"/store/backing1", 0755) err := os.Mkdir(wd+"/store/backing1", 0755)
...@@ -225,7 +235,7 @@ func TestExplicitScan(t *testing.T) { ...@@ -225,7 +235,7 @@ func TestExplicitScan(t *testing.T) {
} }
func TestCreationChecks(t *testing.T) { func TestCreationChecks(t *testing.T) {
wd, clean := setup(t) wd, _, clean := setup(t)
defer clean() defer clean()
err := os.Mkdir(wd+"/store/foo", 0755) err := os.Mkdir(wd+"/store/foo", 0755)
......
...@@ -570,7 +570,7 @@ func (fs *unionFS) Chmod(name string, mode uint32, context *fuse.Context) (code ...@@ -570,7 +570,7 @@ func (fs *unionFS) Chmod(name string, mode uint32, context *fuse.Context) (code
func (fs *unionFS) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) { func (fs *unionFS) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
// We always allow writing. // We always allow writing.
mode = mode &^ fuse.W_OK mode = mode &^ fuse.W_OK
if name == "" { if name == "" || name == _DROP_CACHE {
return fuse.OK return fuse.OK
} }
r := fs.getBranch(name) r := fs.getBranch(name)
......
...@@ -106,6 +106,7 @@ func setupUfs(t *testing.T) (wd string, cleanup func()) { ...@@ -106,6 +106,7 @@ func setupUfs(t *testing.T) (wd string, cleanup func()) {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
go state.Serve() go state.Serve()
state.WaitMount()
return wd, func() { return wd, func() {
err := state.Unmount() err := state.Unmount()
...@@ -243,8 +244,9 @@ func TestUnionFsChtimes(t *testing.T) { ...@@ -243,8 +244,9 @@ func TestUnionFsChtimes(t *testing.T) {
} }
fi, err := os.Lstat(wd + "/mnt/file") fi, err := os.Lstat(wd + "/mnt/file")
stat := fuse.ToStatT(fi) attr := &fuse.Attr{}
if stat.Atim.Sec != 82 || stat.Mtim.Sec != 83 { attr.FromStat(fuse.ToStatT(fi))
if attr.Atime != 82 || attr.Mtime != 83 {
t.Error("Incorrect timestamp", fi) t.Error("Incorrect timestamp", fi)
} }
} }
...@@ -1168,6 +1170,7 @@ func TestUnionFsDisappearing(t *testing.T) { ...@@ -1168,6 +1170,7 @@ func TestUnionFsDisappearing(t *testing.T) {
} }
defer state.Unmount() defer state.Unmount()
go state.Serve() go state.Serve()
state.WaitMount()
err = ioutil.WriteFile(wd+"/ro/file", []byte("blabla"), 0644) err = ioutil.WriteFile(wd+"/ro/file", []byte("blabla"), 0644)
if err != nil { if err != nil {
...@@ -1193,9 +1196,9 @@ func TestUnionFsDisappearing(t *testing.T) { ...@@ -1193,9 +1196,9 @@ func TestUnionFsDisappearing(t *testing.T) {
t.Fatal("write should have failed") t.Fatal("write should have failed")
} }
// Restore, and wait for caches to catch up. // Wait for the caches to purge, and then restore.
wrFs.visibleChan <- true
time.Sleep((3 * entryTtl) / 2) time.Sleep((3 * entryTtl) / 2)
wrFs.visibleChan <- true
_, err = ioutil.ReadDir(wd + "/mnt") _, err = ioutil.ReadDir(wd + "/mnt")
if err != nil { if err != nil {
...@@ -1281,41 +1284,6 @@ func TestUnionFsDoubleOpen(t *testing.T) { ...@@ -1281,41 +1284,6 @@ func TestUnionFsDoubleOpen(t *testing.T) {
} }
} }
func TestUnionFsFdLeak(t *testing.T) {
beforeEntries, err := ioutil.ReadDir("/proc/self/fd")
if err != nil {
t.Fatalf("ReadDir failed: %v", err)
}
wd, clean := setupUfs(t)
err = ioutil.WriteFile(wd+"/ro/file", []byte("blablabla"), 0644)
if err != nil {
t.Fatalf("WriteFile failed: %v", err)
}
setRecursiveWritable(t, wd+"/ro", false)
contents, err := ioutil.ReadFile(wd + "/mnt/file")
if err != nil {
t.Fatalf("ReadFile failed: %v", err)
}
err = ioutil.WriteFile(wd+"/mnt/file", contents, 0644)
if err != nil {
t.Fatalf("WriteFile failed: %v", err)
}
clean()
afterEntries, err := ioutil.ReadDir("/proc/self/fd")
if err != nil {
t.Fatalf("ReadDir failed: %v", err)
}
if len(afterEntries) != len(beforeEntries) {
t.Errorf("/proc/self/fd changed size: after %v before %v", len(beforeEntries), len(afterEntries))
}
}
func TestUnionFsStatFs(t *testing.T) { func TestUnionFsStatFs(t *testing.T) {
wd, clean := setupUfs(t) wd, clean := setupUfs(t)
defer clean() defer clean()
......
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package unionfs
import (
"io/ioutil"
)
func TestUnionFsFdLeak(t *testing.T) {
beforeEntries, err := ioutil.ReadDir("/proc/self/fd")
if err != nil {
t.Fatalf("ReadDir failed: %v", err)
}
wd, clean := setupUfs(t)
err = ioutil.WriteFile(wd+"/ro/file", []byte("blablabla"), 0644)
if err != nil {
t.Fatalf("WriteFile failed: %v", err)
}
setRecursiveWritable(t, wd+"/ro", false)
contents, err := ioutil.ReadFile(wd + "/mnt/file")
if err != nil {
t.Fatalf("ReadFile failed: %v", err)
}
err = ioutil.WriteFile(wd+"/mnt/file", contents, 0644)
if err != nil {
t.Fatalf("WriteFile failed: %v", err)
}
clean()
afterEntries, err := ioutil.ReadDir("/proc/self/fd")
if err != nil {
t.Fatalf("ReadDir failed: %v", err)
}
if len(afterEntries) != len(beforeEntries) {
t.Errorf("/proc/self/fd changed size: after %v before %v", len(beforeEntries), len(afterEntries))
}
}
...@@ -7,7 +7,6 @@ package unionfs ...@@ -7,7 +7,6 @@ package unionfs
import ( import (
"io/ioutil" "io/ioutil"
"os" "os"
"syscall"
"testing" "testing"
"time" "time"
...@@ -76,13 +75,14 @@ func TestXAttrCaching(t *testing.T) { ...@@ -76,13 +75,14 @@ func TestXAttrCaching(t *testing.T) {
} }
defer server.Unmount() defer server.Unmount()
go server.Serve() go server.Serve()
server.WaitMount()
if fi, err := os.Lstat(wd + "/mnt"); err != nil || !fi.IsDir() { if fi, err := os.Lstat(wd + "/mnt"); err != nil || !fi.IsDir() {
t.Fatalf("root not readable: %v, %v", err, fi) t.Fatalf("root not readable: %v, %v", err, fi)
} }
buf := make([]byte, 1024) buf := make([]byte, 1024)
n, err := syscall.Getxattr(wd+"/mnt/file", "user.attr", buf) n, err := Getxattr(wd+"/mnt/file", "user.attr", buf)
if err != nil { if err != nil {
t.Fatalf("Getxattr: %v", err) t.Fatalf("Getxattr: %v", err)
} }
...@@ -91,8 +91,10 @@ func TestXAttrCaching(t *testing.T) { ...@@ -91,8 +91,10 @@ func TestXAttrCaching(t *testing.T) {
if got != want { if got != want {
t.Fatalf("Got %q want %q", got, err) t.Fatalf("Got %q want %q", got, err)
} }
time.Sleep(entryTtl / 2)
n, err = syscall.Getxattr(wd+"/mnt/file", "user.attr", buf) time.Sleep(entryTtl / 3)
n, err = Getxattr(wd+"/mnt/file", "user.attr", buf)
if err != nil { if err != nil {
t.Fatalf("Getxattr: %v", err) t.Fatalf("Getxattr: %v", err)
} }
...@@ -100,7 +102,21 @@ func TestXAttrCaching(t *testing.T) { ...@@ -100,7 +102,21 @@ func TestXAttrCaching(t *testing.T) {
if got != want { if got != want {
t.Fatalf("Got %q want %q", got, err) t.Fatalf("Got %q want %q", got, err)
} }
server.Unmount()
time.Sleep(entryTtl / 3)
// Make sure that an interceding Getxattr() to a filesystem that doesn't implement GetXAttr() doesn't affect future calls.
Getxattr(wd, "whatever", buf)
n, err = Getxattr(wd+"/mnt/file", "user.attr", buf)
if err != nil {
t.Fatalf("Getxattr: %v", err)
}
got = string(buf[:n])
if got != want {
t.Fatalf("Got %q want %q", got, err)
}
if roFS.xattrRead != 1 { if roFS.xattrRead != 1 {
t.Errorf("got xattrRead=%d, want 1", roFS.xattrRead) t.Errorf("got xattrRead=%d, want 1", roFS.xattrRead)
} }
......
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package unionfs
import (
"syscall"
"unsafe"
)
// Darwin doesn't have support for syscall.Getxattr() so we pull it into its own file and implement it by hand on Darwin.
func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
var _p0 *byte
_p0, err = syscall.BytePtrFromString(path)
if err != nil {
return
}
var _p1 *byte
_p1, err = syscall.BytePtrFromString(attr)
if err != nil {
return
}
var _p2 unsafe.Pointer
if len(dest) > 0 {
_p2 = unsafe.Pointer(&dest[0])
} else {
var _zero uintptr
_p2 = unsafe.Pointer(&_zero)
}
r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
sz = int(r0)
if e1 != 0 {
err = e1
}
return
}
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package unionfs
import (
"syscall"
)
// Darwin doesn't have support for syscall.Getxattr() so we pull it into its own file and implement it by hand on Darwin.
func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
return syscall.Getxattr(path, attr, dest)
}
...@@ -87,6 +87,7 @@ func (fs *MultiZipFs) OpenDir(name string, context *fuse.Context) (stream []fuse ...@@ -87,6 +87,7 @@ func (fs *MultiZipFs) OpenDir(name string, context *fuse.Context) (stream []fuse
func (fs *MultiZipFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) { func (fs *MultiZipFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
a := &fuse.Attr{} a := &fuse.Attr{}
a.Owner = *fuse.CurrentOwner()
if name == "" { if name == "" {
// Should not write in top dir. // Should not write in top dir.
a.Mode = fuse.S_IFDIR | 0500 a.Mode = fuse.S_IFDIR | 0500
...@@ -137,7 +138,7 @@ func (fs *MultiZipFs) Unlink(name string, context *fuse.Context) (code fuse.Stat ...@@ -137,7 +138,7 @@ func (fs *MultiZipFs) Unlink(name string, context *fuse.Context) (code fuse.Stat
delete(fs.zips, basename) delete(fs.zips, basename)
delete(fs.dirZipFileMap, basename) delete(fs.dirZipFileMap, basename)
// Drop lock to ensure that notify doesn't cause deadlock. // Drop the lock to ensure that notify doesn't cause a deadlock.
fs.lock.Unlock() fs.lock.Unlock()
code = fs.nodeFs.UnmountNode(root.Inode()) code = fs.nodeFs.UnmountNode(root.Inode())
fs.lock.Lock() fs.lock.Lock()
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs" "github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs" "github.com/hanwen/go-fuse/fuse/pathfs"
) )
...@@ -23,7 +24,7 @@ func VerboseTest() bool { ...@@ -23,7 +24,7 @@ func VerboseTest() bool {
const testTtl = 100 * time.Millisecond const testTtl = 100 * time.Millisecond
func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) { func setupMzfs(t *testing.T) (mountPoint string, state *fuse.Server, cleanup func()) {
fs := NewMultiZipFs() fs := NewMultiZipFs()
mountPoint, _ = ioutil.TempDir("", "") mountPoint, _ = ioutil.TempDir("", "")
nfs := pathfs.NewPathNodeFs(fs, nil) nfs := pathfs.NewPathNodeFs(fs, nil)
...@@ -37,15 +38,16 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) { ...@@ -37,15 +38,16 @@ func setupMzfs(t *testing.T) (mountPoint string, cleanup func()) {
t.Fatalf("MountNodeFileSystem failed: %v", err) t.Fatalf("MountNodeFileSystem failed: %v", err)
} }
go state.Serve() go state.Serve()
state.WaitMount()
return mountPoint, func() { return mountPoint, state, func() {
state.Unmount() state.Unmount()
os.RemoveAll(mountPoint) os.RemoveAll(mountPoint)
} }
} }
func TestMultiZipReadonly(t *testing.T) { func TestMultiZipReadonly(t *testing.T) {
mountPoint, cleanup := setupMzfs(t) mountPoint, _, cleanup := setupMzfs(t)
defer cleanup() defer cleanup()
_, err := os.Create(mountPoint + "/random") _, err := os.Create(mountPoint + "/random")
...@@ -60,7 +62,7 @@ func TestMultiZipReadonly(t *testing.T) { ...@@ -60,7 +62,7 @@ func TestMultiZipReadonly(t *testing.T) {
} }
func TestMultiZipFs(t *testing.T) { func TestMultiZipFs(t *testing.T) {
mountPoint, cleanup := setupMzfs(t) mountPoint, server, cleanup := setupMzfs(t)
defer cleanup() defer cleanup()
zipFile := testZipFile() zipFile := testZipFile()
...@@ -122,8 +124,22 @@ func TestMultiZipFs(t *testing.T) { ...@@ -122,8 +124,22 @@ func TestMultiZipFs(t *testing.T) {
t.Fatalf("Remove failed: %v", err) t.Fatalf("Remove failed: %v", err)
} }
// If FUSE supports invalid inode notifications we expect this node to be gone. Otherwise we'll just make sure that it's not reachable.
if server.KernelSettings().SupportsNotify(fuse.NOTIFY_INVAL_INODE) {
fi, err = os.Stat(mountPoint + "/zipmount") fi, err = os.Stat(mountPoint + "/zipmount")
if err == nil { if err == nil {
t.Errorf("stat should fail after unmount, got %#v", fi) t.Errorf("stat should fail after unmount, got %#v", fi)
} }
} else {
entries, err = ioutil.ReadDir(mountPoint)
if err != nil {
t.Fatalf("ReadDir failed: %v", err)
}
for _, e := range entries {
if e.Name() == "zipmount" {
t.Error("Should not have entry: ", e)
}
}
}
} }
...@@ -36,6 +36,7 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) { ...@@ -36,6 +36,7 @@ func setupZipfs(t *testing.T) (mountPoint string, cleanup func()) {
}) })
go state.Serve() go state.Serve()
state.WaitMount()
return mountPoint, func() { return mountPoint, func() {
state.Unmount() state.Unmount()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment