1
2
3
4
5
6
7 package filesys
8
9 import (
10 "fmt"
11 "io"
12 "math/rand"
13 "os"
14 "path/filepath"
15 "sort"
16 "strings"
17 "testing"
18
19 "github.com/stretchr/testify/require"
20 )
21
22 const content = `
23 Lorem ipsum dolor sit amet,
24 consectetur adipiscing elit,
25 sed do eiusmod tempor incididunt
26 ut labore et dolore magna aliqua.
27 `
28 const shortContent = "hi"
29
30 var topCases = []pathCase{
31 {
32 what: "dotdot",
33 arg: ParentDir,
34 errStr: "illegal name '..' in file creation",
35 },
36 {
37 what: "colon",
38 arg: "a:b",
39 name: "a:b",
40 path: "a:b",
41 },
42 {
43 what: "empty",
44 arg: "",
45 name: "",
46 errStr: "illegal name '.' in file creation",
47 },
48 {
49 what: "simple",
50 arg: "bob",
51 name: "bob",
52 path: "bob",
53 },
54 {
55 what: "longer",
56 arg: filepath.Join("longer", "bob"),
57 name: "bob",
58 path: filepath.Join("longer", "bob"),
59 },
60 {
61 what: "longer yet",
62 arg: filepath.Join("longer", "foo", "bar", "beans", "bob"),
63 name: "bob",
64 path: filepath.Join("longer", "foo", "bar", "beans", "bob"),
65 },
66 {
67 what: "tricky",
68 arg: filepath.Join("bob", ParentDir, "sally"),
69 name: "sally",
70 path: "sally",
71 },
72 {
73 what: "trickier",
74 arg: filepath.Join("bob", "sally", ParentDir, ParentDir, "jean"),
75 name: "jean",
76 path: "jean",
77 },
78 }
79
80 func TestMakeEmptyDirInMemory(t *testing.T) {
81 n := MakeEmptyDirInMemory()
82 if !n.isNodeADir() {
83 t.Fatalf("not a directory")
84 }
85 if n.Size() != 0 {
86 t.Fatalf("unexpected size %d", n.Size())
87 }
88 if n.Name() != "" {
89 t.Fatalf("unexpected name '%s'", n.Name())
90 }
91 if n.Path() != "" {
92 t.Fatalf("unexpected path '%s'", n.Path())
93 }
94 runBasicOperations(
95 t, "MakeEmptyDirInMemory", false, topCases, n)
96 }
97
98 func TestMakeFsInMemory(t *testing.T) {
99 runBasicOperations(
100 t, "MakeFsInMemory", true, topCases, MakeFsInMemory())
101 }
102
103 func runBasicOperations(
104 t *testing.T, tName string, isFSysRooted bool,
105 cases []pathCase, fSys FileSystem) {
106 t.Helper()
107 for _, c := range cases {
108 err := fSys.WriteFile(c.arg, []byte(content))
109 if c.errStr != "" {
110 if err == nil {
111 t.Fatalf("%s; expected error writing to '%s'!", c.what, c.arg)
112 }
113 if !strings.Contains(err.Error(), c.errStr) {
114 t.Fatalf("%s; expected err containing '%s', got '%v'",
115 c.what, c.errStr, err)
116 }
117 continue
118 }
119 if err != nil {
120 t.Fatalf("%s; unexpected error: %v", c.what, err)
121 }
122 if !fSys.Exists(c.path) {
123 t.Fatalf("%s; expect existence of '%s'", c.what, c.path)
124 }
125 stuff, err := fSys.ReadFile(c.path)
126 if err != nil {
127 t.Fatalf("%s; unexpected error: %v", c.what, err)
128 }
129 if string(stuff) != content {
130 t.Fatalf("%s; unexpected content '%s'", c.what, stuff)
131 }
132 f, err := fSys.Open(c.arg)
133 if err != nil {
134 t.Fatalf("%s; unexpected error: %v", c.what, err)
135 }
136 fi, err := f.Stat()
137 if err != nil {
138 t.Fatalf("%s; unexpected error: %v", c.what, err)
139 }
140 if fi.Name() != c.name {
141 t.Fatalf("%s; expected name '%s', got '%s'", c.what, c.name, fi.Name())
142 }
143 buff, err := io.ReadAll(f)
144 if err != nil {
145 t.Fatalf("%s; unexpected error: %v", c.what, err)
146 }
147 if string(buff) != content {
148 t.Fatalf("%s; unexpected buff '%s'", c.what, buff)
149 }
150 count, err := f.Write([]byte(shortContent))
151 if err != nil {
152 t.Fatalf("%s; unexpected error: %v", c.what, err)
153 }
154 if count != len(shortContent) {
155 t.Fatalf("%s; unexpected count: %d", c.what, len(shortContent))
156 }
157 if err := f.Close(); err != nil {
158 t.Fatalf("%s; unexpected error: %v", c.what, err)
159 }
160 stuff, err = fSys.ReadFile(c.path)
161 if err != nil {
162 t.Fatalf("%s; unexpected error: %v", c.what, err)
163 }
164 both := content + shortContent
165 if string(stuff) != both {
166 t.Fatalf("%s; unexpected content '%s', expected '%s'", c.what, stuff, both)
167 }
168
169 content := []byte(shortContent)
170 if err := fSys.WriteFile(c.path, content); err != nil {
171 t.Fatalf("%s; unexpected error: %v", c.what, err)
172 }
173
174 content[0] = '@'
175 stuff, err = fSys.ReadFile(c.path)
176 if err != nil {
177 t.Fatalf("%s; unexpected error: %v", c.what, err)
178 }
179 if string(stuff) != shortContent {
180 t.Fatalf("%s; unexpected content '%s', expected '%s'", c.what, stuff, shortContent)
181 }
182 }
183
184 var actualPaths []string
185 var err error
186 prefix := ""
187 {
188 root := SelfDir
189 if isFSysRooted {
190 root = Separator
191 prefix = Separator
192 }
193 err = fSys.Walk(root, func(path string, info os.FileInfo, err error) error {
194 if err != nil {
195 fmt.Printf("err '%v' at path %q\n", err, path)
196 return nil
197 }
198 if !info.IsDir() {
199 actualPaths = append(actualPaths, path)
200 }
201 return nil
202 })
203 }
204 if err != nil {
205 t.Fatalf("unexpected error %v", err)
206 }
207 var expectedPaths []string
208 for _, c := range cases {
209 if c.errStr == "" {
210 expectedPaths = append(expectedPaths, prefix+c.path)
211 }
212 }
213 sort.Strings(expectedPaths)
214 assertEqualStringSlices(t, expectedPaths, actualPaths, tName)
215 }
216
217 type pathCase struct {
218 what string
219 arg string
220 name string
221 path string
222 errStr string
223 }
224
225 func TestAddDir(t *testing.T) {
226 cases := []pathCase{
227 {
228 what: "dotdot",
229 arg: ParentDir,
230 errStr: "cannot add a directory above ''",
231 },
232 {
233 what: "empty",
234 arg: "",
235 name: "",
236 path: "",
237 },
238 {
239 what: "simple",
240 arg: "bob",
241 name: "bob",
242 path: "bob",
243 },
244 {
245 what: "longer",
246 arg: filepath.Join("longer", "bob"),
247 name: "bob",
248 path: filepath.Join("longer", "bob"),
249 },
250 {
251 what: "longer yet",
252 arg: filepath.Join("longer", "foo", "bar", "beans", "bob"),
253 name: "bob",
254 path: filepath.Join("longer", "foo", "bar", "beans", "bob"),
255 },
256 {
257 what: "tricky",
258 arg: filepath.Join("bob", ParentDir, "sally"),
259 name: "sally",
260 path: "sally",
261 },
262 {
263 what: "trickier",
264 arg: filepath.Join("bob", "sally", ParentDir, ParentDir, "jean"),
265 name: "jean",
266 path: "jean",
267 },
268 }
269 for _, c := range cases {
270 n := MakeEmptyDirInMemory()
271 f, err := n.AddDir(c.arg)
272 if c.errStr != "" {
273 if err == nil {
274 t.Fatalf("%s; expected error!", c.what)
275 }
276 if !strings.Contains(err.Error(), c.errStr) {
277 t.Fatalf(
278 "%s; expected error with '%s', got '%v'",
279 c.what, c.errStr, err)
280 }
281 continue
282 }
283 if err != nil {
284 t.Fatalf("%s; unexpected error: %v", c.what, err)
285 }
286 checkNode(t, c.what, f, c.name, 0, true, c.path)
287 checkOsStat(t, c.what, f, f.Name(), 0, true)
288 }
289 }
290
291 var bagOfCases = []pathCase{
292 {
293 what: "empty",
294 arg: "",
295 errStr: "illegal name '.' in file creation",
296 },
297 {
298 what: "simple",
299 arg: "bob",
300 name: "bob",
301 path: "bob",
302 },
303 {
304 what: "longer",
305 arg: filepath.Join("longer", "bob"),
306 name: "bob",
307 path: filepath.Join("longer", "bob"),
308 },
309 {
310 what: "longer",
311 arg: filepath.Join("longer", "sally"),
312 name: "sally",
313 path: filepath.Join("longer", "sally"),
314 },
315 {
316 what: "even longer",
317 arg: filepath.Join("longer", "than", "the", "other", "bob"),
318 name: "bob",
319 path: filepath.Join("longer", "than", "the", "other", "bob"),
320 },
321 {
322 what: "even longer",
323 arg: filepath.Join("even", "much", "longer", "than", "the", "other", "bob"),
324 name: "bob",
325 path: filepath.Join("even", "much", "longer", "than", "the", "other", "bob"),
326 },
327 }
328
329 func TestAddFile(t *testing.T) {
330 n := MakeEmptyDirInMemory()
331 if n.FileCount() != 0 {
332 t.Fatalf("expected no files, got %d", n.FileCount())
333 }
334 expectedFileCount := 0
335 for _, c := range bagOfCases {
336 f, err := n.AddFile(c.arg, []byte(content))
337 if c.errStr != "" {
338 if err == nil {
339 t.Fatalf("%s; expected error!", c.what)
340 }
341 if !strings.Contains(err.Error(), c.errStr) {
342 t.Fatalf("%s; expected err containing '%s', got '%v'",
343 c.what, c.errStr, err)
344 }
345 continue
346 }
347 if err != nil {
348 t.Fatalf("%s; unexpected error %v", c.what, err)
349 }
350 checkNode(t, c.what, f, c.name, len(content), false, c.path)
351 checkOsStat(t, c.what, f, f.Name(), len(content), false)
352
353 result, err := n.Find(c.arg)
354 if err != nil {
355 t.Fatalf("%s; unexpected find error %v", c.what, err)
356 }
357 if result != f {
358 t.Fatalf("%s; unexpected find result %v", c.what, result)
359 }
360
361 result, err = n.Find(filepath.Join("longer", "bogus"))
362 if err != nil {
363 t.Fatalf("%s; unexpected find error %v", c.what, err)
364 }
365 if result != nil {
366 t.Fatalf("%s; unexpected find result %v", c.what, result)
367 }
368
369 expectedFileCount++
370 fc := n.FileCount()
371 if fc != expectedFileCount {
372 t.Fatalf("expected file count %d, got %d",
373 expectedFileCount, fc)
374 }
375 }
376 }
377
378 func checkNode(
379 t *testing.T, what string, f *fsNode, name string,
380 size int, isDir bool, path string) {
381 t.Helper()
382 if f.isNodeADir() != isDir {
383 t.Fatalf("%s; unexpected isNodeADir = %v", what, f.isNodeADir())
384 }
385 if f.Size() != int64(size) {
386 t.Fatalf("%s; unexpected size %d", what, f.Size())
387 }
388 if name != f.Name() {
389 t.Fatalf("%s; expected name '%s', got '%s'", what, name, f.Name())
390 }
391 if path != f.Path() {
392 t.Fatalf("%s; expected path '%s', got '%s'", what, path, f.Path())
393 }
394 }
395
396 func checkOsStat(
397 t *testing.T, what string, f File, name string,
398 size int, isDir bool) {
399 t.Helper()
400 info, err := f.Stat()
401 if err != nil {
402 t.Fatalf("%s; unexpected stat error %v", what, err)
403 }
404 if info.IsDir() != isDir {
405 t.Fatalf("%s; unexpected info.isNodeADir = %v", what, info.IsDir())
406 }
407 if info.Size() != int64(size) {
408 t.Fatalf("%s; unexpected info.size %d", what, info.Size())
409 }
410 if info.Name() != name {
411 t.Fatalf("%s; expected name '%s', got info.Name '%s'", what, name, info.Name())
412 }
413 }
414
415 var bunchOfFiles = []struct {
416 path string
417 addAsDir bool
418 }{
419 {
420 path: filepath.Join("b", "e", "a", "c", "g"),
421 },
422 {
423 path: filepath.Join("z", "r", "a", "b", "g"),
424 },
425 {
426 path: filepath.Join("b", "q", "a", "c", "g"),
427 },
428 {
429 path: filepath.Join("b", "a", "a", "m", "g"),
430 addAsDir: true,
431 },
432 {
433 path: filepath.Join("b", "w"),
434 },
435 {
436 path: filepath.Join("b", "d", "a", "c", "m"),
437 },
438 {
439 path: filepath.Join("b", "d", "z"),
440 },
441 {
442 path: filepath.Join("b", "d", "y"),
443 },
444 {
445 path: filepath.Join("b", "d", "ignore", "c", "n"),
446 },
447 {
448 path: filepath.Join("b", "d", "x"),
449 },
450 {
451 path: filepath.Join("b", "d", "ignore", "c", "o"),
452 },
453 {
454 path: filepath.Join("b", "d", "ignore", "c", "m"),
455 },
456 {
457 path: filepath.Join("b", "d", "a", "c", "i"),
458 addAsDir: true,
459 },
460 {
461 path: "x",
462 },
463 {
464 path: "y",
465 },
466 {
467 path: filepath.Join("b", "d", "a", "c", "i", "beans"),
468 },
469 {
470 path: filepath.Join("b", "d", "a", "c", "r", "w"),
471 addAsDir: true,
472 },
473 {
474 path: filepath.Join("b", "d", "a", "c", "u"),
475 },
476 {
477 path: filepath.Join("b", "d", ".hidden_file"),
478 },
479 {
480 path: filepath.Join("b", "d", ".hidden_dir"),
481 addAsDir: true,
482 },
483 }
484
485 func makeLoadedFileTree(t *testing.T) *fsNode {
486 t.Helper()
487 n := MakeEmptyDirInMemory()
488 var err error
489 expectedFileCount := 0
490 for _, item := range bunchOfFiles {
491 if item.addAsDir {
492 _, err = n.AddDir(item.path)
493 } else {
494 _, err = n.AddFile(item.path, []byte(content))
495 expectedFileCount++
496 }
497 if err != nil {
498 t.Fatalf("unexpected error %v", err)
499 }
500 }
501 if fc := n.FileCount(); fc != expectedFileCount {
502 t.Fatalf("expected file count %d, got %d",
503 expectedFileCount, fc)
504 }
505 return n
506 }
507
508 func TestWalkMe(t *testing.T) {
509 n := makeLoadedFileTree(t)
510 var actualPaths []string
511 err := n.WalkMe(func(path string, info os.FileInfo, err error) error {
512 if err != nil {
513 fmt.Printf("err '%v' at path %q\n", err, path)
514 return nil
515 }
516 if info.IsDir() {
517 if info.Name() == "ignore" {
518 return filepath.SkipDir
519 }
520 } else {
521 actualPaths = append(actualPaths, path)
522 }
523 return nil
524 })
525 if err != nil {
526 t.Fatalf("unexpected error %v", err)
527 }
528 var expectedPaths []string
529 for _, c := range bunchOfFiles {
530 if !c.addAsDir && !strings.Contains(c.path, "ignore") {
531 expectedPaths = append(expectedPaths, c.path)
532 }
533 }
534 sort.Strings(expectedPaths)
535 assertEqualStringSlices(t, expectedPaths, actualPaths, "testWalkMe")
536 }
537
538 func TestRemove(t *testing.T) {
539 n := makeLoadedFileTree(t)
540 orgCount := n.FileCount()
541
542
543 path := filepath.Join("b", "d", "ignore")
544 result, err := n.Find(path)
545 if err != nil {
546 t.Fatalf("%s; unexpected error %v", path, err)
547 }
548 if result == nil {
549 t.Fatalf("%s; expected to find '%s'", path, path)
550 }
551 if !result.isNodeADir() {
552 t.Fatalf("%s; expected to find a directory", path)
553 }
554 err = result.Remove()
555 if err != nil {
556 t.Fatalf("%s; unable to remove: %v", path, err)
557 }
558 result, err = n.Find(path)
559 if err != nil {
560
561 t.Fatalf("%s; unexpected error %v", path, err)
562 }
563 if result != nil {
564 t.Fatalf("%s; should not have been able to find '%s'", path, path)
565 }
566
567
568 orgCount -= 3
569
570
571 result, _ = n.Find("y")
572 err = result.Remove()
573 if err != nil {
574 t.Fatalf("%s; unable to remove: %v", path, err)
575 }
576 orgCount -= 1
577
578 if fc := n.FileCount(); fc != orgCount {
579 t.Fatalf("expected file count %d, got %d",
580 orgCount, fc)
581 }
582 }
583
584 func TestExists(t *testing.T) {
585 n := makeLoadedFileTree(t)
586 path := filepath.Join("b", "d", "a")
587 if !n.Exists(path) {
588 t.Fatalf("expected existence at %s", path)
589 }
590 if !n.IsDir(path) {
591 t.Fatalf("expected directory at %s", path)
592 }
593 }
594
595 func TestRegExpGlob(t *testing.T) {
596 n := makeLoadedFileTree(t)
597 expected := []string{
598 filepath.Join("b", "d", ".hidden_file"),
599 filepath.Join("b", "d", "a", "c", "i", "beans"),
600 filepath.Join("b", "d", "a", "c", "m"),
601 filepath.Join("b", "d", "a", "c", "u"),
602 filepath.Join("b", "d", "ignore", "c", "m"),
603 filepath.Join("b", "d", "ignore", "c", "n"),
604 filepath.Join("b", "d", "ignore", "c", "o"),
605 filepath.Join("b", "d", "x"),
606 filepath.Join("b", "d", "y"),
607 filepath.Join("b", "d", "z"),
608 }
609 paths, err := n.RegExpGlob("b/d/*")
610 if err != nil {
611 t.Fatalf("glob error: %v", err)
612 }
613 assertEqualStringSlices(t, expected, paths, "glob test")
614 }
615
616 func TestGlob(t *testing.T) {
617 n := makeLoadedFileTree(t)
618
619 tests := map[string]struct {
620 globPattern string
621 expectedFiles []string
622 }{
623 "VisibleFiles": {
624 globPattern: "b/d/*",
625 expectedFiles: []string{
626 filepath.Join("b", "d", "x"),
627 filepath.Join("b", "d", "y"),
628 filepath.Join("b", "d", "z"),
629 },
630 },
631 "HiddenFiles": {
632 globPattern: "b/d/.*",
633 expectedFiles: []string{
634 filepath.Join("b", "d", ".hidden_file"),
635 },
636 },
637 }
638
639 for test, c := range tests {
640 t.Run(test, func(t *testing.T) {
641 paths, err := n.Glob(c.globPattern)
642 if err != nil {
643 t.Fatalf("glob error: %v", err)
644 }
645 assertEqualStringSlices(t, c.expectedFiles, paths, "glob test")
646 })
647 }
648 }
649
650 func assertEqualStringSlices(t *testing.T, expected, actual []string, message string) {
651 t.Helper()
652 if len(expected) != len(actual) {
653 t.Fatalf(
654 "%s; unequal sizes; len(expected)=%d, len(actual)=%d\n%+v\n%+v\n",
655 message, len(expected), len(actual), expected, actual)
656 }
657 for i := range expected {
658 if expected[i] != actual[i] {
659 t.Fatalf(
660 "%s; unequal entries; expected=%s, actual=%s",
661 message, expected[i], actual[i])
662 }
663 }
664 }
665
666 func TestFind(t *testing.T) {
667 cases := []struct {
668 what string
669 arg string
670 expectDir bool
671 expectFile bool
672 errStr string
673 }{
674 {
675 what: "garbage",
676 arg: "///1(*&SA",
677 },
678 {
679 what: "simple",
680 arg: "bob",
681 },
682 {
683 what: "no directory",
684 arg: filepath.Join("b", "rrrrrr"),
685 },
686 {
687 what: "is a directory",
688 arg: filepath.Join("b", "d", "ignore"),
689 expectDir: true,
690 },
691 {
692 what: "longer, ending in file",
693 arg: filepath.Join("b", "d", "x"),
694 expectFile: true,
695 },
696 {
697 what: "moar longer, ending in file",
698 arg: filepath.Join("b", "d", "a", "c", "u"),
699 expectFile: true,
700 },
701 {
702 what: "directory",
703 arg: "b",
704 expectDir: true,
705 },
706 {
707
708
709
710
711
712
713
714
715
716
717
718 what: "empty name",
719 arg: "",
720 },
721 {
722 what: "self dir",
723 arg: SelfDir,
724 expectDir: true,
725 },
726 {
727 what: "parent dir - doesn't exist",
728 arg: ParentDir,
729 },
730 {
731 what: "many parents - doesn't exist",
732 arg: filepath.Join(ParentDir, ParentDir, ParentDir),
733 },
734 }
735
736 n := makeLoadedFileTree(t)
737 for _, item := range cases {
738 result, err := n.Find(item.arg)
739 if item.errStr != "" {
740 if err == nil {
741 t.Fatalf("%s; expected error", item.what)
742 }
743 if !strings.Contains(err.Error(), item.errStr) {
744 t.Fatalf("%s; expected err containing '%s', got '%v'",
745 item.what, item.errStr, err)
746 }
747 continue
748 }
749 if err != nil {
750 t.Fatalf("%s; unexpected error: %v", item.what, err)
751 }
752 if result == nil {
753 if item.expectDir {
754 t.Fatalf(
755 "%s; expected to find directory '%s'", item.what, item.arg)
756 }
757 if item.expectFile {
758 t.Fatalf(
759 "%s; expected to find file '%s'", item.what, item.arg)
760 }
761 continue
762 }
763 if item.expectDir {
764 if !result.isNodeADir() {
765 t.Fatalf(
766 "%s; expected '%s' to be a directory", item.what, item.arg)
767 }
768 continue
769 }
770 if item.expectFile {
771 if result.isNodeADir() {
772 t.Fatalf("%s; expected '%s' to be a file", item.what, item.arg)
773 }
774 continue
775 }
776 t.Fatalf(
777 "%s; expected nothing for '%s', but got '%s'",
778 item.what, item.arg, result.Path())
779 }
780 }
781
782 func TestCleanedAbs(t *testing.T) {
783 cases := []struct {
784 what string
785 full string
786 cDir string
787 name string
788 errStr string
789 }{
790 {
791 what: "empty",
792 full: "",
793 errStr: "doesn't exist",
794 },
795 {
796 what: "simple",
797 full: "bob",
798 errStr: "'bob' doesn't exist",
799 },
800 {
801 what: "no directory",
802 full: filepath.Join("b", "rrrrrr"),
803 errStr: "'b/rrrrrr' doesn't exist",
804 },
805 {
806 what: "longer, ending in file",
807 full: filepath.Join("b", "d", "x"),
808 cDir: filepath.Join("b", "d"),
809 name: "x",
810 },
811 {
812 what: "moar longer, ending in file",
813 full: filepath.Join("b", "d", "a", "c", "u"),
814 cDir: filepath.Join("b", "d", "a", "c"),
815 name: "u",
816 },
817 {
818 what: "directory",
819 full: filepath.Join("b", "d"),
820 cDir: filepath.Join("b", "d"),
821 name: "",
822 },
823 }
824
825 n := makeLoadedFileTree(t)
826 for _, item := range cases {
827 cDir, name, err := n.CleanedAbs(item.full)
828 if item.errStr != "" {
829 if err == nil {
830 t.Fatalf("%s; expected error", item.what)
831 }
832 if !strings.Contains(err.Error(), item.errStr) {
833 t.Fatalf("%s; expected err containing '%s', got '%v'",
834 item.what, item.errStr, err)
835 }
836 continue
837 }
838 if err != nil {
839 t.Fatalf("%s; unexpected error: %v", item.what, err)
840 }
841 if cDir != ConfirmedDir(item.cDir) {
842 t.Fatalf("%s; expected cDir=%s, got '%s'", item.what, item.cDir, cDir)
843 }
844 if name != item.name {
845 t.Fatalf("%s; expected name=%s, got '%s'", item.what, item.name, name)
846 }
847 }
848 }
849
850 func TestConfirmDirMemRoot(t *testing.T) {
851 fSys := MakeFsInMemory()
852 actual, err := ConfirmDir(fSys, Separator)
853 require.NoError(t, err)
854 require.Equal(t, Separator, actual.String())
855 }
856
857 func TestConfirmDirRelativeNode(t *testing.T) {
858 req := require.New(t)
859 fSysEmpty := MakeEmptyDirInMemory()
860
861 fSysRoot, err := fSysEmpty.AddDir("a")
862 req.NoError(err)
863 fSysSub, err := fSysRoot.AddDir("b")
864 req.NoError(err)
865 err = fSysSub.Mkdir("c")
866 req.NoError(err)
867
868 expected := filepath.Join("a", "b", "c")
869 req.Truef(fSysEmpty.Exists(expected), existMsg, expected)
870
871 actual, err := ConfirmDir(fSysSub, "c")
872 req.NoError(err)
873 req.Equal(expected, actual.String())
874 }
875
876 func TestFileOps(t *testing.T) {
877 const path = "foo.txt"
878 content := strings.Repeat("longest content", 100)
879
880 fs := MakeFsInMemory()
881 f, err := fs.Create(path)
882 if err != nil {
883 t.Fatalf("unexpected error: %v", err)
884 }
885 if _, err := fs.Open(path); err == nil {
886 t.Fatalf("expected already opened error, got nil")
887 }
888 if _, err := fmt.Fprint(f, content); err != nil {
889 t.Fatalf("unexpected error: %v", err)
890 }
891
892 if err := f.Close(); err != nil {
893 t.Fatalf("unexpected error: %v", err)
894 }
895 if err := f.Close(); err == nil {
896 t.Fatalf("expected already closed error, got nil")
897 }
898
899 f, err = fs.Open(path)
900 if err != nil {
901 t.Fatalf("unexpected error: %v", err)
902 }
903 defer f.Close()
904
905 for {
906 buf := make([]byte, rand.Intn(10))
907 n, err := f.Read(buf)
908 if err != nil && err != io.EOF {
909 t.Fatalf("unexpected error: %v", err)
910 }
911 if content[:n] != string(buf[:n]) {
912 t.Fatalf("unexpected read: expected %q got %q", content[:n], buf[:n])
913 }
914 content = content[n:]
915 if err != io.EOF {
916 continue
917 }
918 if len(content) == 0 {
919 break
920 }
921 t.Fatalf("unexpected EOF: remaining %d bytes", len(content))
922 }
923 }
924
View as plain text