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 5package bytes_test 6 7import ( 8 . "bytes" 9 "fmt" 10 "io" 11 "sync" 12 "testing" 13) 14 15func TestReader(t *testing.T) { 16 r := NewReader([]byte("0123456789")) 17 tests := []struct { 18 off int64 19 seek int 20 n int 21 want string 22 wantpos int64 23 readerr error 24 seekerr string 25 }{ 26 {seek: io.SeekStart, off: 0, n: 20, want: "0123456789"}, 27 {seek: io.SeekStart, off: 1, n: 1, want: "1"}, 28 {seek: io.SeekCurrent, off: 1, wantpos: 3, n: 2, want: "34"}, 29 {seek: io.SeekStart, off: -1, seekerr: "bytes.Reader.Seek: negative position"}, 30 {seek: io.SeekStart, off: 1 << 33, wantpos: 1 << 33, readerr: io.EOF}, 31 {seek: io.SeekCurrent, off: 1, wantpos: 1<<33 + 1, readerr: io.EOF}, 32 {seek: io.SeekStart, n: 5, want: "01234"}, 33 {seek: io.SeekCurrent, n: 5, want: "56789"}, 34 {seek: io.SeekEnd, off: -1, n: 1, wantpos: 9, want: "9"}, 35 } 36 37 for i, tt := range tests { 38 pos, err := r.Seek(tt.off, tt.seek) 39 if err == nil && tt.seekerr != "" { 40 t.Errorf("%d. want seek error %q", i, tt.seekerr) 41 continue 42 } 43 if err != nil && err.Error() != tt.seekerr { 44 t.Errorf("%d. seek error = %q; want %q", i, err.Error(), tt.seekerr) 45 continue 46 } 47 if tt.wantpos != 0 && tt.wantpos != pos { 48 t.Errorf("%d. pos = %d, want %d", i, pos, tt.wantpos) 49 } 50 buf := make([]byte, tt.n) 51 n, err := r.Read(buf) 52 if err != tt.readerr { 53 t.Errorf("%d. read = %v; want %v", i, err, tt.readerr) 54 continue 55 } 56 got := string(buf[:n]) 57 if got != tt.want { 58 t.Errorf("%d. got %q; want %q", i, got, tt.want) 59 } 60 } 61} 62 63func TestReadAfterBigSeek(t *testing.T) { 64 r := NewReader([]byte("0123456789")) 65 if _, err := r.Seek(1<<31+5, io.SeekStart); err != nil { 66 t.Fatal(err) 67 } 68 if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF { 69 t.Errorf("Read = %d, %v; want 0, EOF", n, err) 70 } 71} 72 73func TestReaderAt(t *testing.T) { 74 r := NewReader([]byte("0123456789")) 75 tests := []struct { 76 off int64 77 n int 78 want string 79 wanterr interface{} 80 }{ 81 {0, 10, "0123456789", nil}, 82 {1, 10, "123456789", io.EOF}, 83 {1, 9, "123456789", nil}, 84 {11, 10, "", io.EOF}, 85 {0, 0, "", nil}, 86 {-1, 0, "", "bytes.Reader.ReadAt: negative offset"}, 87 } 88 for i, tt := range tests { 89 b := make([]byte, tt.n) 90 rn, err := r.ReadAt(b, tt.off) 91 got := string(b[:rn]) 92 if got != tt.want { 93 t.Errorf("%d. got %q; want %q", i, got, tt.want) 94 } 95 if fmt.Sprintf("%v", err) != fmt.Sprintf("%v", tt.wanterr) { 96 t.Errorf("%d. got error = %v; want %v", i, err, tt.wanterr) 97 } 98 } 99} 100 101func TestReaderAtConcurrent(t *testing.T) { 102 // Test for the race detector, to verify ReadAt doesn't mutate 103 // any state. 104 r := NewReader([]byte("0123456789")) 105 var wg sync.WaitGroup 106 for i := 0; i < 5; i++ { 107 wg.Add(1) 108 go func(i int) { 109 defer wg.Done() 110 var buf [1]byte 111 r.ReadAt(buf[:], int64(i)) 112 }(i) 113 } 114 wg.Wait() 115} 116 117func TestEmptyReaderConcurrent(t *testing.T) { 118 // Test for the race detector, to verify a Read that doesn't yield any bytes 119 // is okay to use from multiple goroutines. This was our historic behavior. 120 // See golang.org/issue/7856 121 r := NewReader([]byte{}) 122 var wg sync.WaitGroup 123 for i := 0; i < 5; i++ { 124 wg.Add(2) 125 go func() { 126 defer wg.Done() 127 var buf [1]byte 128 r.Read(buf[:]) 129 }() 130 go func() { 131 defer wg.Done() 132 r.Read(nil) 133 }() 134 } 135 wg.Wait() 136} 137 138func TestReaderWriteTo(t *testing.T) { 139 for i := 0; i < 30; i += 3 { 140 var l int 141 if i > 0 { 142 l = len(testString) / i 143 } 144 s := testString[:l] 145 r := NewReader(testBytes[:l]) 146 var b Buffer 147 n, err := r.WriteTo(&b) 148 if expect := int64(len(s)); n != expect { 149 t.Errorf("got %v; want %v", n, expect) 150 } 151 if err != nil { 152 t.Errorf("for length %d: got error = %v; want nil", l, err) 153 } 154 if b.String() != s { 155 t.Errorf("got string %q; want %q", b.String(), s) 156 } 157 if r.Len() != 0 { 158 t.Errorf("reader contains %v bytes; want 0", r.Len()) 159 } 160 } 161} 162 163func TestReaderLen(t *testing.T) { 164 const data = "hello world" 165 r := NewReader([]byte(data)) 166 if got, want := r.Len(), 11; got != want { 167 t.Errorf("r.Len(): got %d, want %d", got, want) 168 } 169 if n, err := r.Read(make([]byte, 10)); err != nil || n != 10 { 170 t.Errorf("Read failed: read %d %v", n, err) 171 } 172 if got, want := r.Len(), 1; got != want { 173 t.Errorf("r.Len(): got %d, want %d", got, want) 174 } 175 if n, err := r.Read(make([]byte, 1)); err != nil || n != 1 { 176 t.Errorf("Read failed: read %d %v; want 1, nil", n, err) 177 } 178 if got, want := r.Len(), 0; got != want { 179 t.Errorf("r.Len(): got %d, want %d", got, want) 180 } 181} 182 183var UnreadRuneErrorTests = []struct { 184 name string 185 f func(*Reader) 186}{ 187 {"Read", func(r *Reader) { r.Read([]byte{0}) }}, 188 {"ReadByte", func(r *Reader) { r.ReadByte() }}, 189 {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, 190 {"Seek", func(r *Reader) { r.Seek(0, io.SeekCurrent) }}, 191 {"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }}, 192} 193 194func TestUnreadRuneError(t *testing.T) { 195 for _, tt := range UnreadRuneErrorTests { 196 reader := NewReader([]byte("0123456789")) 197 if _, _, err := reader.ReadRune(); err != nil { 198 // should not happen 199 t.Fatal(err) 200 } 201 tt.f(reader) 202 err := reader.UnreadRune() 203 if err == nil { 204 t.Errorf("Unreading after %s: expected error", tt.name) 205 } 206 } 207} 208 209func TestReaderDoubleUnreadRune(t *testing.T) { 210 buf := NewBuffer([]byte("groucho")) 211 if _, _, err := buf.ReadRune(); err != nil { 212 // should not happen 213 t.Fatal(err) 214 } 215 if err := buf.UnreadByte(); err != nil { 216 // should not happen 217 t.Fatal(err) 218 } 219 if err := buf.UnreadByte(); err == nil { 220 t.Fatal("UnreadByte: expected error, got nil") 221 } 222} 223 224// verify that copying from an empty reader always has the same results, 225// regardless of the presence of a WriteTo method. 226func TestReaderCopyNothing(t *testing.T) { 227 type nErr struct { 228 n int64 229 err error 230 } 231 type justReader struct { 232 io.Reader 233 } 234 type justWriter struct { 235 io.Writer 236 } 237 discard := justWriter{io.Discard} // hide ReadFrom 238 239 var with, withOut nErr 240 with.n, with.err = io.Copy(discard, NewReader(nil)) 241 withOut.n, withOut.err = io.Copy(discard, justReader{NewReader(nil)}) 242 if with != withOut { 243 t.Errorf("behavior differs: with = %#v; without: %#v", with, withOut) 244 } 245} 246 247// tests that Len is affected by reads, but Size is not. 248func TestReaderLenSize(t *testing.T) { 249 r := NewReader([]byte("abc")) 250 io.CopyN(io.Discard, r, 1) 251 if r.Len() != 2 { 252 t.Errorf("Len = %d; want 2", r.Len()) 253 } 254 if r.Size() != 3 { 255 t.Errorf("Size = %d; want 3", r.Size()) 256 } 257} 258 259func TestReaderReset(t *testing.T) { 260 r := NewReader([]byte("世界")) 261 if _, _, err := r.ReadRune(); err != nil { 262 t.Errorf("ReadRune: unexpected error: %v", err) 263 } 264 265 const want = "abcdef" 266 r.Reset([]byte(want)) 267 if err := r.UnreadRune(); err == nil { 268 t.Errorf("UnreadRune: expected error, got nil") 269 } 270 buf, err := io.ReadAll(r) 271 if err != nil { 272 t.Errorf("ReadAll: unexpected error: %v", err) 273 } 274 if got := string(buf); got != want { 275 t.Errorf("ReadAll: got %q, want %q", got, want) 276 } 277} 278 279func TestReaderZero(t *testing.T) { 280 if l := (&Reader{}).Len(); l != 0 { 281 t.Errorf("Len: got %d, want 0", l) 282 } 283 284 if n, err := (&Reader{}).Read(nil); n != 0 || err != io.EOF { 285 t.Errorf("Read: got %d, %v; want 0, io.EOF", n, err) 286 } 287 288 if n, err := (&Reader{}).ReadAt(nil, 11); n != 0 || err != io.EOF { 289 t.Errorf("ReadAt: got %d, %v; want 0, io.EOF", n, err) 290 } 291 292 if b, err := (&Reader{}).ReadByte(); b != 0 || err != io.EOF { 293 t.Errorf("ReadByte: got %d, %v; want 0, io.EOF", b, err) 294 } 295 296 if ch, size, err := (&Reader{}).ReadRune(); ch != 0 || size != 0 || err != io.EOF { 297 t.Errorf("ReadRune: got %d, %d, %v; want 0, 0, io.EOF", ch, size, err) 298 } 299 300 if offset, err := (&Reader{}).Seek(11, io.SeekStart); offset != 11 || err != nil { 301 t.Errorf("Seek: got %d, %v; want 11, nil", offset, err) 302 } 303 304 if s := (&Reader{}).Size(); s != 0 { 305 t.Errorf("Size: got %d, want 0", s) 306 } 307 308 if (&Reader{}).UnreadByte() == nil { 309 t.Errorf("UnreadByte: got nil, want error") 310 } 311 312 if (&Reader{}).UnreadRune() == nil { 313 t.Errorf("UnreadRune: got nil, want error") 314 } 315 316 if n, err := (&Reader{}).WriteTo(io.Discard); n != 0 || err != nil { 317 t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err) 318 } 319} 320