Skip to content

Commit 7d732ce

Browse files
authored
Consolidate test helpers for io/fs (#1906)
## Changes We had a number of copies of test helpers for `io/fs` in the repository. This change consolidates all of them to use the `libs/fakefs` package. ## Tests Unit tests pass.
1 parent 7f3fb10 commit 7d732ce

File tree

9 files changed

+201
-138
lines changed

9 files changed

+201
-138
lines changed

cmd/fs/helpers_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88

99
"github.com/databricks/cli/cmd/root"
10+
"github.com/databricks/cli/libs/fakefs"
1011
"github.com/databricks/cli/libs/filer"
1112
"github.com/databricks/databricks-sdk-go/experimental/mocks"
1213
"github.com/spf13/cobra"
@@ -84,7 +85,7 @@ func setupTest(t *testing.T) (*validArgs, *cobra.Command, *mocks.MockWorkspaceCl
8485
cmd, m := setupCommand(t)
8586

8687
fakeFilerForPath := func(ctx context.Context, fullPath string) (filer.Filer, string, error) {
87-
fakeFiler := filer.NewFakeFiler(map[string]filer.FakeFileInfo{
88+
fakeFiler := filer.NewFakeFiler(map[string]fakefs.FileInfo{
8889
"dir": {FakeName: "root", FakeDir: true},
8990
"dir/dirA": {FakeDir: true},
9091
"dir/dirB": {FakeDir: true},

libs/fakefs/fakefs.go

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
package fakefs
22

33
import (
4+
"fmt"
45
"io/fs"
56
"time"
67
)
78

9+
var ErrNotImplemented = fmt.Errorf("not implemented")
10+
811
// DirEntry is a fake implementation of [fs.DirEntry].
912
type DirEntry struct {
10-
FileInfo
13+
fs.FileInfo
1114
}
1215

1316
func (entry DirEntry) Type() fs.FileMode {
1417
typ := fs.ModePerm
15-
if entry.FakeDir {
18+
if entry.IsDir() {
1619
typ |= fs.ModeDir
1720
}
1821
return typ
@@ -53,3 +56,32 @@ func (info FileInfo) IsDir() bool {
5356
func (info FileInfo) Sys() any {
5457
return nil
5558
}
59+
60+
// File is a fake implementation of [fs.File].
61+
type File struct {
62+
FileInfo fs.FileInfo
63+
}
64+
65+
func (f File) Close() error {
66+
return nil
67+
}
68+
69+
func (f File) Read(p []byte) (n int, err error) {
70+
return 0, ErrNotImplemented
71+
}
72+
73+
func (f File) Stat() (fs.FileInfo, error) {
74+
return f.FileInfo, nil
75+
}
76+
77+
// FS is a fake implementation of [fs.FS].
78+
type FS map[string]fs.File
79+
80+
func (f FS) Open(name string) (fs.File, error) {
81+
e, ok := f[name]
82+
if !ok {
83+
return nil, fs.ErrNotExist
84+
}
85+
86+
return e, nil
87+
}

libs/fakefs/fakefs_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package fakefs
2+
3+
import (
4+
"io/fs"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestFile(t *testing.T) {
11+
var fakefile fs.File = File{
12+
FileInfo: FileInfo{
13+
FakeName: "file",
14+
},
15+
}
16+
17+
_, err := fakefile.Read([]byte{})
18+
assert.ErrorIs(t, err, ErrNotImplemented)
19+
20+
fi, err := fakefile.Stat()
21+
assert.NoError(t, err)
22+
assert.Equal(t, "file", fi.Name())
23+
24+
err = fakefile.Close()
25+
assert.NoError(t, err)
26+
}
27+
28+
func TestFS(t *testing.T) {
29+
var fakefs fs.FS = FS{
30+
"file": File{},
31+
}
32+
33+
_, err := fakefs.Open("doesntexist")
34+
assert.ErrorIs(t, err, fs.ErrNotExist)
35+
36+
_, err = fakefs.Open("file")
37+
assert.NoError(t, err)
38+
}

libs/filer/completer/completer_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"testing"
77

88
"github.com/databricks/cli/cmd/root"
9+
"github.com/databricks/cli/libs/fakefs"
910
"github.com/databricks/cli/libs/filer"
1011
"github.com/databricks/databricks-sdk-go/experimental/mocks"
1112
"github.com/spf13/cobra"
@@ -17,7 +18,7 @@ func setupCompleter(t *testing.T, onlyDirs bool) *completer {
1718
// Needed to make type context.valueCtx for mockFilerForPath
1819
ctx = root.SetWorkspaceClient(ctx, mocks.NewMockWorkspaceClient(t).WorkspaceClient)
1920

20-
fakeFiler := filer.NewFakeFiler(map[string]filer.FakeFileInfo{
21+
fakeFiler := filer.NewFakeFiler(map[string]fakefs.FileInfo{
2122
"dir": {FakeName: "root", FakeDir: true},
2223
"dir/dirA": {FakeDir: true},
2324
"dir/dirB": {FakeDir: true},

libs/filer/fake_filer.go

Lines changed: 9 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,58 +8,12 @@ import (
88
"path"
99
"sort"
1010
"strings"
11-
"time"
12-
)
13-
14-
type FakeDirEntry struct {
15-
FakeFileInfo
16-
}
17-
18-
func (entry FakeDirEntry) Type() fs.FileMode {
19-
typ := fs.ModePerm
20-
if entry.FakeDir {
21-
typ |= fs.ModeDir
22-
}
23-
return typ
24-
}
25-
26-
func (entry FakeDirEntry) Info() (fs.FileInfo, error) {
27-
return entry.FakeFileInfo, nil
28-
}
29-
30-
type FakeFileInfo struct {
31-
FakeName string
32-
FakeSize int64
33-
FakeDir bool
34-
FakeMode fs.FileMode
35-
}
36-
37-
func (info FakeFileInfo) Name() string {
38-
return info.FakeName
39-
}
40-
41-
func (info FakeFileInfo) Size() int64 {
42-
return info.FakeSize
43-
}
4411

45-
func (info FakeFileInfo) Mode() fs.FileMode {
46-
return info.FakeMode
47-
}
48-
49-
func (info FakeFileInfo) ModTime() time.Time {
50-
return time.Now()
51-
}
52-
53-
func (info FakeFileInfo) IsDir() bool {
54-
return info.FakeDir
55-
}
56-
57-
func (info FakeFileInfo) Sys() any {
58-
return nil
59-
}
12+
"github.com/databricks/cli/libs/fakefs"
13+
)
6014

6115
type FakeFiler struct {
62-
entries map[string]FakeFileInfo
16+
entries map[string]fakefs.FileInfo
6317
}
6418

6519
func (f *FakeFiler) Write(ctx context.Context, p string, reader io.Reader, mode ...WriteMode) error {
@@ -97,7 +51,7 @@ func (f *FakeFiler) ReadDir(ctx context.Context, p string) ([]fs.DirEntry, error
9751
continue
9852
}
9953

100-
out = append(out, FakeDirEntry{v})
54+
out = append(out, fakefs.DirEntry{FileInfo: v})
10155
}
10256

10357
sort.Slice(out, func(i, j int) bool { return out[i].Name() < out[j].Name() })
@@ -117,7 +71,11 @@ func (f *FakeFiler) Stat(ctx context.Context, path string) (fs.FileInfo, error)
11771
return entry, nil
11872
}
11973

120-
func NewFakeFiler(entries map[string]FakeFileInfo) *FakeFiler {
74+
// NewFakeFiler creates a new fake [Filer] instance with the given entries.
75+
// It sets the [Name] field of each entry to the base name of the path.
76+
//
77+
// This is meant to be used in tests.
78+
func NewFakeFiler(entries map[string]fakefs.FileInfo) *FakeFiler {
12179
fakeFiler := &FakeFiler{
12280
entries: entries,
12381
}

libs/filer/fake_filer_test.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package filer
2+
3+
import (
4+
"context"
5+
"io"
6+
"io/fs"
7+
"testing"
8+
9+
"github.com/databricks/cli/libs/fakefs"
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestFakeFiler_Read(t *testing.T) {
15+
f := NewFakeFiler(map[string]fakefs.FileInfo{
16+
"file": {},
17+
})
18+
19+
ctx := context.Background()
20+
r, err := f.Read(ctx, "file")
21+
require.NoError(t, err)
22+
contents, err := io.ReadAll(r)
23+
require.NoError(t, err)
24+
25+
// Contents of every file is "foo".
26+
assert.Equal(t, "foo", string(contents))
27+
}
28+
29+
func TestFakeFiler_Read_NotFound(t *testing.T) {
30+
f := NewFakeFiler(map[string]fakefs.FileInfo{
31+
"foo": {},
32+
})
33+
34+
ctx := context.Background()
35+
_, err := f.Read(ctx, "bar")
36+
assert.ErrorIs(t, err, fs.ErrNotExist)
37+
}
38+
39+
func TestFakeFiler_ReadDir_NotFound(t *testing.T) {
40+
f := NewFakeFiler(map[string]fakefs.FileInfo{
41+
"dir1": {FakeDir: true},
42+
})
43+
44+
ctx := context.Background()
45+
_, err := f.ReadDir(ctx, "dir2")
46+
assert.ErrorIs(t, err, fs.ErrNotExist)
47+
}
48+
49+
func TestFakeFiler_ReadDir_NotADirectory(t *testing.T) {
50+
f := NewFakeFiler(map[string]fakefs.FileInfo{
51+
"file": {},
52+
})
53+
54+
ctx := context.Background()
55+
_, err := f.ReadDir(ctx, "file")
56+
assert.ErrorIs(t, err, fs.ErrInvalid)
57+
}
58+
59+
func TestFakeFiler_ReadDir(t *testing.T) {
60+
f := NewFakeFiler(map[string]fakefs.FileInfo{
61+
"dir1": {FakeDir: true},
62+
"dir1/file2": {},
63+
"dir1/dir2": {FakeDir: true},
64+
})
65+
66+
ctx := context.Background()
67+
entries, err := f.ReadDir(ctx, "dir1/")
68+
require.NoError(t, err)
69+
require.Len(t, entries, 2)
70+
71+
// The entries are sorted by name.
72+
assert.Equal(t, "dir2", entries[0].Name())
73+
assert.True(t, entries[0].IsDir())
74+
assert.Equal(t, "file2", entries[1].Name())
75+
assert.False(t, entries[1].IsDir())
76+
}
77+
78+
func TestFakeFiler_Stat(t *testing.T) {
79+
f := NewFakeFiler(map[string]fakefs.FileInfo{
80+
"file": {},
81+
})
82+
83+
ctx := context.Background()
84+
info, err := f.Stat(ctx, "file")
85+
require.NoError(t, err)
86+
87+
assert.Equal(t, "file", info.Name())
88+
}
89+
90+
func TestFakeFiler_Stat_NotFound(t *testing.T) {
91+
f := NewFakeFiler(map[string]fakefs.FileInfo{
92+
"foo": {},
93+
})
94+
95+
ctx := context.Background()
96+
_, err := f.Stat(ctx, "bar")
97+
assert.ErrorIs(t, err, fs.ErrNotExist)
98+
}

libs/filer/fs_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io/fs"
77
"testing"
88

9+
"github.com/databricks/cli/libs/fakefs"
910
"github.com/stretchr/testify/assert"
1011
"github.com/stretchr/testify/require"
1112
)
@@ -35,7 +36,7 @@ func TestFsDirImplementsFsReadDirFile(t *testing.T) {
3536
}
3637

3738
func fakeFS() fs.FS {
38-
fakeFiler := NewFakeFiler(map[string]FakeFileInfo{
39+
fakeFiler := NewFakeFiler(map[string]fakefs.FileInfo{
3940
".": {FakeName: "root", FakeDir: true},
4041
"dirA": {FakeDir: true},
4142
"dirB": {FakeDir: true},

libs/notebook/detect_test.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"path/filepath"
88
"testing"
99

10+
"github.com/databricks/cli/libs/fakefs"
1011
"github.com/databricks/databricks-sdk-go/service/workspace"
1112
"github.com/stretchr/testify/assert"
1213
"github.com/stretchr/testify/require"
@@ -100,19 +101,29 @@ func TestDetectFileWithLongHeader(t *testing.T) {
100101
assert.False(t, nb)
101102
}
102103

104+
type fileInfoWithWorkspaceInfo struct {
105+
fakefs.FileInfo
106+
107+
oi workspace.ObjectInfo
108+
}
109+
110+
func (f fileInfoWithWorkspaceInfo) WorkspaceObjectInfo() workspace.ObjectInfo {
111+
return f.oi
112+
}
113+
103114
func TestDetectWithObjectInfo(t *testing.T) {
104-
fakeFS := &fakeFS{
105-
fakeFile{
106-
fakeFileInfo{
107-
workspace.ObjectInfo{
115+
fakefs := fakefs.FS{
116+
"file.py": fakefs.File{
117+
FileInfo: fileInfoWithWorkspaceInfo{
118+
oi: workspace.ObjectInfo{
108119
ObjectType: workspace.ObjectTypeNotebook,
109120
Language: workspace.LanguagePython,
110121
},
111122
},
112123
},
113124
}
114125

115-
nb, lang, err := DetectWithFS(fakeFS, "doesntmatter")
126+
nb, lang, err := DetectWithFS(fakefs, "file.py")
116127
require.NoError(t, err)
117128
assert.True(t, nb)
118129
assert.Equal(t, workspace.LanguagePython, lang)

0 commit comments

Comments
 (0)