| 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 |
| } |