Added flushfs tests involving fdatasync and directories.
For GoogleCloudPlatform/gcsfuse#13.geesefs-0-30-9
commit
02eb1c8e32
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package fsutil
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
const FdatasyncSupported = false
|
||||||
|
|
||||||
|
func fdatasync(f *os.File) error {
|
||||||
|
panic("We require FdatasyncSupported be true.")
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package fsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const FdatasyncSupported = true
|
||||||
|
|
||||||
|
func fdatasync(f *os.File) error {
|
||||||
|
return syscall.Fdatasync(int(f.Fd()))
|
||||||
|
}
|
|
@ -48,3 +48,10 @@ func AnonymousFile(dir string) (f *os.File, err error) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call fdatasync on the supplied file.
|
||||||
|
//
|
||||||
|
// REQUIRES: FdatasyncSupported is true.
|
||||||
|
func Fdatasync(f *os.File) error {
|
||||||
|
return fdatasync(f)
|
||||||
|
}
|
||||||
|
|
|
@ -24,11 +24,14 @@ import (
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create a file system containing a single file named "foo".
|
// Create a file system whose sole contents are a file named "foo" and a
|
||||||
|
// directory named "bar".
|
||||||
//
|
//
|
||||||
// The file may be opened for reading and/or writing. Its initial contents are
|
// The file may be opened for reading and/or writing. Its initial contents are
|
||||||
// empty. Whenever a flush or fsync is received, the supplied function will be
|
// empty. Whenever a flush or fsync is received, the supplied function will be
|
||||||
// called with the current contents of the file and its status returned.
|
// called with the current contents of the file and its status returned.
|
||||||
|
//
|
||||||
|
// The directory cannot be modified.
|
||||||
func NewFileSystem(
|
func NewFileSystem(
|
||||||
reportFlush func(string) error,
|
reportFlush func(string) error,
|
||||||
reportFsync func(string) error) (fs fuse.FileSystem, err error) {
|
reportFsync func(string) error) (fs fuse.FileSystem, err error) {
|
||||||
|
@ -40,7 +43,10 @@ func NewFileSystem(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const fooID = fuse.RootInodeID + 1
|
const (
|
||||||
|
fooID = fuse.RootInodeID + 1 + iota
|
||||||
|
barID
|
||||||
|
)
|
||||||
|
|
||||||
type flushFS struct {
|
type flushFS struct {
|
||||||
fuseutil.NotImplementedFileSystem
|
fuseutil.NotImplementedFileSystem
|
||||||
|
@ -72,6 +78,14 @@ func (fs *flushFS) fooAttributes() fuse.InodeAttributes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LOCKS_REQUIRED(fs.mu)
|
||||||
|
func (fs *flushFS) barAttributes() fuse.InodeAttributes {
|
||||||
|
return fuse.InodeAttributes{
|
||||||
|
Nlink: 1,
|
||||||
|
Mode: 0777 | os.ModeDir,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// File system methods
|
// File system methods
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -94,14 +108,28 @@ func (fs *flushFS) LookUpInode(
|
||||||
defer fs.mu.Unlock()
|
defer fs.mu.Unlock()
|
||||||
|
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
if req.Parent != fuse.RootInodeID || req.Name != "foo" {
|
if req.Parent != fuse.RootInodeID {
|
||||||
err = fuse.ENOENT
|
err = fuse.ENOENT
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Entry = fuse.ChildInodeEntry{
|
// Set up the entry.
|
||||||
Child: fooID,
|
switch req.Name {
|
||||||
Attributes: fs.fooAttributes(),
|
case "foo":
|
||||||
|
resp.Entry = fuse.ChildInodeEntry{
|
||||||
|
Child: fooID,
|
||||||
|
Attributes: fs.fooAttributes(),
|
||||||
|
}
|
||||||
|
|
||||||
|
case "bar":
|
||||||
|
resp.Entry = fuse.ChildInodeEntry{
|
||||||
|
Child: barID,
|
||||||
|
Attributes: fs.barAttributes(),
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = fuse.ENOENT
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -125,6 +153,10 @@ func (fs *flushFS) GetInodeAttributes(
|
||||||
resp.Attributes = fs.fooAttributes()
|
resp.Attributes = fs.fooAttributes()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
case barID:
|
||||||
|
resp.Attributes = fs.barAttributes()
|
||||||
|
return
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = fuse.ENOENT
|
err = fuse.ENOENT
|
||||||
return
|
return
|
||||||
|
@ -222,3 +254,21 @@ func (fs *flushFS) FlushFile(
|
||||||
err = fs.reportFlush(string(fs.fooContents))
|
err = fs.reportFlush(string(fs.fooContents))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fs *flushFS) OpenDir(
|
||||||
|
ctx context.Context,
|
||||||
|
req *fuse.OpenDirRequest) (
|
||||||
|
resp *fuse.OpenDirResponse, err error) {
|
||||||
|
resp = &fuse.OpenDirResponse{}
|
||||||
|
|
||||||
|
fs.mu.Lock()
|
||||||
|
defer fs.mu.Unlock()
|
||||||
|
|
||||||
|
// Sanity check.
|
||||||
|
if req.Inode != barID {
|
||||||
|
err = fuse.ENOSYS
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -409,6 +409,49 @@ func (t *NoErrorsTest) Fsync() {
|
||||||
AssertThat(t.getFsyncs(), ElementsAre("taco", "tacos"))
|
AssertThat(t.getFsyncs(), ElementsAre("taco", "tacos"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *NoErrorsTest) Fdatasync() {
|
||||||
|
var n int
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if !fsutil.FdatasyncSupported {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the file.
|
||||||
|
t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_WRONLY, 0)
|
||||||
|
AssertEq(nil, err)
|
||||||
|
|
||||||
|
// Write some contents to the file.
|
||||||
|
n, err = t.f1.Write([]byte("taco"))
|
||||||
|
AssertEq(nil, err)
|
||||||
|
AssertEq(4, n)
|
||||||
|
|
||||||
|
AssertThat(t.getFlushes(), ElementsAre())
|
||||||
|
AssertThat(t.getFsyncs(), ElementsAre())
|
||||||
|
|
||||||
|
// Fdatasync.
|
||||||
|
err = fsutil.Fdatasync(t.f1)
|
||||||
|
AssertEq(nil, err)
|
||||||
|
|
||||||
|
AssertThat(t.getFlushes(), ElementsAre())
|
||||||
|
AssertThat(t.getFsyncs(), ElementsAre("taco"))
|
||||||
|
|
||||||
|
// Write some more contents.
|
||||||
|
n, err = t.f1.Write([]byte("s"))
|
||||||
|
AssertEq(nil, err)
|
||||||
|
AssertEq(1, n)
|
||||||
|
|
||||||
|
AssertThat(t.getFlushes(), ElementsAre())
|
||||||
|
AssertThat(t.getFsyncs(), ElementsAre("taco"))
|
||||||
|
|
||||||
|
// Fdatasync.
|
||||||
|
err = fsutil.Fdatasync(t.f1)
|
||||||
|
AssertEq(nil, err)
|
||||||
|
|
||||||
|
AssertThat(t.getFlushes(), ElementsAre())
|
||||||
|
AssertThat(t.getFsyncs(), ElementsAre("taco", "tacos"))
|
||||||
|
}
|
||||||
|
|
||||||
func (t *NoErrorsTest) Dup() {
|
func (t *NoErrorsTest) Dup() {
|
||||||
var n int
|
var n int
|
||||||
var err error
|
var err error
|
||||||
|
@ -614,7 +657,29 @@ func (t *NoErrorsTest) Mmap_CloseBeforeMunmap() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *NoErrorsTest) Directory() {
|
func (t *NoErrorsTest) Directory() {
|
||||||
AssertTrue(false, "TODO")
|
var err error
|
||||||
|
|
||||||
|
// Open the directory.
|
||||||
|
t.f1, err = os.Open(path.Join(t.Dir, "bar"))
|
||||||
|
AssertEq(nil, err)
|
||||||
|
|
||||||
|
// Sanity check: stat it.
|
||||||
|
fi, err := t.f1.Stat()
|
||||||
|
AssertEq(nil, err)
|
||||||
|
AssertEq(0777|os.ModeDir, fi.Mode())
|
||||||
|
|
||||||
|
// Sync it.
|
||||||
|
err = t.f1.Sync()
|
||||||
|
AssertEq(nil, err)
|
||||||
|
|
||||||
|
// Close it.
|
||||||
|
err = t.f1.Close()
|
||||||
|
t.f1 = nil
|
||||||
|
AssertEq(nil, err)
|
||||||
|
|
||||||
|
// No flushes or fsync requests should have been received.
|
||||||
|
ExpectThat(t.getFlushes(), ElementsAre())
|
||||||
|
ExpectThat(t.getFsyncs(), ElementsAre())
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -643,7 +708,6 @@ func (t *FlushErrorTest) Close() {
|
||||||
err = t.f1.Close()
|
err = t.f1.Close()
|
||||||
t.f1 = nil
|
t.f1 = nil
|
||||||
|
|
||||||
AssertNe(nil, err)
|
|
||||||
ExpectThat(err, Error(HasSubstr("no such file")))
|
ExpectThat(err, Error(HasSubstr("no such file")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,7 +735,6 @@ func (t *FlushErrorTest) Dup() {
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
AssertEq(nil, err)
|
AssertEq(nil, err)
|
||||||
} else {
|
} else {
|
||||||
AssertNe(nil, err)
|
|
||||||
ExpectThat(err, Error(HasSubstr("no such file")))
|
ExpectThat(err, Error(HasSubstr("no such file")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,7 +742,6 @@ func (t *FlushErrorTest) Dup() {
|
||||||
err = t.f2.Close()
|
err = t.f2.Close()
|
||||||
t.f2 = nil
|
t.f2 = nil
|
||||||
|
|
||||||
AssertNe(nil, err)
|
|
||||||
ExpectThat(err, Error(HasSubstr("no such file")))
|
ExpectThat(err, Error(HasSubstr("no such file")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,6 +787,22 @@ func (t *FsyncErrorTest) Fsync() {
|
||||||
// Fsync.
|
// Fsync.
|
||||||
err = t.f1.Sync()
|
err = t.f1.Sync()
|
||||||
|
|
||||||
AssertNe(nil, err)
|
ExpectThat(err, Error(HasSubstr("no such file")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *FsyncErrorTest) Fdatasync() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if !fsutil.FdatasyncSupported {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the file.
|
||||||
|
t.f1, err = os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0)
|
||||||
|
AssertEq(nil, err)
|
||||||
|
|
||||||
|
// Fdatasync.
|
||||||
|
err = fsutil.Fdatasync(t.f1)
|
||||||
|
|
||||||
ExpectThat(err, Error(HasSubstr("no such file")))
|
ExpectThat(err, Error(HasSubstr("no such file")))
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ var fToolPath = flag.String(
|
||||||
"",
|
"",
|
||||||
"Path to the mount_sample tool. If unset, we will compile it.")
|
"Path to the mount_sample tool. If unset, we will compile it.")
|
||||||
|
|
||||||
|
var fDebug = flag.Bool("debug", false, "If true, print fuse debug info.")
|
||||||
|
|
||||||
// A struct that implements common behavior needed by tests in the samples/
|
// A struct that implements common behavior needed by tests in the samples/
|
||||||
// directory where the file system is mounted by a subprocess. Use it as an
|
// directory where the file system is mounted by a subprocess. Use it as an
|
||||||
// embedded field in your test fixture, calling its SetUp method from your
|
// embedded field in your test fixture, calling its SetUp method from your
|
||||||
|
@ -273,7 +275,13 @@ func (t *SubprocessTest) initialize() (err error) {
|
||||||
mountCmd.Stderr = &stderr
|
mountCmd.Stderr = &stderr
|
||||||
mountCmd.ExtraFiles = extraFiles
|
mountCmd.ExtraFiles = extraFiles
|
||||||
|
|
||||||
// Start it.
|
// Handle debug mode.
|
||||||
|
if *fDebug {
|
||||||
|
mountCmd.Stderr = os.Stderr
|
||||||
|
mountCmd.Args = append(mountCmd.Args, "--fuse.debug")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the command.
|
||||||
if err = mountCmd.Start(); err != nil {
|
if err = mountCmd.Start(); err != nil {
|
||||||
err = fmt.Errorf("mountCmd.Start: %v", err)
|
err = fmt.Errorf("mountCmd.Start: %v", err)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue