github.com/pgavlin/text@v0.0.0-20240419000839-8438d0a47805/reader_test.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package text_test 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "strings" 12 "sync" 13 "testing" 14 ) 15 16 func TestReader(t *testing.T) { 17 r := strings.NewReader("0123456789") 18 tests := []struct { 19 off int64 20 seek int 21 n int 22 want string 23 wantpos int64 24 readerr error 25 seekerr string 26 }{ 27 {seek: io.SeekStart, off: 0, n: 20, want: "0123456789"}, 28 {seek: io.SeekStart, off: 1, n: 1, want: "1"}, 29 {seek: io.SeekCurrent, off: 1, wantpos: 3, n: 2, want: "34"}, 30 {seek: io.SeekStart, off: -1, seekerr: "strings.Reader.Seek: negative position"}, 31 {seek: io.SeekStart, off: 1 << 33, wantpos: 1 << 33, readerr: io.EOF}, 32 {seek: io.SeekCurrent, off: 1, wantpos: 1<<33 + 1, readerr: io.EOF}, 33 {seek: io.SeekStart, n: 5, want: "01234"}, 34 {seek: io.SeekCurrent, n: 5, want: "56789"}, 35 {seek: io.SeekEnd, off: -1, n: 1, wantpos: 9, want: "9"}, 36 } 37 38 for i, tt := range tests { 39 pos, err := r.Seek(tt.off, tt.seek) 40 if err == nil && tt.seekerr != "" { 41 t.Errorf("%d. want seek error %q", i, tt.seekerr) 42 continue 43 } 44 if err != nil && err.Error() != tt.seekerr { 45 t.Errorf("%d. seek error = %q; want %q", i, err.Error(), tt.seekerr) 46 continue 47 } 48 if tt.wantpos != 0 && tt.wantpos != pos { 49 t.Errorf("%d. pos = %d, want %d", i, pos, tt.wantpos) 50 } 51 buf := make([]byte, tt.n) 52 n, err := r.Read(buf) 53 if err != tt.readerr { 54 t.Errorf("%d. read = %v; want %v", i, err, tt.readerr) 55 continue 56 } 57 got := string(buf[:n]) 58 if got != tt.want { 59 t.Errorf("%d. got %q; want %q", i, got, tt.want) 60 } 61 } 62 } 63 64 func TestReadAfterBigSeek(t *testing.T) { 65 r := strings.NewReader("0123456789") 66 if _, err := r.Seek(1<<31+5, io.SeekStart); err != nil { 67 t.Fatal(err) 68 } 69 if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF { 70 t.Errorf("Read = %d, %v; want 0, EOF", n, err) 71 } 72 } 73 74 func TestReaderAt(t *testing.T) { 75 r := strings.NewReader("0123456789") 76 tests := []struct { 77 off int64 78 n int 79 want string 80 wanterr any 81 }{ 82 {0, 10, "0123456789", nil}, 83 {1, 10, "123456789", io.EOF}, 84 {1, 9, "123456789", nil}, 85 {11, 10, "", io.EOF}, 86 {0, 0, "", nil}, 87 {-1, 0, "", "strings.Reader.ReadAt: negative offset"}, 88 } 89 for i, tt := range tests { 90 b := make([]byte, tt.n) 91 rn, err := r.ReadAt(b, tt.off) 92 got := string(b[:rn]) 93 if got != tt.want { 94 t.Errorf("%d. got %q; want %q", i, got, tt.want) 95 } 96 if fmt.Sprintf("%v", err) != fmt.Sprintf("%v", tt.wanterr) { 97 t.Errorf("%d. got error = %v; want %v", i, err, tt.wanterr) 98 } 99 } 100 } 101 102 func TestReaderAtConcurrent(t *testing.T) { 103 // Test for the race detector, to verify ReadAt doesn't mutate 104 // any state. 105 r := strings.NewReader("0123456789") 106 var wg sync.WaitGroup 107 for i := 0; i < 5; i++ { 108 wg.Add(1) 109 go func(i int) { 110 defer wg.Done() 111 var buf [1]byte 112 r.ReadAt(buf[:], int64(i)) 113 }(i) 114 } 115 wg.Wait() 116 } 117 118 func TestEmptyReaderConcurrent(t *testing.T) { 119 // Test for the race detector, to verify a Read that doesn't yield any bytes 120 // is okay to use from multiple goroutines. This was our historic behavior. 121 // See golang.org/issue/7856 122 r := strings.NewReader("") 123 var wg sync.WaitGroup 124 for i := 0; i < 5; i++ { 125 wg.Add(2) 126 go func() { 127 defer wg.Done() 128 var buf [1]byte 129 r.Read(buf[:]) 130 }() 131 go func() { 132 defer wg.Done() 133 r.Read(nil) 134 }() 135 } 136 wg.Wait() 137 } 138 139 func TestWriteTo(t *testing.T) { 140 const str = "0123456789" 141 for i := 0; i <= len(str); i++ { 142 s := str[i:] 143 r := strings.NewReader(s) 144 var b bytes.Buffer 145 n, err := r.WriteTo(&b) 146 if expect := int64(len(s)); n != expect { 147 t.Errorf("got %v; want %v", n, expect) 148 } 149 if err != nil { 150 t.Errorf("for length %d: got error = %v; want nil", len(s), err) 151 } 152 if b.String() != s { 153 t.Errorf("got string %q; want %q", b.String(), s) 154 } 155 if r.Len() != 0 { 156 t.Errorf("reader contains %v bytes; want 0", r.Len()) 157 } 158 } 159 } 160 161 // tests that Len is affected by reads, but Size is not. 162 func TestReaderLenSize(t *testing.T) { 163 r := strings.NewReader("abc") 164 io.CopyN(io.Discard, r, 1) 165 if r.Len() != 2 { 166 t.Errorf("Len = %d; want 2", r.Len()) 167 } 168 if r.Size() != 3 { 169 t.Errorf("Size = %d; want 3", r.Size()) 170 } 171 } 172 173 func TestReaderReset(t *testing.T) { 174 r := strings.NewReader("世界") 175 if _, _, err := r.ReadRune(); err != nil { 176 t.Errorf("ReadRune: unexpected error: %v", err) 177 } 178 179 const want = "abcdef" 180 r.Reset(want) 181 if err := r.UnreadRune(); err == nil { 182 t.Errorf("UnreadRune: expected error, got nil") 183 } 184 buf, err := io.ReadAll(r) 185 if err != nil { 186 t.Errorf("ReadAll: unexpected error: %v", err) 187 } 188 if got := string(buf); got != want { 189 t.Errorf("ReadAll: got %q, want %q", got, want) 190 } 191 } 192 193 func TestReaderZero(t *testing.T) { 194 if l := (&strings.Reader{}).Len(); l != 0 { 195 t.Errorf("Len: got %d, want 0", l) 196 } 197 198 if n, err := (&strings.Reader{}).Read(nil); n != 0 || err != io.EOF { 199 t.Errorf("Read: got %d, %v; want 0, io.EOF", n, err) 200 } 201 202 if n, err := (&strings.Reader{}).ReadAt(nil, 11); n != 0 || err != io.EOF { 203 t.Errorf("ReadAt: got %d, %v; want 0, io.EOF", n, err) 204 } 205 206 if b, err := (&strings.Reader{}).ReadByte(); b != 0 || err != io.EOF { 207 t.Errorf("ReadByte: got %d, %v; want 0, io.EOF", b, err) 208 } 209 210 if ch, size, err := (&strings.Reader{}).ReadRune(); ch != 0 || size != 0 || err != io.EOF { 211 t.Errorf("ReadRune: got %d, %d, %v; want 0, 0, io.EOF", ch, size, err) 212 } 213 214 if offset, err := (&strings.Reader{}).Seek(11, io.SeekStart); offset != 11 || err != nil { 215 t.Errorf("Seek: got %d, %v; want 11, nil", offset, err) 216 } 217 218 if s := (&strings.Reader{}).Size(); s != 0 { 219 t.Errorf("Size: got %d, want 0", s) 220 } 221 222 if (&strings.Reader{}).UnreadByte() == nil { 223 t.Errorf("UnreadByte: got nil, want error") 224 } 225 226 if (&strings.Reader{}).UnreadRune() == nil { 227 t.Errorf("UnreadRune: got nil, want error") 228 } 229 230 if n, err := (&strings.Reader{}).WriteTo(io.Discard); n != 0 || err != nil { 231 t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err) 232 } 233 }