diff --git a/mockfile.go b/mockfile.go new file mode 100644 index 0000000..5c8e080 --- /dev/null +++ b/mockfile.go @@ -0,0 +1,43 @@ +package vfs + +import ( + "io/fs" + "os" + "time" +) + +type MockFile struct { + name string + mode os.FileMode + modified time.Time + open bool + size int64 +} + +func (f *MockFile) Stat() (fs.FileInfo, error) { + if f.open { + return &fileInfo{ + name: f.name, + size: f.size, + modified: f.modified, + mode: f.mode, + }, nil + } + return nil, fs.ErrClosed +} + +func (f *MockFile) Read(data []byte) (int, error) { + if f.open { + data = []byte{} + return 0, nil + } + return 0, fs.ErrClosed +} + +func (f *MockFile) Close() error { + if f.open { + f.open = false + return nil + } + return fs.ErrClosed +} diff --git a/vfs.go b/vfs.go index 5c66b21..dd2268f 100644 --- a/vfs.go +++ b/vfs.go @@ -42,17 +42,24 @@ func (f *FS) Open(path string) (fs.File, error) { switch c := child.(type) { case *File: - fp := &File{ + return &File{ name: c.name, mode: c.mode, data: bytes.NewBuffer(c.data.Bytes()), open: true, - } - return fp, nil + }, nil case *directory: return &directoryHandle{ dir: c, }, nil + case *MockFile: + return &MockFile{ + name: c.name, + mode: c.mode, + modified: c.modified, + open: true, + size: c.size, + }, nil } return nil, fmt.Errorf("%s is unknown file type %v", path, fs.ErrInvalid) @@ -87,6 +94,13 @@ func (f *FS) find(path string) (interface{}, error) { return nil, fmt.Errorf("%s does not exist", path) } + if _, ok := child.(*MockFile); ok { + if i == len(split)-1 { + return child, nil + } + return nil, fmt.Errorf("%s does not exist", path) + } + if subdir, ok := child.(*directory); !ok { return nil, fmt.Errorf("directory %s does not exist", path) } else { @@ -218,6 +232,54 @@ func (f *FS) MkdirAll(path string, mode os.FileMode) error { return nil } +func (f *FS) CreateMockFile(fpath string, size int64, mode os.FileMode) error { + if !fs.ValidPath(fpath) { + return &fs.PathError{ + Op: "WriteFile", + Path: fpath, + Err: fs.ErrInvalid, + } + } + + if fpath == "." { + fpath = "" + } + + err := func() error { + dirName, fileName := path.Split(fpath) + dirName = strings.TrimSuffix(dirName, "/") + + dir, err := f.findDirectory(dirName) + if err != nil { + return err + } + + dir.mutex.Lock() + defer dir.mutex.Unlock() + + checkExist := dir.children[fileName] + if checkExist != nil { + if _, ok := checkExist.(*File); !ok { + return fmt.Errorf("%s is a directory that already exists", fpath) + } + } + + file := &MockFile{ + name: fileName, + mode: 0666, + size: size, + } + dir.children[fileName] = file + return nil + }() + + if err != nil { + return err + } + + return nil +} + func (f *FS) WriteFile(path string, data []byte, mode os.FileMode) error { if !fs.ValidPath(path) { return &fs.PathError{ diff --git a/vfs_test.go b/vfs_test.go index fcf03e0..f9798ea 100644 --- a/vfs_test.go +++ b/vfs_test.go @@ -41,3 +41,22 @@ func TestVFS_Basic(t *testing.T) { assert.NoError(t, err) } } + +func TestVFS_MockFile(t *testing.T) { + vfs := NewVFS() + path := "test.txt" + sz := int64(8096) + + err := vfs.CreateMockFile(path, sz, 0666) + assert.NoError(t, err) + + fp, err := vfs.Open(path) + assert.NoError(t, err) + + stat, err := fp.Stat() + assert.NoError(t, err) + assert.Equal(t, stat.Size(), sz) + + err = fp.Close() + assert.NoError(t, err) +}