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
|
||||
}
|
||||
|
||||
// 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"
|
||||
)
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
//
|
||||
// The directory cannot be modified.
|
||||
func NewFileSystem(
|
||||
reportFlush func(string) error,
|
||||
reportFsync func(string) error) (fs fuse.FileSystem, err error) {
|
||||
|
@ -40,7 +43,10 @@ func NewFileSystem(
|
|||
return
|
||||
}
|
||||
|
||||
const fooID = fuse.RootInodeID + 1
|
||||
const (
|
||||
fooID = fuse.RootInodeID + 1 + iota
|
||||
barID
|
||||
)
|
||||
|
||||
type flushFS struct {
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -94,14 +108,28 @@ func (fs *flushFS) LookUpInode(
|
|||
defer fs.mu.Unlock()
|
||||
|
||||
// Sanity check.
|
||||
if req.Parent != fuse.RootInodeID || req.Name != "foo" {
|
||||
if req.Parent != fuse.RootInodeID {
|
||||
err = fuse.ENOENT
|
||||
return
|
||||
}
|
||||
|
||||
resp.Entry = fuse.ChildInodeEntry{
|
||||
Child: fooID,
|
||||
Attributes: fs.fooAttributes(),
|
||||
// Set up the entry.
|
||||
switch req.Name {
|
||||
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
|
||||
|
@ -125,6 +153,10 @@ func (fs *flushFS) GetInodeAttributes(
|
|||
resp.Attributes = fs.fooAttributes()
|
||||
return
|
||||
|
||||
case barID:
|
||||
resp.Attributes = fs.barAttributes()
|
||||
return
|
||||
|
||||
default:
|
||||
err = fuse.ENOENT
|
||||
return
|
||||
|
@ -222,3 +254,21 @@ func (fs *flushFS) FlushFile(
|
|||
err = fs.reportFlush(string(fs.fooContents))
|
||||
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"))
|
||||
}
|
||||
|
||||
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() {
|
||||
var n int
|
||||
var err error
|
||||
|
@ -614,7 +657,29 @@ func (t *NoErrorsTest) Mmap_CloseBeforeMunmap() {
|
|||
}
|
||||
|
||||
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()
|
||||
t.f1 = nil
|
||||
|
||||
AssertNe(nil, err)
|
||||
ExpectThat(err, Error(HasSubstr("no such file")))
|
||||
}
|
||||
|
||||
|
@ -671,7 +735,6 @@ func (t *FlushErrorTest) Dup() {
|
|||
if runtime.GOOS == "darwin" {
|
||||
AssertEq(nil, err)
|
||||
} else {
|
||||
AssertNe(nil, err)
|
||||
ExpectThat(err, Error(HasSubstr("no such file")))
|
||||
}
|
||||
|
||||
|
@ -679,7 +742,6 @@ func (t *FlushErrorTest) Dup() {
|
|||
err = t.f2.Close()
|
||||
t.f2 = nil
|
||||
|
||||
AssertNe(nil, err)
|
||||
ExpectThat(err, Error(HasSubstr("no such file")))
|
||||
}
|
||||
|
||||
|
@ -725,6 +787,22 @@ func (t *FsyncErrorTest) Fsync() {
|
|||
// Fsync.
|
||||
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")))
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ var fToolPath = flag.String(
|
|||
"",
|
||||
"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/
|
||||
// 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
|
||||
|
@ -273,7 +275,13 @@ func (t *SubprocessTest) initialize() (err error) {
|
|||
mountCmd.Stderr = &stderr
|
||||
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 {
|
||||
err = fmt.Errorf("mountCmd.Start: %v", err)
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue