summaryrefslogtreecommitdiffhomepage
path: root/pkg/p9/p9test
diff options
context:
space:
mode:
authorGoogler <noreply@google.com>2018-04-27 10:37:02 -0700
committerAdin Scannell <ascannell@google.com>2018-04-28 01:44:26 -0400
commitd02b74a5dcfed4bfc8f2f8e545bca4d2afabb296 (patch)
tree54f95eef73aee6bacbfc736fffc631be2605ed53 /pkg/p9/p9test
parentf70210e742919f40aa2f0934a22f1c9ba6dada62 (diff)
Check in gVisor.
PiperOrigin-RevId: 194583126 Change-Id: Ica1d8821a90f74e7e745962d71801c598c652463
Diffstat (limited to 'pkg/p9/p9test')
-rw-r--r--pkg/p9/p9test/BUILD28
-rw-r--r--pkg/p9/p9test/client_test.go335
-rw-r--r--pkg/p9/p9test/mocks.go490
3 files changed, 853 insertions, 0 deletions
diff --git a/pkg/p9/p9test/BUILD b/pkg/p9/p9test/BUILD
new file mode 100644
index 000000000..339c86089
--- /dev/null
+++ b/pkg/p9/p9test/BUILD
@@ -0,0 +1,28 @@
+package(licenses = ["notice"]) # Apache 2.0
+
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+
+go_test(
+ name = "p9test_test",
+ size = "small",
+ srcs = ["client_test.go"],
+ embed = [":p9test"],
+ deps = [
+ "//pkg/fd",
+ "//pkg/p9",
+ "//pkg/unet",
+ ],
+)
+
+go_library(
+ name = "p9test",
+ srcs = [
+ "mocks.go",
+ ],
+ importpath = "gvisor.googlesource.com/gvisor/pkg/p9/p9test",
+ visibility = ["//:sandbox"],
+ deps = [
+ "//pkg/fd",
+ "//pkg/p9",
+ ],
+)
diff --git a/pkg/p9/p9test/client_test.go b/pkg/p9/p9test/client_test.go
new file mode 100644
index 000000000..8e35d6017
--- /dev/null
+++ b/pkg/p9/p9test/client_test.go
@@ -0,0 +1,335 @@
+// Copyright 2018 Google Inc.
+//
+// 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 p9test
+
+import (
+ "io/ioutil"
+ "os"
+ "reflect"
+ "syscall"
+ "testing"
+
+ "gvisor.googlesource.com/gvisor/pkg/fd"
+ "gvisor.googlesource.com/gvisor/pkg/p9"
+ "gvisor.googlesource.com/gvisor/pkg/unet"
+)
+
+func TestDonateFD(t *testing.T) {
+ // Temporary file.
+ osFile, err := ioutil.TempFile("", "p9")
+ if err != nil {
+ t.Fatalf("could not create temporary file: %v", err)
+ }
+ os.Remove(osFile.Name())
+
+ hfi, err := osFile.Stat()
+ if err != nil {
+ osFile.Close()
+ t.Fatalf("stat failed: %v", err)
+ }
+ osFileStat := hfi.Sys().(*syscall.Stat_t)
+
+ f, err := fd.NewFromFile(osFile)
+ // osFile should always be closed.
+ osFile.Close()
+ if err != nil {
+ t.Fatalf("unable to create file: %v", err)
+ }
+
+ // Craft attacher to attach to the mocked file which will return our
+ // temporary file.
+ fileMock := &FileMock{OpenMock: OpenMock{File: f}}
+ attacher := &AttachMock{File: fileMock}
+
+ // Make socket pair.
+ serverSocket, clientSocket, err := unet.SocketPair(false)
+ if err != nil {
+ t.Fatalf("socketpair got err %v wanted nil", err)
+ }
+ defer clientSocket.Close()
+ server := p9.NewServer(attacher)
+ go server.Handle(serverSocket)
+ client, err := p9.NewClient(clientSocket, 1024*1024 /* 1M message size */, p9.HighestVersionString())
+ if err != nil {
+ t.Fatalf("new client got %v, expected nil", err)
+ }
+
+ // Attach to the mocked file.
+ cFile, err := client.Attach("")
+ if err != nil {
+ t.Fatalf("attach failed: %v", err)
+ }
+
+ // Try to open the mocked file.
+ clientHostFile, _, _, err := cFile.Open(0)
+ if err != nil {
+ t.Fatalf("open failed: %v", err)
+ }
+ var clientStat syscall.Stat_t
+ if err := syscall.Fstat(clientHostFile.FD(), &clientStat); err != nil {
+ t.Fatalf("stat failed: %v", err)
+ }
+
+ // Compare inode nums to make sure it's the same file.
+ if clientStat.Ino != osFileStat.Ino {
+ t.Errorf("fd donation failed")
+ }
+}
+
+// TestClient is a megatest.
+//
+// This allows us to probe various edge cases, while changing the state of the
+// underlying server in expected ways. The test slowly builds server state and
+// is documented inline.
+//
+// We wind up with the following, after probing edge cases:
+//
+// FID 1: ServerFile (sf).
+// FID 2: Directory (d).
+// FID 3: File (f).
+// FID 4: Symlink (s).
+//
+// Although you should use the FID method on the individual files.
+func TestClient(t *testing.T) {
+ var (
+ // Sentinel error.
+ sentinelErr = syscall.Errno(4383)
+
+ // Backend mocks.
+ a = &AttachMock{}
+ sf = &FileMock{}
+ d = &FileMock{}
+ f = &FileMock{}
+ s = &FileMock{}
+
+ // Client Files for the above.
+ sfFile p9.File
+ )
+
+ testSteps := []struct {
+ name string
+ fn func(*p9.Client) error
+ want error
+ }{
+ {
+ name: "bad-attach",
+ want: sentinelErr,
+ fn: func(c *p9.Client) error {
+ a.File = nil
+ a.Err = sentinelErr
+ _, err := c.Attach("")
+ return err
+ },
+ },
+ {
+ name: "attach",
+ fn: func(c *p9.Client) error {
+ a.Called = false
+ a.File = sf
+ a.Err = nil
+ var err error
+ sfFile, err = c.Attach("foo")
+ if !a.Called {
+ t.Errorf("Attach never Called?")
+ }
+ if a.AttachName != "foo" {
+ // This wasn't carried through?
+ t.Errorf("attachName got %v wanted foo", a.AttachName)
+ }
+ return err
+ },
+ },
+ {
+ name: "bad-walk",
+ want: sentinelErr,
+ fn: func(c *p9.Client) error {
+ sf.WalkMock.File = d
+ sf.WalkMock.Err = sentinelErr
+ _, _, err := sfFile.Walk([]string{"foo", "bar"})
+ return err
+ },
+ },
+ {
+ name: "walk-to-dir",
+ fn: func(c *p9.Client) error {
+ sf.WalkMock.Called = false
+ sf.WalkMock.File = d
+ sf.WalkMock.Err = nil
+ sf.WalkMock.QIDs = []p9.QID{{Type: 1}}
+ var qids []p9.QID
+ var err error
+ qids, _, err = sfFile.Walk([]string{"foo", "bar"})
+ if !sf.WalkMock.Called {
+ t.Errorf("Walk never Called?")
+ }
+ if !reflect.DeepEqual(sf.WalkMock.Names, []string{"foo", "bar"}) {
+ t.Errorf("got names %v wanted []{foo, bar}", sf.WalkMock.Names)
+ }
+ if len(qids) != 1 || qids[0].Type != 1 {
+ t.Errorf("got qids %v wanted []{{Type: 1}}", qids)
+ }
+ return err
+ },
+ },
+ {
+ name: "walkgetattr-to-dir",
+ fn: func(c *p9.Client) error {
+ sf.WalkGetAttrMock.Called = false
+ sf.WalkGetAttrMock.File = d
+ sf.WalkGetAttrMock.Err = nil
+ sf.WalkGetAttrMock.QIDs = []p9.QID{{Type: 1}}
+ sf.WalkGetAttrMock.Attr = p9.Attr{UID: 1}
+ sf.WalkGetAttrMock.Valid = p9.AttrMask{Mode: true}
+ var qids []p9.QID
+ var err error
+ var mask p9.AttrMask
+ var attr p9.Attr
+ qids, _, mask, attr, err = sfFile.WalkGetAttr([]string{"foo", "bar"})
+ if !sf.WalkGetAttrMock.Called {
+ t.Errorf("Walk never Called?")
+ }
+ if !reflect.DeepEqual(sf.WalkGetAttrMock.Names, []string{"foo", "bar"}) {
+ t.Errorf("got names %v wanted []{foo, bar}", sf.WalkGetAttrMock.Names)
+ }
+ if len(qids) != 1 || qids[0].Type != 1 {
+ t.Errorf("got qids %v wanted []{{Type: 1}}", qids)
+ }
+ if !reflect.DeepEqual(attr, sf.WalkGetAttrMock.Attr) {
+ t.Errorf("got attrs %s wanted %s", attr, sf.WalkGetAttrMock.Attr)
+ }
+ if !reflect.DeepEqual(mask, sf.WalkGetAttrMock.Valid) {
+ t.Errorf("got mask %s wanted %s", mask, sf.WalkGetAttrMock.Valid)
+ }
+ return err
+ },
+ },
+ {
+ name: "walk-to-file",
+ fn: func(c *p9.Client) error {
+ // Basic sanity check is done in walk-to-dir.
+ //
+ // Here we just create basic file FIDs to use.
+ sf.WalkMock.File = f
+ sf.WalkMock.Err = nil
+ var err error
+ _, _, err = sfFile.Walk(nil)
+ return err
+ },
+ },
+ {
+ name: "walk-to-symlink",
+ fn: func(c *p9.Client) error {
+ // See note in walk-to-file.
+ sf.WalkMock.File = s
+ sf.WalkMock.Err = nil
+ var err error
+ _, _, err = sfFile.Walk(nil)
+ return err
+ },
+ },
+ {
+ name: "bad-statfs",
+ want: sentinelErr,
+ fn: func(c *p9.Client) error {
+ sf.StatFSMock.Err = sentinelErr
+ _, err := sfFile.StatFS()
+ return err
+ },
+ },
+ {
+ name: "statfs",
+ fn: func(c *p9.Client) error {
+ sf.StatFSMock.Called = false
+ sf.StatFSMock.Stat = p9.FSStat{Type: 1}
+ sf.StatFSMock.Err = nil
+ stat, err := sfFile.StatFS()
+ if !sf.StatFSMock.Called {
+ t.Errorf("StatfS never Called?")
+ }
+ if stat.Type != 1 {
+ t.Errorf("got stat %v wanted {Type: 1}", stat)
+ }
+ return err
+ },
+ },
+ }
+
+ // First, create a new server and connection.
+ serverSocket, clientSocket, err := unet.SocketPair(false)
+ if err != nil {
+ t.Fatalf("socketpair got err %v wanted nil", err)
+ }
+ defer clientSocket.Close()
+ server := p9.NewServer(a)
+ go server.Handle(serverSocket)
+ client, err := p9.NewClient(clientSocket, 1024*1024 /* 1M message size */, p9.HighestVersionString())
+ if err != nil {
+ t.Fatalf("new client got err %v, wanted nil", err)
+ }
+
+ // Now, run through each of the test steps.
+ for _, step := range testSteps {
+ err := step.fn(client)
+ if err != step.want {
+ // Don't fail, just note this one step failed.
+ t.Errorf("step %q got %v wanted %v", step.name, err, step.want)
+ }
+ }
+}
+
+func BenchmarkClient(b *testing.B) {
+ // Backend mock.
+ a := &AttachMock{
+ File: &FileMock{
+ ReadAtMock: ReadAtMock{N: 1},
+ },
+ }
+
+ // First, create a new server and connection.
+ serverSocket, clientSocket, err := unet.SocketPair(false)
+ if err != nil {
+ b.Fatalf("socketpair got err %v wanted nil", err)
+ }
+ defer clientSocket.Close()
+ server := p9.NewServer(a)
+ go server.Handle(serverSocket)
+ client, err := p9.NewClient(clientSocket, 1024*1024 /* 1M message size */, p9.HighestVersionString())
+ if err != nil {
+ b.Fatalf("new client got %v, expected nil", err)
+ }
+
+ // Attach to the server.
+ f, err := client.Attach("")
+ if err != nil {
+ b.Fatalf("error during attach, got %v wanted nil", err)
+ }
+
+ // Open the file.
+ if _, _, _, err := f.Open(p9.ReadOnly); err != nil {
+ b.Fatalf("error during open, got %v wanted nil", err)
+ }
+
+ // Reset the clock.
+ b.ResetTimer()
+
+ // Do N reads.
+ var buf [1]byte
+ for i := 0; i < b.N; i++ {
+ _, err := f.ReadAt(buf[:], 0)
+ if err != nil {
+ b.Fatalf("error during read %d, got %v wanted nil", i, err)
+ }
+ }
+}
diff --git a/pkg/p9/p9test/mocks.go b/pkg/p9/p9test/mocks.go
new file mode 100644
index 000000000..e10f206dd
--- /dev/null
+++ b/pkg/p9/p9test/mocks.go
@@ -0,0 +1,490 @@
+// Copyright 2018 Google Inc.
+//
+// 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 p9test
+
+import (
+ "gvisor.googlesource.com/gvisor/pkg/fd"
+ "gvisor.googlesource.com/gvisor/pkg/p9"
+)
+
+// StatFSMock mocks p9.File.StatFS.
+type StatFSMock struct {
+ Called bool
+
+ // Return.
+ Stat p9.FSStat
+ Err error
+}
+
+// StatFS implements p9.File.StatFS.
+func (f *StatFSMock) StatFS() (p9.FSStat, error) {
+ f.Called = true
+ return f.Stat, f.Err
+}
+
+// GetAttrMock mocks p9.File.GetAttr.
+type GetAttrMock struct {
+ Called bool
+
+ // Args.
+ Req p9.AttrMask
+
+ // Return.
+ QID p9.QID
+ Valid p9.AttrMask
+ Attr p9.Attr
+ Err error
+}
+
+// GetAttr implements p9.File.GetAttr.
+func (g *GetAttrMock) GetAttr(req p9.AttrMask) (p9.QID, p9.AttrMask, p9.Attr, error) {
+ g.Called, g.Req = true, req
+ return g.QID, g.Valid, g.Attr, g.Err
+}
+
+// WalkGetAttrMock mocks p9.File.WalkGetAttr.
+type WalkGetAttrMock struct {
+ Called bool
+
+ // Args.
+ Names []string
+
+ // Return.
+ QIDs []p9.QID
+ File p9.File
+ Valid p9.AttrMask
+ Attr p9.Attr
+ Err error
+}
+
+// WalkGetAttr implements p9.File.WalkGetAttr.
+func (w *WalkGetAttrMock) WalkGetAttr(names []string) ([]p9.QID, p9.File, p9.AttrMask, p9.Attr, error) {
+ w.Called, w.Names = true, names
+ return w.QIDs, w.File, w.Valid, w.Attr, w.Err
+}
+
+// SetAttrMock mocks p9.File.SetAttr.
+type SetAttrMock struct {
+ Called bool
+
+ // Args.
+ Valid p9.SetAttrMask
+ Attr p9.SetAttr
+
+ // Return.
+ Err error
+}
+
+// SetAttr implements p9.File.SetAttr.
+func (s *SetAttrMock) SetAttr(valid p9.SetAttrMask, attr p9.SetAttr) error {
+ s.Called, s.Valid, s.Attr = true, valid, attr
+ return s.Err
+}
+
+// RemoveMock mocks p9.File.Remove.
+type RemoveMock struct {
+ Called bool
+
+ // Return.
+ Err error
+}
+
+// Remove implements p9.File.Remove.
+func (r *RemoveMock) Remove() error {
+ r.Called = true
+ return r.Err
+}
+
+// OpenMock mocks p9.File.Open.
+type OpenMock struct {
+ Called bool
+
+ // Args.
+ Flags p9.OpenFlags
+
+ // Return.
+ File *fd.FD
+ QID p9.QID
+ IOUnit uint32
+ Err error
+}
+
+// Open implements p9.File.Open.
+func (o *OpenMock) Open(flags p9.OpenFlags) (*fd.FD, p9.QID, uint32, error) {
+ o.Called, o.Flags = true, flags
+ return o.File, o.QID, o.IOUnit, o.Err
+}
+
+// ReadAtMock mocks p9.File.ReadAt.
+type ReadAtMock struct {
+ Called bool
+
+ // Args.
+ P []byte
+ Offset uint64
+
+ // Return.
+ N int
+ Err error
+}
+
+// ReadAt implements p9.File.ReadAt.
+func (r *ReadAtMock) ReadAt(p []byte, offset uint64) (int, error) {
+ r.Called, r.P, r.Offset = true, p, offset
+ return r.N, r.Err
+}
+
+// WriteAtMock mocks p9.File.WriteAt.
+type WriteAtMock struct {
+ Called bool
+
+ // Args.
+ P []byte
+ Offset uint64
+
+ // Return.
+ N int
+ Err error
+}
+
+// WriteAt implements p9.File.WriteAt.
+func (w *WriteAtMock) WriteAt(p []byte, offset uint64) (int, error) {
+ w.Called, w.P, w.Offset = true, p, offset
+ return w.N, w.Err
+}
+
+// FSyncMock mocks p9.File.FSync.
+type FSyncMock struct {
+ Called bool
+
+ // Return.
+ Err error
+}
+
+// FSync implements p9.File.FSync.
+func (f *FSyncMock) FSync() error {
+ f.Called = true
+ return f.Err
+}
+
+// MkdirMock mocks p9.File.Mkdir.
+type MkdirMock struct {
+ Called bool
+
+ // Args.
+ Name string
+ Permissions p9.FileMode
+ UID p9.UID
+ GID p9.GID
+
+ // Return.
+ QID p9.QID
+ Err error
+}
+
+// Mkdir implements p9.File.Mkdir.
+func (s *MkdirMock) Mkdir(name string, permissions p9.FileMode, uid p9.UID, gid p9.GID) (p9.QID, error) {
+ s.Called, s.Name, s.Permissions, s.UID, s.GID = true, name, permissions, uid, gid
+ return s.QID, s.Err
+}
+
+// SymlinkMock mocks p9.File.Symlink.
+type SymlinkMock struct {
+ Called bool
+
+ // Args.
+ Oldname string
+ Newname string
+ UID p9.UID
+ GID p9.GID
+
+ // Return.
+ QID p9.QID
+ Err error
+}
+
+// Symlink implements p9.File.Symlink.
+func (s *SymlinkMock) Symlink(oldname string, newname string, uid p9.UID, gid p9.GID) (p9.QID, error) {
+ s.Called, s.Oldname, s.Newname, s.UID, s.GID = true, oldname, newname, uid, gid
+ return s.QID, s.Err
+}
+
+// MknodMock mocks p9.File.Mknod.
+type MknodMock struct {
+ Called bool
+
+ // Args.
+ Name string
+ Permissions p9.FileMode
+ Major uint32
+ Minor uint32
+ UID p9.UID
+ GID p9.GID
+
+ // Return.
+ QID p9.QID
+ Err error
+}
+
+// Mknod implements p9.File.Mknod.
+func (m *MknodMock) Mknod(name string, permissions p9.FileMode, major uint32, minor uint32, uid p9.UID, gid p9.GID) (p9.QID, error) {
+ m.Called, m.Name, m.Permissions, m.Major, m.Minor, m.UID, m.GID = true, name, permissions, major, minor, uid, gid
+ return m.QID, m.Err
+}
+
+// UnlinkAtMock mocks p9.File.UnlinkAt.
+type UnlinkAtMock struct {
+ Called bool
+
+ // Args.
+ Name string
+ Flags uint32
+
+ // Return.
+ Err error
+}
+
+// UnlinkAt implements p9.File.UnlinkAt.
+func (u *UnlinkAtMock) UnlinkAt(name string, flags uint32) error {
+ u.Called, u.Name, u.Flags = true, name, flags
+ return u.Err
+}
+
+// ReaddirMock mocks p9.File.Readdir.
+type ReaddirMock struct {
+ Called bool
+
+ // Args.
+ Offset uint64
+ Count uint32
+
+ // Return.
+ Dirents []p9.Dirent
+ Err error
+}
+
+// Readdir implements p9.File.Readdir.
+func (r *ReaddirMock) Readdir(offset uint64, count uint32) ([]p9.Dirent, error) {
+ r.Called, r.Offset, r.Count = true, offset, count
+ return r.Dirents, r.Err
+}
+
+// ReadlinkMock mocks p9.File.Readlink.
+type ReadlinkMock struct {
+ Called bool
+
+ // Return.
+ Target string
+ Err error
+}
+
+// Readlink implements p9.File.Readlink.
+func (r *ReadlinkMock) Readlink() (string, error) {
+ r.Called = true
+ return r.Target, r.Err
+}
+
+// AttachMock mocks p9.Attacher.Attach.
+type AttachMock struct {
+ Called bool
+
+ // Args.
+ AttachName string
+
+ // Return.
+ File p9.File
+ Err error
+}
+
+// Attach implements p9.Attacher.Attach.
+func (a *AttachMock) Attach(attachName string) (p9.File, error) {
+ a.Called, a.AttachName = true, attachName
+ return a.File, a.Err
+}
+
+// WalkMock mocks p9.File.Walk.
+type WalkMock struct {
+ Called bool
+
+ // Args.
+ Names []string
+
+ // Return.
+ QIDs []p9.QID
+ File p9.File
+ Err error
+}
+
+// Walk implements p9.File.Walk.
+func (w *WalkMock) Walk(names []string) ([]p9.QID, p9.File, error) {
+ w.Called, w.Names = true, names
+ return w.QIDs, w.File, w.Err
+}
+
+// RenameMock mocks p9.File.Rename.
+type RenameMock struct {
+ Called bool
+
+ // Args.
+ Directory p9.File
+ Name string
+
+ // Return.
+ Err error
+}
+
+// Rename implements p9.File.Rename.
+func (r *RenameMock) Rename(directory p9.File, name string) error {
+ r.Called, r.Directory, r.Name = true, directory, name
+ return r.Err
+}
+
+// CloseMock mocks p9.File.Close.
+type CloseMock struct {
+ Called bool
+
+ // Return.
+ Err error
+}
+
+// Close implements p9.File.Close.
+func (d *CloseMock) Close() error {
+ d.Called = true
+ return d.Err
+}
+
+// CreateMock mocks p9.File.Create.
+type CreateMock struct {
+ Called bool
+
+ // Args.
+ Name string
+ Flags p9.OpenFlags
+ Permissions p9.FileMode
+ UID p9.UID
+ GID p9.GID
+
+ // Return.
+ HostFile *fd.FD
+ File p9.File
+ QID p9.QID
+ IOUnit uint32
+ Err error
+}
+
+// Create implements p9.File.Create.
+func (c *CreateMock) Create(name string, flags p9.OpenFlags, permissions p9.FileMode, uid p9.UID, gid p9.GID) (*fd.FD, p9.File, p9.QID, uint32, error) {
+ c.Called, c.Name, c.Flags, c.Permissions, c.UID, c.GID = true, name, flags, permissions, uid, gid
+ return c.HostFile, c.File, c.QID, c.IOUnit, c.Err
+}
+
+// LinkMock mocks p9.File.Link.
+type LinkMock struct {
+ Called bool
+
+ // Args.
+ Target p9.File
+ Newname string
+
+ // Return.
+ Err error
+}
+
+// Link implements p9.File.Link.
+func (l *LinkMock) Link(target p9.File, newname string) error {
+ l.Called, l.Target, l.Newname = true, target, newname
+ return l.Err
+}
+
+// RenameAtMock mocks p9.File.RenameAt.
+type RenameAtMock struct {
+ Called bool
+
+ // Args.
+ Oldname string
+ Newdir p9.File
+ Newname string
+
+ // Return.
+ Err error
+}
+
+// RenameAt implements p9.File.RenameAt.
+func (r *RenameAtMock) RenameAt(oldname string, newdir p9.File, newname string) error {
+ r.Called, r.Oldname, r.Newdir, r.Newname = true, oldname, newdir, newname
+ return r.Err
+}
+
+// FlushMock mocks p9.File.Flush.
+type FlushMock struct {
+ Called bool
+
+ // Return.
+ Err error
+}
+
+// Flush implements p9.File.Flush.
+func (f *FlushMock) Flush() error {
+ return f.Err
+}
+
+// ConnectMock mocks p9.File.Connect.
+type ConnectMock struct {
+ Called bool
+
+ // Args.
+ Flags p9.ConnectFlags
+
+ // Return.
+ File *fd.FD
+ Err error
+}
+
+// Connect implements p9.File.Connect.
+func (o *ConnectMock) Connect(flags p9.ConnectFlags) (*fd.FD, error) {
+ o.Called, o.Flags = true, flags
+ return o.File, o.Err
+}
+
+// FileMock mocks p9.File.
+type FileMock struct {
+ WalkMock
+ WalkGetAttrMock
+ StatFSMock
+ GetAttrMock
+ SetAttrMock
+ RemoveMock
+ RenameMock
+ CloseMock
+ OpenMock
+ ReadAtMock
+ WriteAtMock
+ FSyncMock
+ CreateMock
+ MkdirMock
+ SymlinkMock
+ LinkMock
+ MknodMock
+ RenameAtMock
+ UnlinkAtMock
+ ReaddirMock
+ ReadlinkMock
+ FlushMock
+ ConnectMock
+}
+
+var (
+ _ p9.File = &FileMock{}
+)