memfs - file_rw_test.go
1 package memfs
2
3 import (
4 "bytes"
5 "errors"
6 "io"
7 "io/fs"
8 "reflect"
9 "strings"
10 "sync"
11 "testing"
12 )
13
14 var _ interface {
15 io.ReadSeekCloser
16 io.ReaderAt
17 io.Writer
18 io.WriterTo
19 io.WriterAt
20 io.RuneScanner
21 io.ByteScanner
22 io.ByteWriter
23 } = &File{}
24
25 func TestReadRW(t *testing.T) {
26 for n, test := range [...]struct {
27 Data []byte
28 Mode opMode
29 Err error
30 }{
31 {
32 Err: &fs.PathError{
33 Op: "read",
34 Err: fs.ErrClosed,
35 },
36 },
37 {
38 Mode: opRead,
39 },
40 {
41 Data: []byte("Hello, World"),
42 Mode: opRead,
43 },
44 {
45 Data: []byte(strings.Repeat("Hello, World!", 1000)),
46 Mode: opRead,
47 },
48 {
49 Mode: opSeek,
50 Err: &fs.PathError{
51 Op: "read",
52 Err: fs.ErrInvalid,
53 },
54 },
55 } {
56 f := File{
57 mu: &sync.RWMutex{},
58 file: file{
59 inode: &inode{
60 data: test.Data,
61 },
62 opMode: test.Mode,
63 },
64 }
65
66 data, err := io.ReadAll(&f)
67 if !reflect.DeepEqual(err, test.Err) {
68 t.Errorf("test %d: expecting error %s, got %s", n+1, test.Err, err)
69 } else if !bytes.Equal(data, test.Data) {
70 t.Errorf("test %d: expecting bytes %v, got %v", n+1, test.Data, data)
71 }
72 }
73 }
74
75 func TestReadAtRW(t *testing.T) {
76 for n, test := range [...]struct {
77 Data []byte
78 Mode opMode
79 Read [][2]int64
80 Output [][]byte
81 Err error
82 }{
83 {
84 Err: fs.ErrClosed,
85 },
86 {
87 Data: []byte("Hello, World"),
88 Mode: opRead,
89 Read: [][2]int64{
90 {1, 0},
91 },
92 Output: [][]byte{
93 []byte("H"),
94 },
95 Err: &fs.PathError{
96 Op: "readat",
97 Path: "",
98 Err: fs.ErrInvalid,
99 },
100 },
101 {
102 Mode: opSeek,
103 Data: []byte("Hello, World"),
104 Read: [][2]int64{
105 {1, 0},
106 },
107 Output: [][]byte{
108 []byte("H"),
109 },
110 Err: &fs.PathError{
111 Op: "readat",
112 Path: "",
113 Err: fs.ErrInvalid,
114 },
115 },
116 {
117 Mode: opRead | opSeek,
118 Data: []byte("Hello, World"),
119 Read: [][2]int64{
120 {1, 0},
121 },
122 Output: [][]byte{
123 []byte("H"),
124 },
125 },
126 {
127 Mode: opRead | opSeek,
128 Data: []byte("Hello, World"),
129 Read: [][2]int64{
130 {1, 0},
131 {1, 0},
132 {2, 0},
133 {2, 4},
134 {4, 2},
135 },
136 Output: [][]byte{
137 []byte("H"),
138 []byte("H"),
139 []byte("He"),
140 []byte("o,"),
141 []byte("llo,"),
142 },
143 },
144 } {
145 f := File{
146 mu: &sync.RWMutex{},
147 file: file{
148 inode: &inode{
149 data: test.Data,
150 },
151 opMode: test.Mode,
152 },
153 }
154
155 readAtTests := func(o int) bool {
156 for m, toRead := range test.Read {
157 buf := make([]byte, toRead[0])
158 l, err := f.ReadAt(buf, toRead[1])
159 if !reflect.DeepEqual(err, test.Err) {
160 t.Errorf("test %d.%d.%d: expecting error %s, got %s", n+1, o, m+1, test.Err, err)
161
162 return false
163 } else if test.Err != nil {
164 return false
165 } else if len(buf) != l {
166 t.Errorf("test %d.%d.%d: expecting to read %d bytes, read %d", n+1, o, m+1, len(buf), l)
167
168 return false
169 } else if string(buf) != string(test.Output[m]) {
170 t.Errorf("test %d.%d.%d: expecting to read %s, read %s", n+1, o, m+1, test.Output[m], buf)
171
172 return false
173 }
174 }
175
176 return true
177 }
178
179 if !readAtTests(1) {
180 continue
181 }
182
183 if !readAtTests(2) {
184 continue
185 }
186
187 if test.Err != nil {
188 continue
189 }
190
191 _, err := f.Read([]byte{1})
192 if err != nil {
193 t.Errorf("test %d: unexpected error: %s", n+1, err)
194
195 continue
196 }
197
198 if !readAtTests(3) {
199 continue
200 }
201
202 _, err = f.Read([]byte{2})
203 if err != nil {
204 t.Errorf("test %d: unexpected error: %s", n+1, err)
205
206 continue
207 }
208
209 if !readAtTests(4) {
210 continue
211 }
212
213 _, err = io.ReadAll(&f)
214 if err != nil {
215 t.Errorf("test %d: unexpected error: %s", n+1, err)
216
217 continue
218 }
219
220 if !readAtTests(5) {
221 continue
222 }
223 }
224 }
225
226 func TestReadByteRW(t *testing.T) {
227 Tests:
228 for n, test := range [...]struct {
229 Data []byte
230 Mode opMode
231 Err error
232 }{
233 {
234 Err: &fs.PathError{
235 Op: "readbyte",
236 Path: "",
237 Err: fs.ErrInvalid,
238 },
239 },
240 {
241 Data: []byte{'a'},
242 Err: &fs.PathError{
243 Op: "readbyte",
244 Path: "",
245 Err: fs.ErrClosed,
246 },
247 },
248 {
249 Data: []byte("abc"),
250 Mode: opRead,
251 },
252 } {
253 f := File{
254 mu: &sync.RWMutex{},
255 file: file{
256 inode: &inode{
257 data: test.Data,
258 },
259 opMode: test.Mode,
260 },
261 }
262
263 for i := range test.Data {
264 b, err := f.ReadByte()
265 if !reflect.DeepEqual(err, test.Err) {
266 t.Errorf("test %d.%d: expecting error %s, got %s", n+1, i+1, test.Err, err)
267 } else if test.Err != nil {
268 continue Tests
269 } else if test.Data[i] != b {
270 t.Errorf("test %d.%d: expecting to read byte %d, got %d", n+1, i+1, test.Data[0], b)
271 }
272 }
273
274 if test.Err != nil {
275 continue
276 }
277
278 b, err := f.ReadByte()
279 if !errors.Is(err, io.EOF) {
280 t.Errorf("test %d.%d: expecting error %s, got %s", n+1, len(test.Data)+1, io.EOF, err)
281 } else if b != 0 {
282 t.Errorf("test %d.%d: expecting to read byte %d, got %d", n+1, len(test.Data)+1, 0, b)
283 }
284 }
285 }
286
287 func TestUnreadByteRW(t *testing.T) {
288 f := File{
289 mu: &sync.RWMutex{},
290 file: file{
291 inode: &inode{
292 data: []byte("12345"),
293 },
294 opMode: opRead,
295 },
296 }
297
298 f.ReadByte()
299
300 err := f.UnreadByte()
301 if !reflect.DeepEqual(err, &fs.PathError{
302 Op: "unreadbyte",
303 Path: "",
304 Err: fs.ErrInvalid,
305 }) {
306 t.Errorf("test 1: expecting ErrClosed, got %s", err)
307
308 return
309 }
310
311 f.opMode |= opSeek
312
313 c, _ := f.ReadByte()
314 if c != '2' {
315 t.Errorf("test 2: expecting to read '2', read %q", c)
316
317 return
318 }
319
320 err = f.UnreadByte()
321 if !errors.Is(err, nil) {
322 t.Errorf("test 3: expecting nil error, got %s", err)
323
324 return
325 }
326
327 c, _ = f.ReadByte()
328 if c != '2' {
329 t.Errorf("test 4: expecting to read '2', read %q", c)
330
331 return
332 }
333
334 err = f.UnreadByte()
335 if !errors.Is(err, nil) {
336 t.Errorf("test 5: expecting nil error, got %s", err)
337
338 return
339 }
340
341 err = f.UnreadByte()
342 if !reflect.DeepEqual(err, &fs.PathError{
343 Op: "unreadbyte",
344 Path: "",
345 Err: fs.ErrInvalid,
346 }) {
347 t.Errorf("test 6: expecting ErrInvalid error, got %s", err)
348
349 return
350 }
351
352 c, _ = f.ReadByte()
353 if c != '2' {
354 t.Errorf("test 7: expecting to read '2', read %q", c)
355
356 return
357 }
358
359 f.ReadByte()
360
361 err = f.UnreadByte()
362 if !errors.Is(err, nil) {
363 t.Errorf("test 8: expecting nil error, got %s", err)
364
365 return
366 }
367
368 c, _ = f.ReadByte()
369 if c != '3' {
370 t.Errorf("test 9: expecting to read '3', read %q", c)
371
372 return
373 }
374
375 f.Read([]byte{0})
376
377 err = f.UnreadByte()
378 if !reflect.DeepEqual(err, &fs.PathError{
379 Op: "unreadbyte",
380 Path: "",
381 Err: fs.ErrInvalid,
382 }) {
383 t.Errorf("test 10: expecting nil error, got %s", err)
384
385 return
386 }
387 }
388
389 func TestReadRuneRW(t *testing.T) {
390 f := File{
391 mu: &sync.RWMutex{},
392 file: file{
393 inode: &inode{
394 data: []byte("1ħᕗ🐶"),
395 },
396 },
397 }
398
399 _, _, err := f.ReadRune()
400 if !errors.Is(err, fs.ErrClosed) {
401 t.Errorf("test 1: expecting ErrClosed, got %s", err)
402
403 return
404 }
405
406 f.opMode = opRead
407
408 r, n, err := f.ReadRune()
409
410 if !errors.Is(err, nil) {
411 t.Errorf("test 2: expecting nil error, got %s", err)
412
413 return
414 } else if n != 1 {
415 t.Errorf("test 2: expecting to read 1 byte, read %d", n)
416
417 return
418 } else if r != '1' {
419 t.Errorf("test 2: expecting to read '1', read %q", r)
420
421 return
422 }
423
424 r, n, err = f.ReadRune()
425
426 if !errors.Is(err, nil) {
427 t.Errorf("test 3: expecting nil error, got %s", err)
428
429 return
430 } else if n != 2 {
431 t.Errorf("test 3: expecting to read 2 bytes, read %d", n)
432
433 return
434 } else if r != 'ħ' {
435 t.Errorf("test 3: expecting to read 'ħ', read %q", r)
436
437 return
438 }
439
440 r, n, err = f.ReadRune()
441
442 if !errors.Is(err, nil) {
443 t.Errorf("test 4: expecting nil error, got %s", err)
444
445 return
446 } else if n != 3 {
447 t.Errorf("test 4: expecting to read 3 bytes, read %d", n)
448
449 return
450 } else if r != 'ᕗ' {
451 t.Errorf("test 4: expecting to read 'ᕗ', read %q", r)
452
453 return
454 }
455
456 r, n, err = f.ReadRune()
457
458 if !errors.Is(err, nil) {
459 t.Errorf("test 5: expecting nil error, got %s", err)
460
461 return
462 } else if n != 4 {
463 t.Errorf("test 5: expecting to read 4 bytes, read %d", n)
464
465 return
466 } else if r != '🐶' {
467 t.Errorf("test 5: expecting to read '🐶', read %q", r)
468
469 return
470 }
471
472 r, n, err = f.ReadRune()
473 if !errors.Is(err, io.EOF) {
474 t.Errorf("test 6: expecting error EOF, got %s", err)
475
476 return
477 } else if n != 0 {
478 t.Errorf("test 6: expecting to read 0 bytes, read %d", n)
479
480 return
481 } else if r != 0 {
482 t.Errorf("test 6: expecting to read 0, read %q", r)
483
484 return
485 }
486 }
487
488 func TestUnreadRuneRW(t *testing.T) {
489 f := File{
490 mu: &sync.RWMutex{},
491 file: file{
492 inode: &inode{
493 data: []byte("1ħᕗ🐶"),
494 },
495 opMode: opRead,
496 },
497 }
498
499 f.ReadRune()
500
501 err := f.UnreadRune()
502 if !reflect.DeepEqual(err, &fs.PathError{
503 Op: "unreadrune",
504 Path: "",
505 Err: fs.ErrInvalid,
506 }) {
507 t.Errorf("test 1: expecting ErrClosed, got %s", err)
508
509 return
510 }
511
512 f.opMode |= opSeek
513 f.pos = 0
514
515 c, _, _ := f.ReadRune()
516 if c != '1' {
517 t.Errorf("test 2: expecting to read '1', read %q", c)
518
519 return
520 }
521
522 err = f.UnreadRune()
523 if !errors.Is(err, nil) {
524 t.Errorf("test 3: expecting nil error, got %s", err)
525
526 return
527 }
528
529 c, _, _ = f.ReadRune()
530 if c != '1' {
531 t.Errorf("test 4: expecting to read '1', read %q", c)
532
533 return
534 }
535
536 err = f.UnreadRune()
537 if !errors.Is(err, nil) {
538 t.Errorf("test 5: expecting nil error, got %s", err)
539
540 return
541 }
542
543 err = f.UnreadRune()
544 if !reflect.DeepEqual(err, &fs.PathError{
545 Op: "unreadrune",
546 Path: "",
547 Err: fs.ErrInvalid,
548 }) {
549 t.Errorf("test 6: expecting ErrInvalid error, got %s", err)
550
551 return
552 }
553
554 c, _, _ = f.ReadRune()
555 if c != '1' {
556 t.Errorf("test 7: expecting to read '1', read %q", c)
557
558 return
559 }
560
561 err = f.UnreadRune()
562 if !errors.Is(err, nil) {
563 t.Errorf("test 8: expecting nil error, got %s", err)
564
565 return
566 }
567
568 c, _, _ = f.ReadRune()
569 if c != '1' {
570 t.Errorf("test 9: expecting to read '1', read %q", c)
571
572 return
573 }
574
575 f.Read([]byte{0})
576
577 err = f.UnreadRune()
578 if !reflect.DeepEqual(err, &fs.PathError{
579 Op: "unreadrune",
580 Path: "",
581 Err: fs.ErrInvalid,
582 }) {
583 t.Errorf("test 10: expecting nil error, got %s", err)
584
585 return
586 }
587
588 f.pos = 1
589
590 f.ReadRune()
591
592 f.UnreadRune()
593
594 c, _, _ = f.ReadRune()
595 if c != 'ħ' {
596 t.Errorf("test 11: expecting to read 'ħ', read %q", c)
597
598 return
599 }
600
601 f.ReadRune()
602 f.ReadRune()
603 f.UnreadRune()
604
605 c, _, _ = f.ReadRune()
606 if c != '🐶' {
607 t.Errorf("test 12: expecting to read '🐶', read %q", c)
608
609 return
610 }
611
612 f.UnreadRune()
613
614 c, _, _ = f.ReadRune()
615 if c != '🐶' {
616 t.Errorf("test 12: expecting to read '🐶', read %q", c)
617
618 return
619 }
620 }
621
622 func TestWriteToRW(t *testing.T) {
623 f := File{
624 mu: &sync.RWMutex{},
625 file: file{
626 inode: &inode{
627 data: []byte("12345"),
628 },
629 },
630 }
631
632 var sb strings.Builder
633
634 _, err := f.WriteTo(&sb)
635 if !reflect.DeepEqual(err, &fs.PathError{
636 Op: "writeto",
637 Path: "",
638 Err: fs.ErrClosed,
639 }) {
640 t.Errorf("test 1: expecting to get error ErrClosed, got %s", err)
641 }
642
643 f.opMode = opRead
644
645 n, err := f.WriteTo(&sb)
646 if err != nil {
647 t.Errorf("test 2: expecting to get no error, got %s", err)
648 } else if n != 5 {
649 t.Errorf("test 2: expecting to read 5 bytes, read %d", n)
650 } else if str := sb.String(); str != "12345" {
651 t.Errorf("test 2: expecting to write %q, wrote %q", "12345", str)
652 }
653
654 _, err = f.WriteTo(&sb)
655 if !errors.Is(err, io.EOF) {
656 t.Errorf("test 3: expecting to get error EOF, got %s", err)
657 }
658
659 f.pos = 1
660
661 sb.Reset()
662
663 n, err = f.WriteTo(&sb)
664 if err != nil {
665 t.Errorf("test 4: expecting to get no error, got %s", err)
666 } else if n != 4 {
667 t.Errorf("test 4: expecting to read 5 bytes, read %d", n)
668 } else if str := sb.String(); str != "2345" {
669 t.Errorf("test 4: expecting to write %q, wrote %q", "2345", str)
670 }
671 }
672
673 func TestSeekRW(t *testing.T) {
674 f := File{
675 mu: &sync.RWMutex{},
676 file: file{
677 inode: &inode{
678 data: make([]byte, 100),
679 },
680 opMode: opSeek,
681 },
682 }
683 for n, test := range [...]struct {
684 Offset int64
685 Whence int
686 Pos int64
687 Err error
688 }{
689 {
690 Offset: 0,
691 Whence: io.SeekStart,
692 Pos: 0,
693 },
694 {
695 Offset: -1,
696 Whence: io.SeekStart,
697 Pos: 0,
698 Err: &fs.PathError{
699 Op: "seek",
700 Path: "",
701 Err: fs.ErrInvalid,
702 },
703 },
704 {
705 Offset: 10,
706 Whence: io.SeekStart,
707 Pos: 10,
708 },
709 {
710 Offset: 10,
711 Whence: io.SeekStart,
712 Pos: 10,
713 },
714 {
715 Offset: -1,
716 Whence: io.SeekStart,
717 Pos: 0,
718 Err: &fs.PathError{
719 Op: "seek",
720 Path: "",
721 Err: fs.ErrInvalid,
722 },
723 },
724 {
725 Offset: 10,
726 Whence: io.SeekStart,
727 Pos: 10,
728 },
729 {
730 Offset: 10,
731 Whence: io.SeekCurrent,
732 Pos: 20,
733 },
734 {
735 Offset: 10,
736 Whence: io.SeekCurrent,
737 Pos: 30,
738 },
739 {
740 Offset: -10,
741 Whence: io.SeekCurrent,
742 Pos: 20,
743 },
744 {
745 Offset: 0,
746 Whence: io.SeekCurrent,
747 Pos: 20,
748 },
749 {
750 Offset: 0,
751 Whence: io.SeekEnd,
752 Pos: 100,
753 },
754 {
755 Offset: 10,
756 Whence: io.SeekEnd,
757 Pos: 110,
758 },
759 {
760 Offset: -10,
761 Whence: io.SeekEnd,
762 Pos: 90,
763 },
764 } {
765 pos, err := f.Seek(test.Offset, test.Whence)
766 if !reflect.DeepEqual(err, test.Err) {
767 t.Errorf("test %d: expecting error %s, got %s", n+1, test.Err, err)
768 } else if pos != test.Pos {
769 t.Errorf("test %d: expecting pos %d, got %d", n+1, test.Pos, pos)
770 }
771 }
772 }
773
774 func TestWrite(t *testing.T) {
775 var toWrite [256]byte
776
777 for n := range toWrite {
778 toWrite[n] = byte(n)
779 }
780
781 f := File{
782 mu: &sync.RWMutex{},
783 file: file{
784 inode: &inode{
785 data: make([]byte, 100),
786 },
787 },
788 }
789
790 n, err := f.Write(toWrite[:10])
791 if !reflect.DeepEqual(err, &fs.PathError{
792 Op: "write",
793 Path: "",
794 Err: fs.ErrClosed,
795 }) {
796 t.Errorf("test 1: expecting ErrClosed, got %s", err)
797 } else if n != 0 {
798 t.Errorf("test 1: expecting to write 0 bytes, wrote %d", n)
799 }
800
801 for n := range toWrite {
802 if n == 0 {
803 continue
804 }
805
806 f := File{
807 mu: &sync.RWMutex{},
808 file: file{
809 inode: &inode{
810 data: make([]byte, 100),
811 },
812 opMode: opWrite,
813 },
814 }
815
816 for i := 0; i < 100; i++ {
817 m, err := f.Write(toWrite[:n])
818 if !errors.Is(err, nil) {
819 t.Errorf("test %d: expecting no error, got %s", n+1, err)
820 } else if m != n {
821 t.Errorf("test %d: expecting to write %d bytes, wrote %d", n+1, n, m)
822 }
823 }
824
825 expected := bytes.Repeat(toWrite[:n], 100)
826 if !bytes.Equal(f.data, expected) {
827 t.Errorf("test %d: expecting to write %v, wrote %v", n+1, expected, f.data)
828 }
829 }
830 }
831
832 func TestWriteAt(t *testing.T) {
833 f := File{
834 mu: &sync.RWMutex{},
835 file: file{
836 inode: &inode{
837 data: make([]byte, 10),
838 },
839 },
840 }
841
842 n, err := f.WriteAt([]byte{0}, 0)
843 if !reflect.DeepEqual(err, &fs.PathError{
844 Op: "writeat",
845 Path: "",
846 Err: fs.ErrClosed,
847 }) {
848 t.Errorf("test 1: expecting ErrClosed, got %s", err)
849 } else if n != 0 {
850 t.Errorf("test 1: expecting to write 0 bytes, wrote %d", n)
851 }
852
853 f.opMode = opWrite | opSeek
854
855 for n, test := range [...]struct {
856 ToWrite []byte
857 Pos int64
858 N int
859 Err error
860 Buffer []byte
861 }{
862 {
863 ToWrite: []byte("Beep"),
864 Pos: 2,
865 N: 4,
866 Err: nil,
867 Buffer: []byte("\000\000Beep\000\000\000\000"),
868 },
869 {
870 ToWrite: []byte("Boop"),
871 Pos: 2,
872 N: 4,
873 Err: nil,
874 Buffer: []byte("\000\000Boop\000\000\000\000"),
875 },
876 {
877 ToWrite: []byte("FooBar"),
878 Pos: 12,
879 N: 6,
880 Err: nil,
881 Buffer: []byte("\000\000Boop\000\000\000\000\000\000FooBar"),
882 },
883 {
884 ToWrite: []byte("Hello"),
885 Pos: 0,
886 N: 5,
887 Err: nil,
888 Buffer: []byte("Hellop\000\000\000\000\000\000FooBar"),
889 },
890 } {
891 m, err := f.WriteAt(test.ToWrite, test.Pos)
892 if !reflect.DeepEqual(test.Err, err) {
893 t.Errorf("test %d: expecting error %s, got %s", n+1, test.Err, err)
894 } else if m != test.N {
895 t.Errorf("test %d: expecting to write %d bytes, wrote %d", n+1, test.N, m)
896 } else if !bytes.Equal(f.data, test.Buffer) {
897 t.Errorf("test %d: expecting buffer to be %v bytes, got %v", n+1, test.Buffer, f.data)
898 }
899 }
900 }
901
902 func TestWriteString(t *testing.T) {
903 var toWrite [256]byte
904
905 for n := range toWrite {
906 toWrite[n] = byte(n)
907 }
908
909 f := File{
910 mu: &sync.RWMutex{},
911 file: file{
912 inode: &inode{
913 data: make([]byte, 100),
914 },
915 },
916 }
917
918 n, err := f.WriteString(string(toWrite[:10]))
919 if !reflect.DeepEqual(err, &fs.PathError{
920 Op: "writestring",
921 Path: "",
922 Err: fs.ErrClosed,
923 }) {
924 t.Errorf("test 1: expecting ErrClosed, got %s", err)
925 } else if n != 0 {
926 t.Errorf("test 1: expecting to write 0 bytes, wrote %d", n)
927 }
928
929 for n := range toWrite {
930 if n == 0 {
931 continue
932 }
933
934 f := File{
935 mu: &sync.RWMutex{},
936 file: file{
937 inode: &inode{
938 data: make([]byte, 100),
939 },
940 opMode: opWrite,
941 },
942 }
943
944 for i := 0; i < 100; i++ {
945 m, err := f.WriteString(string(toWrite[:n]))
946 if !errors.Is(err, nil) {
947 t.Errorf("test %d: expecting no error, got %s", n+1, err)
948 } else if m != n {
949 t.Errorf("test %d: expecting to write %d bytes, wrote %d", n+1, n, m)
950 }
951 }
952
953 expected := bytes.Repeat(toWrite[:n], 100)
954 if !bytes.Equal(f.data, expected) {
955 t.Errorf("test %d: expecting to write %v, wrote %v", n+1, expected, f.data)
956 }
957 }
958 }
959
960 func TestWriteByte(t *testing.T) {
961 Tests:
962 for n, test := range [...]struct {
963 Data []byte
964 Mode opMode
965 Err error
966 }{
967 {
968 Err: &fs.PathError{
969 Op: "writebyte",
970 Path: "",
971 Err: fs.ErrInvalid,
972 },
973 },
974 {
975 Data: []byte{'a'},
976 Err: &fs.PathError{
977 Op: "writebyte",
978 Path: "",
979 Err: fs.ErrClosed,
980 },
981 },
982 {
983 Data: []byte("abc"),
984 Mode: opWrite,
985 },
986 } {
987 f := File{
988 mu: &sync.RWMutex{},
989 file: file{
990 inode: &inode{
991 data: test.Data,
992 },
993 opMode: test.Mode,
994 },
995 }
996
997 for i := range test.Data {
998 err := f.WriteByte(test.Data[i])
999 if !reflect.DeepEqual(err, test.Err) {
1000 t.Errorf("test %d.%d: expecting error %s, got %s", n+1, i+1, test.Err, err)
1001 } else if test.Err != nil {
1002 continue Tests
1003 }
1004 }
1005
1006 if test.Err != nil {
1007 continue
1008 }
1009
1010 if !bytes.Equal(test.Data, f.data) {
1011 t.Errorf("test %d: expecting to write %s, wrote %s", n+1, test.Data, f.data)
1012 }
1013 }
1014 }
1015
1016 func TestCloseRW(t *testing.T) {
1017 f := File{
1018 mu: &sync.RWMutex{},
1019 file: file{
1020 inode: &inode{},
1021 opMode: opWrite,
1022 },
1023 }
1024
1025 _, err := f.WriteString("123")
1026 if err != nil {
1027 t.Errorf("test 1: expecting nil error, got %s", err)
1028 }
1029
1030 err = f.Close()
1031 if err != nil {
1032 t.Errorf("test 2: expecting nil error, got %s", err)
1033 }
1034
1035 _, err = f.WriteString("1")
1036 if !reflect.DeepEqual(err, &fs.PathError{
1037 Op: "writestring",
1038 Path: "",
1039 Err: fs.ErrClosed,
1040 }) {
1041 t.Errorf("test 3: expecting ErrClosed error, got %s", err)
1042 }
1043
1044 f.opMode = opRead
1045
1046 var buf [1]byte
1047
1048 _, err = f.Read(buf[:])
1049 if err != nil {
1050 t.Errorf("test 4: expecting nil error, got %s", err)
1051 } else if buf[0] != '1' {
1052 t.Errorf("test 4: expecting to read '1', read %s", buf[:1])
1053 }
1054
1055 err = f.Close()
1056 if err != nil {
1057 t.Errorf("test 5: expecting nil error, got %s", err)
1058 }
1059
1060 _, err = f.Read(buf[:])
1061 if !reflect.DeepEqual(err, &fs.PathError{
1062 Op: "read",
1063 Path: "",
1064 Err: fs.ErrClosed,
1065 }) {
1066 t.Errorf("test 6: expecting ErrClosed error, got %s", err)
1067 }
1068
1069 f.opMode = opSeek
1070
1071 pos, err := f.Seek(1, io.SeekStart)
1072 if err != nil {
1073 t.Errorf("test 7: expecting nil error, got %s", err)
1074 } else if pos != 1 {
1075 t.Errorf("test 7: expecting to be at position 1, at %d", pos)
1076 }
1077
1078 err = f.Close()
1079 if err != nil {
1080 t.Errorf("test 8: expecting nil error, got %s", err)
1081 }
1082
1083 pos, err = f.Seek(1, io.SeekStart)
1084 if !reflect.DeepEqual(err, &fs.PathError{
1085 Op: "seek",
1086 Path: "",
1087 Err: fs.ErrClosed,
1088 }) {
1089 t.Errorf("test 9: expecting ErrClosed error, got %s", err)
1090 }
1091 }
1092
1093 func TestReadFrom(t *testing.T) {
1094 buf := make([]byte, 0, 255*1024*1024)
1095
1096 for i := 0; i < 1024*1024; i++ {
1097 for j := 0; j < 255; j++ {
1098 buf = append(buf, byte(j))
1099 }
1100 }
1101
1102 f := File{
1103 mu: &sync.RWMutex{},
1104 file: file{
1105 inode: &inode{},
1106 opMode: opWrite,
1107 },
1108 }
1109
1110 n, err := f.ReadFrom(bytes.NewBuffer(buf))
1111
1112 if err != nil {
1113 t.Errorf("unexpected error: %v", err)
1114 } else if n != 255*1024*1024 {
1115 t.Errorf("expected to read %d bytes, read %d", 255*1024*1024, n)
1116 } else if !bytes.Equal(buf, f.data) {
1117 t.Errorf("File data does not match buf data")
1118 }
1119 }
1120