github.com/databricks/cli@v0.203.0/libs/filer/fs_test.go (about) 1 package filer 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "io/fs" 8 "path" 9 "sort" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 ) 17 18 type fakeDirEntry struct { 19 fakeFileInfo 20 } 21 22 func (entry fakeDirEntry) Type() fs.FileMode { 23 typ := fs.ModePerm 24 if entry.dir { 25 typ |= fs.ModeDir 26 } 27 return typ 28 } 29 30 func (entry fakeDirEntry) Info() (fs.FileInfo, error) { 31 return entry.fakeFileInfo, nil 32 } 33 34 type fakeFileInfo struct { 35 name string 36 size int64 37 dir bool 38 mode fs.FileMode 39 } 40 41 func (info fakeFileInfo) Name() string { 42 return info.name 43 } 44 45 func (info fakeFileInfo) Size() int64 { 46 return info.size 47 } 48 49 func (info fakeFileInfo) Mode() fs.FileMode { 50 return info.mode 51 } 52 53 func (info fakeFileInfo) ModTime() time.Time { 54 return time.Now() 55 } 56 57 func (info fakeFileInfo) IsDir() bool { 58 return info.dir 59 } 60 61 func (info fakeFileInfo) Sys() any { 62 return nil 63 } 64 65 type fakeFiler struct { 66 entries map[string]fakeFileInfo 67 } 68 69 func (f *fakeFiler) Write(ctx context.Context, p string, reader io.Reader, mode ...WriteMode) error { 70 return fmt.Errorf("not implemented") 71 } 72 73 func (f *fakeFiler) Read(ctx context.Context, p string) (io.ReadCloser, error) { 74 _, ok := f.entries[p] 75 if !ok { 76 return nil, fs.ErrNotExist 77 } 78 79 return io.NopCloser(strings.NewReader("foo")), nil 80 } 81 82 func (f *fakeFiler) Delete(ctx context.Context, p string, mode ...DeleteMode) error { 83 return fmt.Errorf("not implemented") 84 } 85 86 func (f *fakeFiler) ReadDir(ctx context.Context, p string) ([]fs.DirEntry, error) { 87 entry, ok := f.entries[p] 88 if !ok { 89 return nil, fs.ErrNotExist 90 } 91 92 if !entry.dir { 93 return nil, fs.ErrInvalid 94 } 95 96 // Find all entries contained in the specified directory `p`. 97 var out []fs.DirEntry 98 for k, v := range f.entries { 99 if k == p || path.Dir(k) != p { 100 continue 101 } 102 103 out = append(out, fakeDirEntry{v}) 104 } 105 106 sort.Slice(out, func(i, j int) bool { return out[i].Name() < out[j].Name() }) 107 return out, nil 108 } 109 110 func (f *fakeFiler) Mkdir(ctx context.Context, path string) error { 111 return fmt.Errorf("not implemented") 112 } 113 114 func (f *fakeFiler) Stat(ctx context.Context, path string) (fs.FileInfo, error) { 115 entry, ok := f.entries[path] 116 if !ok { 117 return nil, fs.ErrNotExist 118 } 119 120 return entry, nil 121 } 122 123 func TestFsImplementsFS(t *testing.T) { 124 var _ fs.FS = &filerFS{} 125 } 126 127 func TestFsImplementsReadDirFS(t *testing.T) { 128 var _ fs.ReadDirFS = &filerFS{} 129 } 130 131 func TestFsImplementsReadFileFS(t *testing.T) { 132 var _ fs.ReadDirFS = &filerFS{} 133 } 134 135 func TestFsImplementsStatFS(t *testing.T) { 136 var _ fs.StatFS = &filerFS{} 137 } 138 139 func TestFsFileImplementsFsFile(t *testing.T) { 140 var _ fs.File = &fsFile{} 141 } 142 143 func TestFsDirImplementsFsReadDirFile(t *testing.T) { 144 var _ fs.ReadDirFile = &fsDir{} 145 } 146 147 func fakeFS() fs.FS { 148 fakeFiler := &fakeFiler{ 149 entries: map[string]fakeFileInfo{ 150 ".": {name: "root", dir: true}, 151 "dirA": {dir: true}, 152 "dirB": {dir: true}, 153 "fileA": {size: 3}, 154 }, 155 } 156 157 for k, v := range fakeFiler.entries { 158 if v.name != "" { 159 continue 160 } 161 v.name = path.Base(k) 162 fakeFiler.entries[k] = v 163 } 164 165 return NewFS(context.Background(), fakeFiler) 166 } 167 168 func TestFsGlob(t *testing.T) { 169 fakeFS := fakeFS() 170 matches, err := fs.Glob(fakeFS, "*") 171 require.NoError(t, err) 172 assert.Equal(t, []string{"dirA", "dirB", "fileA"}, matches) 173 } 174 175 func TestFsOpenFile(t *testing.T) { 176 fakeFS := fakeFS() 177 fakeFile, err := fakeFS.Open("fileA") 178 require.NoError(t, err) 179 180 info, err := fakeFile.Stat() 181 require.NoError(t, err) 182 assert.Equal(t, "fileA", info.Name()) 183 assert.Equal(t, int64(3), info.Size()) 184 assert.Equal(t, fs.FileMode(0), info.Mode()) 185 assert.Equal(t, false, info.IsDir()) 186 187 // Read until closed. 188 b := make([]byte, 3) 189 n, err := fakeFile.Read(b) 190 require.NoError(t, err) 191 assert.Equal(t, 3, n) 192 assert.Equal(t, []byte{'f', 'o', 'o'}, b) 193 _, err = fakeFile.Read(b) 194 assert.ErrorIs(t, err, io.EOF) 195 196 // Close. 197 err = fakeFile.Close() 198 assert.NoError(t, err) 199 200 // Close again. 201 err = fakeFile.Close() 202 assert.ErrorIs(t, err, fs.ErrClosed) 203 } 204 205 func TestFsOpenDir(t *testing.T) { 206 fakeFS := fakeFS() 207 fakeFile, err := fakeFS.Open(".") 208 require.NoError(t, err) 209 210 info, err := fakeFile.Stat() 211 require.NoError(t, err) 212 assert.Equal(t, "root", info.Name()) 213 assert.Equal(t, true, info.IsDir()) 214 215 de, ok := fakeFile.(fs.ReadDirFile) 216 require.True(t, ok) 217 218 // Read all entries in one shot. 219 reference, err := de.ReadDir(-1) 220 require.NoError(t, err) 221 222 // Read entries one at a time. 223 { 224 var tmp, entries []fs.DirEntry 225 var err error 226 227 de.Close() 228 229 for i := 0; i < 3; i++ { 230 tmp, err = de.ReadDir(1) 231 require.NoError(t, err) 232 entries = append(entries, tmp...) 233 } 234 235 _, err = de.ReadDir(1) 236 require.ErrorIs(t, err, io.EOF, err) 237 238 // Compare to reference. 239 assert.Equal(t, reference, entries) 240 } 241 242 // Read entries and overshoot at the end. 243 { 244 var tmp, entries []fs.DirEntry 245 var err error 246 247 de.Close() 248 249 tmp, err = de.ReadDir(1) 250 require.NoError(t, err) 251 entries = append(entries, tmp...) 252 253 tmp, err = de.ReadDir(20) 254 require.NoError(t, err) 255 entries = append(entries, tmp...) 256 257 _, err = de.ReadDir(1) 258 require.ErrorIs(t, err, io.EOF, err) 259 260 // Compare to reference. 261 assert.Equal(t, reference, entries) 262 } 263 } 264 265 func TestFsReadDir(t *testing.T) { 266 fakeFS := fakeFS().(fs.ReadDirFS) 267 entries, err := fakeFS.ReadDir(".") 268 require.NoError(t, err) 269 assert.Len(t, entries, 3) 270 assert.Equal(t, "dirA", entries[0].Name()) 271 assert.Equal(t, "dirB", entries[1].Name()) 272 assert.Equal(t, "fileA", entries[2].Name()) 273 } 274 275 func TestFsReadFile(t *testing.T) { 276 fakeFS := fakeFS().(fs.ReadFileFS) 277 buf, err := fakeFS.ReadFile("fileA") 278 require.NoError(t, err) 279 assert.Equal(t, []byte("foo"), buf) 280 } 281 282 func TestFsStat(t *testing.T) { 283 fakeFS := fakeFS().(fs.StatFS) 284 info, err := fakeFS.Stat("fileA") 285 require.NoError(t, err) 286 assert.Equal(t, "fileA", info.Name()) 287 assert.Equal(t, int64(3), info.Size()) 288 }