blob: 218032a6d48359f2ae7e6b559d0b5533a1625e5a [file] [log] [blame]
package shared_tests
// This file contains tests which would go in go/vfs except that they use the
// mocks in go/vfs/mocks, which depends on go/vfs and thus would create a cycle.
import (
"context"
"io"
"os"
"path"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/deepequal/assertdeep"
"go.skia.org/infra/go/testutils/unittest"
"go.skia.org/infra/go/vfs"
"go.skia.org/infra/go/vfs/mocks"
)
func TestReuseContextFile(t *testing.T) {
unittest.SmallTest(t)
// Setup.
origFile := &mocks.File{}
key := &struct{}{}
val := &struct{}{}
ctx := context.WithValue(context.Background(), key, val)
wrapFile := vfs.WithContext(ctx, origFile)
var buf []byte
// Mock calls to the underlying File which match the Context passed to
// WithContext.
origFile.On("Read", ctx, buf).Return(0, nil)
origFile.On("Stat", ctx).Return(nil, nil)
origFile.On("Close", ctx).Return(nil)
// Call the associated methods on wrapFile.
_, err := wrapFile.Read(buf)
require.NoError(t, err)
_, err = wrapFile.Stat()
require.NoError(t, err)
err = wrapFile.Close()
require.NoError(t, err)
origFile.AssertExpectations(t)
}
func TestReadFile(t *testing.T) {
unittest.SmallTest(t)
ctx := context.Background()
name := "myfile.txt"
fs := &mocks.FS{}
f := &mocks.File{}
fs.On("Open", ctx, name).Return(f, nil)
contents := []uint8("hello world")
// Note: this only works because our input is smaller than the buffer size
// used by ioutil.ReadAll.
f.On("Read", ctx, mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
arg := args.Get(1).([]uint8)
copy(arg, contents)
}).Return(len(contents), io.EOF)
f.On("Close", ctx).Return(nil)
result, err := vfs.ReadFile(ctx, fs, name)
require.NoError(t, err)
require.Equal(t, contents, result)
fs.AssertExpectations(t)
f.AssertExpectations(t)
}
func TestReadDir(t *testing.T) {
unittest.SmallTest(t)
ctx := context.Background()
name := "mydir"
fs := &mocks.FS{}
dir := &mocks.ReadDirFile{}
contents := []os.FileInfo{
vfs.FileInfo{
Name: "myfile.txt",
Size: 128,
Mode: os.ModePerm,
ModTime: time.Now(),
IsDir: false,
Sys: nil,
}.Get(),
vfs.FileInfo{
Name: "subdir",
Size: 0,
Mode: os.ModePerm | os.ModeDir,
ModTime: time.Now(),
IsDir: true,
Sys: nil,
}.Get(),
}
fs.On("Open", ctx, name).Return(dir, nil)
dir.On("ReadDir", ctx, -1).Return(contents, nil)
dir.On("Close", ctx).Return(nil)
result, err := vfs.ReadDir(ctx, fs, name)
require.NoError(t, err)
assertdeep.Equal(t, contents, result)
fs.AssertExpectations(t)
dir.AssertExpectations(t)
}
func TestStat(t *testing.T) {
unittest.SmallTest(t)
ctx := context.Background()
fs := &mocks.FS{}
dir, dirFi := mockStat(ctx, fs, "myDir", true)
result, err := vfs.Stat(ctx, fs, dirFi.Name())
require.NoError(t, err)
assertdeep.Equal(t, dirFi, result)
fs.AssertExpectations(t)
dir.AssertExpectations(t)
}
func TestWalk(t *testing.T) {
unittest.SmallTest(t)
ctx := context.Background()
fs := &mocks.FS{}
rootDir, rootDirFi := mockStat(ctx, fs, "root", true)
_, rootFileFi := mockStat(ctx, fs, path.Join(rootDirFi.Name(), "rootFile"), false)
subDir, subDirFi := mockStat(ctx, fs, path.Join(rootDirFi.Name(), "subdir"), true)
rootDir.On("ReadDir", ctx, -1).Return([]os.FileInfo{subDirFi, rootFileFi}, nil)
_, subDirFileFi := mockStat(ctx, fs, path.Join(rootDirFi.Name(), subDirFi.Name(), "subdirFile"), false)
subDir.On("ReadDir", ctx, -1).Return([]os.FileInfo{subDirFileFi}, nil)
expect := map[string]os.FileInfo{
rootDirFi.Name(): rootDirFi,
path.Join(rootDirFi.Name(), rootFileFi.Name()): rootFileFi,
path.Join(rootDirFi.Name(), subDirFi.Name()): subDirFi,
path.Join(rootDirFi.Name(), subDirFi.Name(), subDirFileFi.Name()): subDirFileFi,
}
visited := map[string]bool{}
walkFn := func(name string, fi os.FileInfo, err error) error {
require.NoError(t, err)
assertdeep.Equal(t, expect[name], fi)
visited[name] = true
return nil
}
require.NoError(t, vfs.Walk(ctx, fs, rootDirFi.Name(), walkFn))
require.Equal(t, len(expect), len(visited))
// TODO(borenet): Test filepath.SkipDir.
}
func mockStat(ctx context.Context, fs *mocks.FS, fullPath string, isDir bool) (*mock.Mock, *vfs.FileInfoImpl) {
fi := vfs.FileInfo{
Name: filepath.Base(fullPath),
Size: 128,
Mode: os.ModePerm,
ModTime: time.Now(),
IsDir: isDir,
Sys: nil,
}.Get()
var file vfs.File
var m *mock.Mock
if isDir {
fi.FileInfo.Mode = fi.FileInfo.Mode | os.ModeDir
dir := &mocks.ReadDirFile{}
m = &dir.Mock
file = dir
} else {
f := &mocks.File{}
m = &f.Mock
file = f
}
fs.On("Open", ctx, fullPath).Return(file, nil)
m.On("Stat", ctx).Return(fi, nil)
m.On("Close", ctx).Return(nil)
return m, fi
}