1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package afero
16
17 import (
18 "bytes"
19 "fmt"
20 "io"
21 iofs "io/fs"
22 "os"
23 "path/filepath"
24 "runtime"
25 "strings"
26 "syscall"
27 "testing"
28 )
29
30 var (
31 testName = "test.txt"
32 Fss = []Fs{&MemMapFs{}, &OsFs{}}
33 )
34
35 var testRegistry map[Fs][]string = make(map[Fs][]string)
36
37 func testDir(fs Fs) string {
38 name, err := TempDir(fs, "", "afero")
39 if err != nil {
40 panic(fmt.Sprint("unable to work with test dir", err))
41 }
42 testRegistry[fs] = append(testRegistry[fs], name)
43
44 return name
45 }
46
47 func tmpFile(fs Fs) File {
48 x, err := TempFile(fs, "", "afero")
49 if err != nil {
50 panic(fmt.Sprint("unable to work with temp file", err))
51 }
52
53 testRegistry[fs] = append(testRegistry[fs], x.Name())
54
55 return x
56 }
57
58
59 func TestRead0(t *testing.T) {
60 for _, fs := range Fss {
61 f := tmpFile(fs)
62 defer f.Close()
63 f.WriteString("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
64
65 var b []byte
66
67 n, err := f.Read(b)
68 if n != 0 || err != nil {
69 t.Errorf("%v: Read(0) = %d, %v, want 0, nil", fs.Name(), n, err)
70 }
71 f.Seek(0, 0)
72 b = make([]byte, 100)
73 n, err = f.Read(b)
74 if n <= 0 || err != nil {
75 t.Errorf("%v: Read(100) = %d, %v, want >0, nil", fs.Name(), n, err)
76 }
77 }
78 }
79
80 func TestOpenFile(t *testing.T) {
81 defer removeAllTestFiles(t)
82 for _, fs := range Fss {
83 tmp := testDir(fs)
84 path := filepath.Join(tmp, testName)
85
86 f, err := fs.OpenFile(path, os.O_RDWR|os.O_CREATE, 0o600)
87 if err != nil {
88 t.Error(fs.Name(), "OpenFile (O_CREATE) failed:", err)
89 continue
90 }
91 io.WriteString(f, "initial")
92 f.Close()
93
94 f, err = fs.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0o600)
95 if err != nil {
96 t.Error(fs.Name(), "OpenFile (O_APPEND) failed:", err)
97 continue
98 }
99 io.WriteString(f, "|append")
100 f.Close()
101
102 f, _ = fs.OpenFile(path, os.O_RDONLY, 0o600)
103 contents, _ := io.ReadAll(f)
104 expectedContents := "initial|append"
105 if string(contents) != expectedContents {
106 t.Errorf("%v: appending, expected '%v', got: '%v'", fs.Name(), expectedContents, string(contents))
107 }
108 f.Close()
109
110 f, err = fs.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0o600)
111 if err != nil {
112 t.Error(fs.Name(), "OpenFile (O_TRUNC) failed:", err)
113 continue
114 }
115 contents, _ = io.ReadAll(f)
116 if string(contents) != "" {
117 t.Errorf("%v: expected truncated file, got: '%v'", fs.Name(), string(contents))
118 }
119 f.Close()
120 }
121 }
122
123 func TestCreate(t *testing.T) {
124 defer removeAllTestFiles(t)
125 for _, fs := range Fss {
126 tmp := testDir(fs)
127 path := filepath.Join(tmp, testName)
128
129 f, err := fs.Create(path)
130 if err != nil {
131 t.Error(fs.Name(), "Create failed:", err)
132 f.Close()
133 continue
134 }
135 io.WriteString(f, "initial")
136 f.Close()
137
138 f, err = fs.Create(path)
139 if err != nil {
140 t.Error(fs.Name(), "Create failed:", err)
141 f.Close()
142 continue
143 }
144 secondContent := "second create"
145 io.WriteString(f, secondContent)
146 f.Close()
147
148 f, err = fs.Open(path)
149 if err != nil {
150 t.Error(fs.Name(), "Open failed:", err)
151 f.Close()
152 continue
153 }
154 buf, err := ReadAll(f)
155 if err != nil {
156 t.Error(fs.Name(), "ReadAll failed:", err)
157 f.Close()
158 continue
159 }
160 if string(buf) != secondContent {
161 t.Error(fs.Name(), "Content should be", "\""+secondContent+"\" but is \""+string(buf)+"\"")
162 f.Close()
163 continue
164 }
165 f.Close()
166 }
167 }
168
169 func TestMemFileRead(t *testing.T) {
170 f := tmpFile(new(MemMapFs))
171
172 f.WriteString("abcd")
173 f.Seek(0, 0)
174 b := make([]byte, 8)
175 n, err := f.Read(b)
176 if n != 4 {
177 t.Errorf("didn't read all bytes: %v %v %v", n, err, b)
178 }
179 if err != nil {
180 t.Errorf("err is not nil: %v %v %v", n, err, b)
181 }
182 n, err = f.Read(b)
183 if n != 0 {
184 t.Errorf("read more bytes: %v %v %v", n, err, b)
185 }
186 if err != io.EOF {
187 t.Errorf("error is not EOF: %v %v %v", n, err, b)
188 }
189 }
190
191 func TestRename(t *testing.T) {
192 defer removeAllTestFiles(t)
193 for _, fs := range Fss {
194 tDir := testDir(fs)
195 from := filepath.Join(tDir, "/renamefrom")
196 to := filepath.Join(tDir, "/renameto")
197 exists := filepath.Join(tDir, "/renameexists")
198 file, err := fs.Create(from)
199 if err != nil {
200 t.Fatalf("%s: open %q failed: %v", fs.Name(), to, err)
201 }
202 if err = file.Close(); err != nil {
203 t.Errorf("%s: close %q failed: %v", fs.Name(), to, err)
204 }
205 file, err = fs.Create(exists)
206 if err != nil {
207 t.Fatalf("%s: open %q failed: %v", fs.Name(), to, err)
208 }
209 if err = file.Close(); err != nil {
210 t.Errorf("%s: close %q failed: %v", fs.Name(), to, err)
211 }
212 err = fs.Rename(from, to)
213 if err != nil {
214 t.Fatalf("%s: rename %q, %q failed: %v", fs.Name(), to, from, err)
215 }
216 file, err = fs.Create(from)
217 if err != nil {
218 t.Fatalf("%s: open %q failed: %v", fs.Name(), to, err)
219 }
220 if err = file.Close(); err != nil {
221 t.Errorf("%s: close %q failed: %v", fs.Name(), to, err)
222 }
223 err = fs.Rename(from, exists)
224 if err != nil {
225 t.Errorf("%s: rename %q, %q failed: %v", fs.Name(), exists, from, err)
226 }
227 names, err := readDirNames(fs, tDir)
228 if err != nil {
229 t.Errorf("%s: readDirNames error: %v", fs.Name(), err)
230 }
231 found := false
232 for _, e := range names {
233 if e == "renamefrom" {
234 t.Error("File is still called renamefrom")
235 }
236 if e == "renameto" {
237 found = true
238 }
239 }
240 if !found {
241 t.Error("File was not renamed to renameto")
242 }
243
244 _, err = fs.Stat(to)
245 if err != nil {
246 t.Errorf("%s: stat %q failed: %v", fs.Name(), to, err)
247 }
248 }
249 }
250
251 func TestRemove(t *testing.T) {
252 for _, fs := range Fss {
253
254 x, err := TempFile(fs, "", "afero")
255 if err != nil {
256 t.Error(fmt.Sprint("unable to work with temp file", err))
257 }
258
259 path := x.Name()
260 x.Close()
261
262 tDir := filepath.Dir(path)
263
264 err = fs.Remove(path)
265 if err != nil {
266 t.Errorf("%v: Remove() failed: %v", fs.Name(), err)
267 continue
268 }
269
270 _, err = fs.Stat(path)
271 if !os.IsNotExist(err) {
272 t.Errorf("%v: Remove() didn't remove file", fs.Name())
273 continue
274 }
275
276
277 err = fs.Remove(path)
278 if !os.IsNotExist(err) {
279 t.Errorf("%v: Remove() didn't raise error for non-existent file", fs.Name())
280 }
281
282 f, err := fs.Open(tDir)
283 if err != nil {
284 t.Error("TestDir should still exist:", err)
285 }
286
287 names, err := f.Readdirnames(-1)
288 if err != nil {
289 t.Error("Readdirnames failed:", err)
290 }
291
292 for _, e := range names {
293 if e == testName {
294 t.Error("File was not removed from parent directory")
295 }
296 }
297 }
298 }
299
300 func TestTruncate(t *testing.T) {
301 defer removeAllTestFiles(t)
302 for _, fs := range Fss {
303 f := tmpFile(fs)
304 defer f.Close()
305
306 checkSize(t, f, 0)
307 f.Write([]byte("hello, world\n"))
308 checkSize(t, f, 13)
309 f.Truncate(10)
310 checkSize(t, f, 10)
311 f.Truncate(1024)
312 checkSize(t, f, 1024)
313 f.Truncate(0)
314 checkSize(t, f, 0)
315 _, err := f.Write([]byte("surprise!"))
316 if err == nil {
317 checkSize(t, f, 13+9)
318 }
319 }
320 }
321
322 func TestSeek(t *testing.T) {
323 defer removeAllTestFiles(t)
324 for _, fs := range Fss {
325 f := tmpFile(fs)
326 defer f.Close()
327
328 const data = "hello, world\n"
329 io.WriteString(f, data)
330
331 type test struct {
332 in int64
333 whence int
334 out int64
335 }
336 tests := []test{
337 {0, 1, int64(len(data))},
338 {0, 0, 0},
339 {5, 0, 5},
340 {0, 2, int64(len(data))},
341 {0, 0, 0},
342 {-1, 2, int64(len(data)) - 1},
343 {1 << 33, 0, 1 << 33},
344 {1 << 33, 2, 1<<33 + int64(len(data))},
345 }
346 for i, tt := range tests {
347 off, err := f.Seek(tt.in, tt.whence)
348 if off != tt.out || err != nil {
349 if e, ok := err.(*os.PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 {
350
351
352 break
353 }
354 t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
355 }
356 }
357 }
358 }
359
360 func TestReadAt(t *testing.T) {
361 defer removeAllTestFiles(t)
362 for _, fs := range Fss {
363 f := tmpFile(fs)
364 defer f.Close()
365
366 const data = "hello, world\n"
367 io.WriteString(f, data)
368
369 b := make([]byte, 5)
370 n, err := f.ReadAt(b, 7)
371 if err != nil || n != len(b) {
372 t.Fatalf("ReadAt 7: %d, %v", n, err)
373 }
374 if string(b) != "world" {
375 t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
376 }
377 }
378 }
379
380 func TestWriteAt(t *testing.T) {
381 defer removeAllTestFiles(t)
382 for _, fs := range Fss {
383 f := tmpFile(fs)
384 defer f.Close()
385
386 const data = "hello, world\n"
387 io.WriteString(f, data)
388
389 n, err := f.WriteAt([]byte("WORLD"), 7)
390 if err != nil || n != 5 {
391 t.Fatalf("WriteAt 7: %d, %v", n, err)
392 }
393
394 f2, err := fs.Open(f.Name())
395 if err != nil {
396 t.Fatalf("%v: ReadFile %s: %v", fs.Name(), f.Name(), err)
397 }
398 defer f2.Close()
399 buf := new(bytes.Buffer)
400 buf.ReadFrom(f2)
401 b := buf.Bytes()
402 if string(b) != "hello, WORLD\n" {
403 t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n")
404 }
405
406 }
407 }
408
409 func setupTestDir(t *testing.T, fs Fs) string {
410 path := testDir(fs)
411 return setupTestFiles(t, fs, path)
412 }
413
414 func setupTestDirRoot(t *testing.T, fs Fs) string {
415 path := testDir(fs)
416 setupTestFiles(t, fs, path)
417 return path
418 }
419
420 func setupTestDirReusePath(t *testing.T, fs Fs, path string) string {
421 testRegistry[fs] = append(testRegistry[fs], path)
422 return setupTestFiles(t, fs, path)
423 }
424
425 func setupTestFiles(t *testing.T, fs Fs, path string) string {
426 testSubDir := filepath.Join(path, "more", "subdirectories", "for", "testing", "we")
427 err := fs.MkdirAll(testSubDir, 0o700)
428 if err != nil && !os.IsExist(err) {
429 t.Fatal(err)
430 }
431
432 f, err := fs.Create(filepath.Join(testSubDir, "testfile1"))
433 if err != nil {
434 t.Fatal(err)
435 }
436 f.WriteString("Testfile 1 content")
437 f.Close()
438
439 f, err = fs.Create(filepath.Join(testSubDir, "testfile2"))
440 if err != nil {
441 t.Fatal(err)
442 }
443 f.WriteString("Testfile 2 content")
444 f.Close()
445
446 f, err = fs.Create(filepath.Join(testSubDir, "testfile3"))
447 if err != nil {
448 t.Fatal(err)
449 }
450 f.WriteString("Testfile 3 content")
451 f.Close()
452
453 f, err = fs.Create(filepath.Join(testSubDir, "testfile4"))
454 if err != nil {
455 t.Fatal(err)
456 }
457 f.WriteString("Testfile 4 content")
458 f.Close()
459 return testSubDir
460 }
461
462 func TestReaddirnames(t *testing.T) {
463 defer removeAllTestFiles(t)
464 for _, fs := range Fss {
465 testSubDir := setupTestDir(t, fs)
466 tDir := filepath.Dir(testSubDir)
467
468 root, err := fs.Open(tDir)
469 if err != nil {
470 t.Fatal(fs.Name(), tDir, err)
471 }
472 defer root.Close()
473
474 namesRoot, err := root.Readdirnames(-1)
475 if err != nil {
476 t.Fatal(fs.Name(), namesRoot, err)
477 }
478
479 sub, err := fs.Open(testSubDir)
480 if err != nil {
481 t.Fatal(err)
482 }
483 defer sub.Close()
484
485 namesSub, err := sub.Readdirnames(-1)
486 if err != nil {
487 t.Fatal(fs.Name(), namesSub, err)
488 }
489
490 findNames(fs, t, tDir, testSubDir, namesRoot, namesSub)
491 }
492 }
493
494 func TestReaddirSimple(t *testing.T) {
495 defer removeAllTestFiles(t)
496 for _, fs := range Fss {
497 testSubDir := setupTestDir(t, fs)
498 tDir := filepath.Dir(testSubDir)
499
500 root, err := fs.Open(tDir)
501 if err != nil {
502 t.Fatal(err)
503 }
504 defer root.Close()
505
506 rootInfo, err := root.Readdir(1)
507 if err != nil {
508 t.Log(myFileInfo(rootInfo))
509 t.Error(err)
510 }
511
512 rootInfo, err = root.Readdir(5)
513 if err != io.EOF {
514 t.Log(myFileInfo(rootInfo))
515 t.Error(err)
516 }
517
518 sub, err := fs.Open(testSubDir)
519 if err != nil {
520 t.Fatal(err)
521 }
522 defer sub.Close()
523
524 subInfo, err := sub.Readdir(5)
525 if err != nil {
526 t.Log(myFileInfo(subInfo))
527 t.Error(err)
528 }
529 }
530 }
531
532 func TestReaddir(t *testing.T) {
533 defer removeAllTestFiles(t)
534 const nums = 6
535 for num := 0; num < nums; num++ {
536 outputs := make([]string, len(Fss))
537 infos := make([]string, len(Fss))
538 for i, fs := range Fss {
539 testSubDir := setupTestDir(t, fs)
540 root, err := fs.Open(testSubDir)
541 if err != nil {
542 t.Fatal(err)
543 }
544
545 infosn := make([]string, nums)
546
547 for j := 0; j < nums; j++ {
548 info, err := root.Readdir(num)
549 outputs[i] += fmt.Sprintf("%v Error: %v\n", myFileInfo(info), err)
550 s := fmt.Sprintln(len(info), err)
551 infosn[j] = s
552 infos[i] += s
553 }
554 root.Close()
555
556
557 if _, ok := root.(iofs.ReadDirFile); ok {
558 root, err = fs.Open(testSubDir)
559 if err != nil {
560 t.Fatal(err)
561 }
562 defer root.Close()
563
564 for j := 0; j < nums; j++ {
565 dirEntries, err := root.(iofs.ReadDirFile).ReadDir(num)
566 s := fmt.Sprintln(len(dirEntries), err)
567 if s != infosn[j] {
568 t.Fatalf("%s: %s != %s", fs.Name(), s, infosn[j])
569 }
570 }
571 }
572 }
573
574 fail := false
575 for i, o := range infos {
576 if i == 0 {
577 continue
578 }
579 if o != infos[i-1] {
580 fail = true
581 break
582 }
583 }
584 if fail {
585 t.Log("Readdir outputs not equal for Readdir(", num, ")")
586 for i, o := range outputs {
587 t.Log(Fss[i].Name())
588 t.Log(o)
589 }
590 t.Fail()
591 }
592 }
593 }
594
595
596 func TestReaddirRegularFile(t *testing.T) {
597 defer removeAllTestFiles(t)
598 for _, fs := range Fss {
599 f := tmpFile(fs)
600 defer f.Close()
601
602 _, err := f.Readdirnames(-1)
603 if err == nil {
604 t.Fatal("Expected error")
605 }
606
607 _, err = f.Readdir(-1)
608 if err == nil {
609 t.Fatal("Expected error")
610 }
611 }
612 }
613
614 type myFileInfo []os.FileInfo
615
616 func (m myFileInfo) String() string {
617 out := "Fileinfos:\n"
618 for _, e := range m {
619 out += " " + e.Name() + "\n"
620 }
621 return out
622 }
623
624 func TestReaddirAll(t *testing.T) {
625 defer removeAllTestFiles(t)
626 for _, fs := range Fss {
627 testSubDir := setupTestDir(t, fs)
628 tDir := filepath.Dir(testSubDir)
629
630 root, err := fs.Open(tDir)
631 if err != nil {
632 t.Fatal(err)
633 }
634 defer root.Close()
635
636 rootInfo, err := root.Readdir(-1)
637 if err != nil {
638 t.Fatal(err)
639 }
640 namesRoot := []string{}
641 for _, e := range rootInfo {
642 namesRoot = append(namesRoot, e.Name())
643 }
644
645 sub, err := fs.Open(testSubDir)
646 if err != nil {
647 t.Fatal(err)
648 }
649 defer sub.Close()
650
651 subInfo, err := sub.Readdir(-1)
652 if err != nil {
653 t.Fatal(err)
654 }
655 namesSub := []string{}
656 for _, e := range subInfo {
657 namesSub = append(namesSub, e.Name())
658 }
659
660 findNames(fs, t, tDir, testSubDir, namesRoot, namesSub)
661 }
662 }
663
664 func findNames(fs Fs, t *testing.T, tDir, testSubDir string, root, sub []string) {
665 var foundRoot bool
666 for _, e := range root {
667 f, err := fs.Open(filepath.Join(tDir, e))
668 if err != nil {
669 t.Error("Open", filepath.Join(tDir, e), ":", err)
670 }
671 defer f.Close()
672
673 if equal(e, "we") {
674 foundRoot = true
675 }
676 }
677 if !foundRoot {
678 t.Logf("Names root: %v", root)
679 t.Logf("Names sub: %v", sub)
680 t.Error("Didn't find subdirectory we")
681 }
682
683 var found1, found2 bool
684 for _, e := range sub {
685 f, err := fs.Open(filepath.Join(testSubDir, e))
686 if err != nil {
687 t.Error("Open", filepath.Join(testSubDir, e), ":", err)
688 }
689 defer f.Close()
690
691 if equal(e, "testfile1") {
692 found1 = true
693 }
694 if equal(e, "testfile2") {
695 found2 = true
696 }
697 }
698
699 if !found1 {
700 t.Logf("Names root: %v", root)
701 t.Logf("Names sub: %v", sub)
702 t.Error("Didn't find testfile1")
703 }
704 if !found2 {
705 t.Logf("Names root: %v", root)
706 t.Logf("Names sub: %v", sub)
707 t.Error("Didn't find testfile2")
708 }
709 }
710
711 func removeAllTestFiles(t *testing.T) {
712 for fs, list := range testRegistry {
713 for _, path := range list {
714 if err := fs.RemoveAll(path); err != nil {
715 t.Error(fs.Name(), err)
716 }
717 }
718 }
719 testRegistry = make(map[Fs][]string)
720 }
721
722 func equal(name1, name2 string) (r bool) {
723 switch runtime.GOOS {
724 case "windows":
725 r = strings.EqualFold(name1, name2)
726 default:
727 r = name1 == name2
728 }
729 return
730 }
731
732 func checkSize(t *testing.T, f File, size int64) {
733 dir, err := f.Stat()
734 if err != nil {
735 t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
736 }
737 if dir.Size() != size {
738 t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size)
739 }
740 }
741
View as plain text