@@ -11,6 +11,8 @@ import (
11
11
"os"
12
12
"path"
13
13
"path/filepath"
14
+ "reflect"
15
+ "sort"
14
16
"strconv"
15
17
"strings"
16
18
"testing"
@@ -202,10 +204,10 @@ func TestWalk(t *testing.T) {
202
204
}
203
205
}
204
206
205
- i := 0
207
+ i , prevFrag := 0 , ""
206
208
err := fs .walk ("test" , tc .dir , func (dir * memFSNode , frag string , final bool ) error {
207
209
got := walkStep {
208
- name : dir . name ,
210
+ name : prevFrag ,
209
211
frag : frag ,
210
212
final : final ,
211
213
}
@@ -214,7 +216,7 @@ func TestWalk(t *testing.T) {
214
216
if got != want {
215
217
return fmt .Errorf ("got %+v, want %+v" , got , want )
216
218
}
217
- i ++
219
+ i , prevFrag = i + 1 , frag
218
220
return nil
219
221
})
220
222
if err != nil {
@@ -223,6 +225,36 @@ func TestWalk(t *testing.T) {
223
225
}
224
226
}
225
227
228
+ // find appends to ss the names of the named file and its children. It is
229
+ // analogous to the Unix find command.
230
+ //
231
+ // The returned strings are not guaranteed to be in any particular order.
232
+ func find (ss []string , fs FileSystem , name string ) ([]string , error ) {
233
+ stat , err := fs .Stat (name )
234
+ if err != nil {
235
+ return nil , err
236
+ }
237
+ ss = append (ss , name )
238
+ if stat .IsDir () {
239
+ f , err := fs .OpenFile (name , os .O_RDONLY , 0 )
240
+ if err != nil {
241
+ return nil , err
242
+ }
243
+ defer f .Close ()
244
+ children , err := f .Readdir (- 1 )
245
+ if err != nil {
246
+ return nil , err
247
+ }
248
+ for _ , c := range children {
249
+ ss , err = find (ss , fs , path .Join (name , c .Name ()))
250
+ if err != nil {
251
+ return nil , err
252
+ }
253
+ }
254
+ }
255
+ return ss , nil
256
+ }
257
+
226
258
func testFS (t * testing.T , fs FileSystem ) {
227
259
errStr := func (err error ) string {
228
260
switch {
@@ -236,8 +268,8 @@ func testFS(t *testing.T, fs FileSystem) {
236
268
return "ok"
237
269
}
238
270
239
- // The non-"stat" test cases should change the file system state. The
240
- // indentation of the "stat"s helps distinguish such test cases.
271
+ // The non-"find" non-" stat" test cases should change the file system state. The
272
+ // indentation of the "find"s and " stat"s helps distinguish such test cases.
241
273
testCases := []string {
242
274
" stat / want dir" ,
243
275
" stat /a want errNotExist" ,
@@ -252,6 +284,7 @@ func testFS(t *testing.T, fs FileSystem) {
252
284
" stat /d want dir" ,
253
285
"create /d/e EEE want ok" ,
254
286
" stat /d/e want 3" ,
287
+ " find / /a /d /d/e" ,
255
288
"create /d/f FFFF want ok" ,
256
289
"create /d/g GGGGGGG want ok" ,
257
290
"mk-dir /d/m want ok" ,
@@ -263,6 +296,7 @@ func testFS(t *testing.T, fs FileSystem) {
263
296
" stat /d/h want errNotExist" ,
264
297
" stat /d/m want dir" ,
265
298
" stat /d/m/p want 5" ,
299
+ " find / /a /d /d/e /d/f /d/g /d/m /d/m/p" ,
266
300
"rm-all /d want ok" ,
267
301
" stat /a want 1" ,
268
302
" stat /d want errNotExist" ,
@@ -271,6 +305,7 @@ func testFS(t *testing.T, fs FileSystem) {
271
305
" stat /d/g want errNotExist" ,
272
306
" stat /d/m want errNotExist" ,
273
307
" stat /d/m/p want errNotExist" ,
308
+ " find / /a" ,
274
309
"mk-dir /d/m want errNotExist" ,
275
310
"mk-dir /d want ok" ,
276
311
"create /d/f FFFF want ok" ,
@@ -285,6 +320,7 @@ func testFS(t *testing.T, fs FileSystem) {
285
320
" stat /c want errNotExist" ,
286
321
" stat /d want dir" ,
287
322
" stat /d/m want dir" ,
323
+ " find / /a /b /d /d/m" ,
288
324
"rename /b /b want ok" ,
289
325
" stat /b want 2" ,
290
326
" stat /c want errNotExist" ,
@@ -293,6 +329,7 @@ func testFS(t *testing.T, fs FileSystem) {
293
329
" stat /c want 2" ,
294
330
" stat /d/m want dir" ,
295
331
" stat /d/n want errNotExist" ,
332
+ " find / /a /c /d /d/m" ,
296
333
"rename /d/m /d/n want ok" ,
297
334
"create /d/n/q QQQQ want ok" ,
298
335
" stat /d/m want errNotExist" ,
@@ -302,6 +339,7 @@ func testFS(t *testing.T, fs FileSystem) {
302
339
"rename /c /d/n/q want ok" ,
303
340
" stat /c want errNotExist" ,
304
341
" stat /d/n/q want 2" ,
342
+ " find / /a /d /d/n /d/n/q" ,
305
343
"create /d/n/r RRRRR want ok" ,
306
344
"mk-dir /u want ok" ,
307
345
"mk-dir /u/v want ok" ,
@@ -316,10 +354,12 @@ func testFS(t *testing.T, fs FileSystem) {
316
354
" stat /t want dir" ,
317
355
" stat /t/q want 2" ,
318
356
" stat /t/r want 5" ,
357
+ " find / /a /d /t /t/q /t/r /u /u/v" ,
319
358
"rename /t / want err" ,
320
359
"rename /t /u/v want ok" ,
321
360
" stat /u/v/r want 5" ,
322
361
"rename / /x want err" ,
362
+ " find / /a /d /u /u/v /u/v/q /u/v/r" ,
323
363
}
324
364
325
365
for i , tc := range testCases {
@@ -352,6 +392,17 @@ func testFS(t *testing.T, fs FileSystem) {
352
392
}
353
393
}
354
394
395
+ case "find" :
396
+ got , err := find (nil , fs , "/" )
397
+ if err != nil {
398
+ t .Fatalf ("test case #%d %q: find: %v" , i , tc , err )
399
+ }
400
+ sort .Strings (got )
401
+ want := strings .Split (arg , " " )
402
+ if ! reflect .DeepEqual (got , want ) {
403
+ t .Fatalf ("test case #%d %q:\n got %s\n want %s" , i , tc , got , want )
404
+ }
405
+
355
406
case "mk-dir" , "rename" , "rm-all" , "stat" :
356
407
nParts := 3
357
408
if op == "rename" {
@@ -372,12 +423,22 @@ func testFS(t *testing.T, fs FileSystem) {
372
423
opErr = fs .RemoveAll (parts [0 ])
373
424
case "stat" :
374
425
var stat os.FileInfo
375
- if stat , opErr = fs .Stat (parts [0 ]); opErr == nil {
426
+ fileName := parts [0 ]
427
+ if stat , opErr = fs .Stat (fileName ); opErr == nil {
376
428
if stat .IsDir () {
377
429
got = "dir"
378
430
} else {
379
431
got = strconv .Itoa (int (stat .Size ()))
380
432
}
433
+
434
+ if fileName == "/" {
435
+ // For a Dir FileSystem, the virtual file system root maps to a
436
+ // real file system name like "/tmp/webdav-test012345", which does
437
+ // not end with "/". We skip such cases.
438
+ } else if statName := stat .Name (); path .Base (fileName ) != statName {
439
+ t .Fatalf ("test case #%d %q: file name %q inconsistent with stat name %q" ,
440
+ i , tc , fileName , statName )
441
+ }
381
442
}
382
443
}
383
444
if got == "" {
0 commit comments