1// Copyright 2009 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 "io" 10 "math/rand" 11 "runtime" 12 "testing" 13 "unicode/utf8" 14) 15 16const N = 10000 // make this bigger for a larger (and slower) test 17var testString string // test data for write tests 18var testBytes []byte // test data; same as testString but as a slice. 19 20type negativeReader struct{} 21 22func (r *negativeReader) Read([]byte) (int, error) { return -1, nil } 23 24func init() { 25 testBytes = make([]byte, N) 26 for i := 0; i < N; i++ { 27 testBytes[i] = 'a' + byte(i%26) 28 } 29 testString = string(testBytes) 30} 31 32// Verify that contents of buf match the string s. 33func check(t *testing.T, testname string, buf *Buffer, s string) { 34 bytes := buf.Bytes() 35 str := buf.String() 36 if buf.Len() != len(bytes) { 37 t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d", testname, buf.Len(), len(bytes)) 38 } 39 40 if buf.Len() != len(str) { 41 t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d", testname, buf.Len(), len(str)) 42 } 43 44 if buf.Len() != len(s) { 45 t.Errorf("%s: buf.Len() == %d, len(s) == %d", testname, buf.Len(), len(s)) 46 } 47 48 if string(bytes) != s { 49 t.Errorf("%s: string(buf.Bytes()) == %q, s == %q", testname, string(bytes), s) 50 } 51} 52 53// Fill buf through n writes of string fus. 54// The initial contents of buf corresponds to the string s; 55// the result is the final contents of buf returned as a string. 56func fillString(t *testing.T, testname string, buf *Buffer, s string, n int, fus string) string { 57 check(t, testname+" (fill 1)", buf, s) 58 for ; n > 0; n-- { 59 m, err := buf.WriteString(fus) 60 if m != len(fus) { 61 t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fus)) 62 } 63 if err != nil { 64 t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) 65 } 66 s += fus 67 check(t, testname+" (fill 4)", buf, s) 68 } 69 return s 70} 71 72// Fill buf through n writes of byte slice fub. 73// The initial contents of buf corresponds to the string s; 74// the result is the final contents of buf returned as a string. 75func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub []byte) string { 76 check(t, testname+" (fill 1)", buf, s) 77 for ; n > 0; n-- { 78 m, err := buf.Write(fub) 79 if m != len(fub) { 80 t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fub)) 81 } 82 if err != nil { 83 t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) 84 } 85 s += string(fub) 86 check(t, testname+" (fill 4)", buf, s) 87 } 88 return s 89} 90 91func TestNewBuffer(t *testing.T) { 92 buf := NewBuffer(testBytes) 93 check(t, "NewBuffer", buf, testString) 94} 95 96func TestNewBufferString(t *testing.T) { 97 buf := NewBufferString(testString) 98 check(t, "NewBufferString", buf, testString) 99} 100 101// Empty buf through repeated reads into fub. 102// The initial contents of buf corresponds to the string s. 103func empty(t *testing.T, testname string, buf *Buffer, s string, fub []byte) { 104 check(t, testname+" (empty 1)", buf, s) 105 106 for { 107 n, err := buf.Read(fub) 108 if n == 0 { 109 break 110 } 111 if err != nil { 112 t.Errorf(testname+" (empty 2): err should always be nil, found err == %s", err) 113 } 114 s = s[n:] 115 check(t, testname+" (empty 3)", buf, s) 116 } 117 118 check(t, testname+" (empty 4)", buf, "") 119} 120 121func TestBasicOperations(t *testing.T) { 122 var buf Buffer 123 124 for i := 0; i < 5; i++ { 125 check(t, "TestBasicOperations (1)", &buf, "") 126 127 buf.Reset() 128 check(t, "TestBasicOperations (2)", &buf, "") 129 130 buf.Truncate(0) 131 check(t, "TestBasicOperations (3)", &buf, "") 132 133 n, err := buf.Write(testBytes[0:1]) 134 if want := 1; err != nil || n != want { 135 t.Errorf("Write: got (%d, %v), want (%d, %v)", n, err, want, nil) 136 } 137 check(t, "TestBasicOperations (4)", &buf, "a") 138 139 buf.WriteByte(testString[1]) 140 check(t, "TestBasicOperations (5)", &buf, "ab") 141 142 n, err = buf.Write(testBytes[2:26]) 143 if want := 24; err != nil || n != want { 144 t.Errorf("Write: got (%d, %v), want (%d, %v)", n, err, want, nil) 145 } 146 check(t, "TestBasicOperations (6)", &buf, testString[0:26]) 147 148 buf.Truncate(26) 149 check(t, "TestBasicOperations (7)", &buf, testString[0:26]) 150 151 buf.Truncate(20) 152 check(t, "TestBasicOperations (8)", &buf, testString[0:20]) 153 154 empty(t, "TestBasicOperations (9)", &buf, testString[0:20], make([]byte, 5)) 155 empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100)) 156 157 buf.WriteByte(testString[1]) 158 c, err := buf.ReadByte() 159 if want := testString[1]; err != nil || c != want { 160 t.Errorf("ReadByte: got (%q, %v), want (%q, %v)", c, err, want, nil) 161 } 162 c, err = buf.ReadByte() 163 if err != io.EOF { 164 t.Errorf("ReadByte: got (%q, %v), want (%q, %v)", c, err, byte(0), io.EOF) 165 } 166 } 167} 168 169func TestLargeStringWrites(t *testing.T) { 170 var buf Buffer 171 limit := 30 172 if testing.Short() { 173 limit = 9 174 } 175 for i := 3; i < limit; i += 3 { 176 s := fillString(t, "TestLargeWrites (1)", &buf, "", 5, testString) 177 empty(t, "TestLargeStringWrites (2)", &buf, s, make([]byte, len(testString)/i)) 178 } 179 check(t, "TestLargeStringWrites (3)", &buf, "") 180} 181 182func TestLargeByteWrites(t *testing.T) { 183 var buf Buffer 184 limit := 30 185 if testing.Short() { 186 limit = 9 187 } 188 for i := 3; i < limit; i += 3 { 189 s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes) 190 empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(testString)/i)) 191 } 192 check(t, "TestLargeByteWrites (3)", &buf, "") 193} 194 195func TestLargeStringReads(t *testing.T) { 196 var buf Buffer 197 for i := 3; i < 30; i += 3 { 198 s := fillString(t, "TestLargeReads (1)", &buf, "", 5, testString[0:len(testString)/i]) 199 empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(testString))) 200 } 201 check(t, "TestLargeStringReads (3)", &buf, "") 202} 203 204func TestLargeByteReads(t *testing.T) { 205 var buf Buffer 206 for i := 3; i < 30; i += 3 { 207 s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) 208 empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(testString))) 209 } 210 check(t, "TestLargeByteReads (3)", &buf, "") 211} 212 213func TestMixedReadsAndWrites(t *testing.T) { 214 var buf Buffer 215 s := "" 216 for i := 0; i < 50; i++ { 217 wlen := rand.Intn(len(testString)) 218 if i%2 == 0 { 219 s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testString[0:wlen]) 220 } else { 221 s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen]) 222 } 223 224 rlen := rand.Intn(len(testString)) 225 fub := make([]byte, rlen) 226 n, _ := buf.Read(fub) 227 s = s[n:] 228 } 229 empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len())) 230} 231 232func TestCapWithPreallocatedSlice(t *testing.T) { 233 buf := NewBuffer(make([]byte, 10)) 234 n := buf.Cap() 235 if n != 10 { 236 t.Errorf("expected 10, got %d", n) 237 } 238} 239 240func TestCapWithSliceAndWrittenData(t *testing.T) { 241 buf := NewBuffer(make([]byte, 0, 10)) 242 buf.Write([]byte("test")) 243 n := buf.Cap() 244 if n != 10 { 245 t.Errorf("expected 10, got %d", n) 246 } 247} 248 249func TestNil(t *testing.T) { 250 var b *Buffer 251 if b.String() != "<nil>" { 252 t.Errorf("expected <nil>; got %q", b.String()) 253 } 254} 255 256func TestReadFrom(t *testing.T) { 257 var buf Buffer 258 for i := 3; i < 30; i += 3 { 259 s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) 260 var b Buffer 261 b.ReadFrom(&buf) 262 empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(testString))) 263 } 264} 265 266type panicReader struct{ panic bool } 267 268func (r panicReader) Read(p []byte) (int, error) { 269 if r.panic { 270 panic(nil) 271 } 272 return 0, io.EOF 273} 274 275// Make sure that an empty Buffer remains empty when 276// it is "grown" before a Read that panics 277func TestReadFromPanicReader(t *testing.T) { 278 279 // First verify non-panic behaviour 280 var buf Buffer 281 i, err := buf.ReadFrom(panicReader{}) 282 if err != nil { 283 t.Fatal(err) 284 } 285 if i != 0 { 286 t.Fatalf("unexpected return from bytes.ReadFrom (1): got: %d, want %d", i, 0) 287 } 288 check(t, "TestReadFromPanicReader (1)", &buf, "") 289 290 // Confirm that when Reader panics, the empty buffer remains empty 291 var buf2 Buffer 292 defer func() { 293 recover() 294 check(t, "TestReadFromPanicReader (2)", &buf2, "") 295 }() 296 buf2.ReadFrom(panicReader{panic: true}) 297} 298 299func TestReadFromNegativeReader(t *testing.T) { 300 var b Buffer 301 defer func() { 302 switch err := recover().(type) { 303 case nil: 304 t.Fatal("bytes.Buffer.ReadFrom didn't panic") 305 case error: 306 // this is the error string of errNegativeRead 307 wantError := "bytes.Buffer: reader returned negative count from Read" 308 if err.Error() != wantError { 309 t.Fatalf("recovered panic: got %v, want %v", err.Error(), wantError) 310 } 311 default: 312 t.Fatalf("unexpected panic value: %#v", err) 313 } 314 }() 315 316 b.ReadFrom(new(negativeReader)) 317} 318 319func TestWriteTo(t *testing.T) { 320 var buf Buffer 321 for i := 3; i < 30; i += 3 { 322 s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) 323 var b Buffer 324 buf.WriteTo(&b) 325 empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(testString))) 326 } 327} 328 329func TestRuneIO(t *testing.T) { 330 const NRune = 1000 331 // Built a test slice while we write the data 332 b := make([]byte, utf8.UTFMax*NRune) 333 var buf Buffer 334 n := 0 335 for r := rune(0); r < NRune; r++ { 336 size := utf8.EncodeRune(b[n:], r) 337 nbytes, err := buf.WriteRune(r) 338 if err != nil { 339 t.Fatalf("WriteRune(%U) error: %s", r, err) 340 } 341 if nbytes != size { 342 t.Fatalf("WriteRune(%U) expected %d, got %d", r, size, nbytes) 343 } 344 n += size 345 } 346 b = b[0:n] 347 348 // Check the resulting bytes 349 if !Equal(buf.Bytes(), b) { 350 t.Fatalf("incorrect result from WriteRune: %q not %q", buf.Bytes(), b) 351 } 352 353 p := make([]byte, utf8.UTFMax) 354 // Read it back with ReadRune 355 for r := rune(0); r < NRune; r++ { 356 size := utf8.EncodeRune(p, r) 357 nr, nbytes, err := buf.ReadRune() 358 if nr != r || nbytes != size || err != nil { 359 t.Fatalf("ReadRune(%U) got %U,%d not %U,%d (err=%s)", r, nr, nbytes, r, size, err) 360 } 361 } 362 363 // Check that UnreadRune works 364 buf.Reset() 365 366 // check at EOF 367 if err := buf.UnreadRune(); err == nil { 368 t.Fatal("UnreadRune at EOF: got no error") 369 } 370 if _, _, err := buf.ReadRune(); err == nil { 371 t.Fatal("ReadRune at EOF: got no error") 372 } 373 if err := buf.UnreadRune(); err == nil { 374 t.Fatal("UnreadRune after ReadRune at EOF: got no error") 375 } 376 377 // check not at EOF 378 buf.Write(b) 379 for r := rune(0); r < NRune; r++ { 380 r1, size, _ := buf.ReadRune() 381 if err := buf.UnreadRune(); err != nil { 382 t.Fatalf("UnreadRune(%U) got error %q", r, err) 383 } 384 r2, nbytes, err := buf.ReadRune() 385 if r1 != r2 || r1 != r || nbytes != size || err != nil { 386 t.Fatalf("ReadRune(%U) after UnreadRune got %U,%d not %U,%d (err=%s)", r, r2, nbytes, r, size, err) 387 } 388 } 389} 390 391func TestNext(t *testing.T) { 392 b := []byte{0, 1, 2, 3, 4} 393 tmp := make([]byte, 5) 394 for i := 0; i <= 5; i++ { 395 for j := i; j <= 5; j++ { 396 for k := 0; k <= 6; k++ { 397 // 0 <= i <= j <= 5; 0 <= k <= 6 398 // Check that if we start with a buffer 399 // of length j at offset i and ask for 400 // Next(k), we get the right bytes. 401 buf := NewBuffer(b[0:j]) 402 n, _ := buf.Read(tmp[0:i]) 403 if n != i { 404 t.Fatalf("Read %d returned %d", i, n) 405 } 406 bb := buf.Next(k) 407 want := k 408 if want > j-i { 409 want = j - i 410 } 411 if len(bb) != want { 412 t.Fatalf("in %d,%d: len(Next(%d)) == %d", i, j, k, len(bb)) 413 } 414 for l, v := range bb { 415 if v != byte(l+i) { 416 t.Fatalf("in %d,%d: Next(%d)[%d] = %d, want %d", i, j, k, l, v, l+i) 417 } 418 } 419 } 420 } 421 } 422} 423 424var readBytesTests = []struct { 425 buffer string 426 delim byte 427 expected []string 428 err error 429}{ 430 {"", 0, []string{""}, io.EOF}, 431 {"a\x00", 0, []string{"a\x00"}, nil}, 432 {"abbbaaaba", 'b', []string{"ab", "b", "b", "aaab"}, nil}, 433 {"hello\x01world", 1, []string{"hello\x01"}, nil}, 434 {"foo\nbar", 0, []string{"foo\nbar"}, io.EOF}, 435 {"alpha\nbeta\ngamma\n", '\n', []string{"alpha\n", "beta\n", "gamma\n"}, nil}, 436 {"alpha\nbeta\ngamma", '\n', []string{"alpha\n", "beta\n", "gamma"}, io.EOF}, 437} 438 439func TestReadBytes(t *testing.T) { 440 for _, test := range readBytesTests { 441 buf := NewBufferString(test.buffer) 442 var err error 443 for _, expected := range test.expected { 444 var bytes []byte 445 bytes, err = buf.ReadBytes(test.delim) 446 if string(bytes) != expected { 447 t.Errorf("expected %q, got %q", expected, bytes) 448 } 449 if err != nil { 450 break 451 } 452 } 453 if err != test.err { 454 t.Errorf("expected error %v, got %v", test.err, err) 455 } 456 } 457} 458 459func TestReadString(t *testing.T) { 460 for _, test := range readBytesTests { 461 buf := NewBufferString(test.buffer) 462 var err error 463 for _, expected := range test.expected { 464 var s string 465 s, err = buf.ReadString(test.delim) 466 if s != expected { 467 t.Errorf("expected %q, got %q", expected, s) 468 } 469 if err != nil { 470 break 471 } 472 } 473 if err != test.err { 474 t.Errorf("expected error %v, got %v", test.err, err) 475 } 476 } 477} 478 479func BenchmarkReadString(b *testing.B) { 480 const n = 32 << 10 481 482 data := make([]byte, n) 483 data[n-1] = 'x' 484 b.SetBytes(int64(n)) 485 for i := 0; i < b.N; i++ { 486 buf := NewBuffer(data) 487 _, err := buf.ReadString('x') 488 if err != nil { 489 b.Fatal(err) 490 } 491 } 492} 493 494func TestGrow(t *testing.T) { 495 x := []byte{'x'} 496 y := []byte{'y'} 497 tmp := make([]byte, 72) 498 for _, startLen := range []int{0, 100, 1000, 10000, 100000} { 499 xBytes := Repeat(x, startLen) 500 for _, growLen := range []int{0, 100, 1000, 10000, 100000} { 501 buf := NewBuffer(xBytes) 502 // If we read, this affects buf.off, which is good to test. 503 readBytes, _ := buf.Read(tmp) 504 buf.Grow(growLen) 505 yBytes := Repeat(y, growLen) 506 // Check no allocation occurs in write, as long as we're single-threaded. 507 var m1, m2 runtime.MemStats 508 runtime.ReadMemStats(&m1) 509 buf.Write(yBytes) 510 runtime.ReadMemStats(&m2) 511 if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs { 512 t.Errorf("allocation occurred during write") 513 } 514 // Check that buffer has correct data. 515 if !Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) { 516 t.Errorf("bad initial data at %d %d", startLen, growLen) 517 } 518 if !Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) { 519 t.Errorf("bad written data at %d %d", startLen, growLen) 520 } 521 } 522 } 523} 524 525func TestGrowOverflow(t *testing.T) { 526 defer func() { 527 if err := recover(); err != ErrTooLarge { 528 t.Errorf("after too-large Grow, recover() = %v; want %v", err, ErrTooLarge) 529 } 530 }() 531 532 buf := NewBuffer(make([]byte, 1)) 533 const maxInt = int(^uint(0) >> 1) 534 buf.Grow(maxInt) 535} 536 537// Was a bug: used to give EOF reading empty slice at EOF. 538func TestReadEmptyAtEOF(t *testing.T) { 539 b := new(Buffer) 540 slice := make([]byte, 0) 541 n, err := b.Read(slice) 542 if err != nil { 543 t.Errorf("read error: %v", err) 544 } 545 if n != 0 { 546 t.Errorf("wrong count; got %d want 0", n) 547 } 548} 549 550func TestUnreadByte(t *testing.T) { 551 b := new(Buffer) 552 553 // check at EOF 554 if err := b.UnreadByte(); err == nil { 555 t.Fatal("UnreadByte at EOF: got no error") 556 } 557 if _, err := b.ReadByte(); err == nil { 558 t.Fatal("ReadByte at EOF: got no error") 559 } 560 if err := b.UnreadByte(); err == nil { 561 t.Fatal("UnreadByte after ReadByte at EOF: got no error") 562 } 563 564 // check not at EOF 565 b.WriteString("abcdefghijklmnopqrstuvwxyz") 566 567 // after unsuccessful read 568 if n, err := b.Read(nil); n != 0 || err != nil { 569 t.Fatalf("Read(nil) = %d,%v; want 0,nil", n, err) 570 } 571 if err := b.UnreadByte(); err == nil { 572 t.Fatal("UnreadByte after Read(nil): got no error") 573 } 574 575 // after successful read 576 if _, err := b.ReadBytes('m'); err != nil { 577 t.Fatalf("ReadBytes: %v", err) 578 } 579 if err := b.UnreadByte(); err != nil { 580 t.Fatalf("UnreadByte: %v", err) 581 } 582 c, err := b.ReadByte() 583 if err != nil { 584 t.Fatalf("ReadByte: %v", err) 585 } 586 if c != 'm' { 587 t.Errorf("ReadByte = %q; want %q", c, 'm') 588 } 589} 590 591// Tests that we occasionally compact. Issue 5154. 592func TestBufferGrowth(t *testing.T) { 593 var b Buffer 594 buf := make([]byte, 1024) 595 b.Write(buf[0:1]) 596 var cap0 int 597 for i := 0; i < 5<<10; i++ { 598 b.Write(buf) 599 b.Read(buf) 600 if i == 0 { 601 cap0 = b.Cap() 602 } 603 } 604 cap1 := b.Cap() 605 // (*Buffer).grow allows for 2x capacity slop before sliding, 606 // so set our error threshold at 3x. 607 if cap1 > cap0*3 { 608 t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0) 609 } 610} 611 612func BenchmarkWriteByte(b *testing.B) { 613 const n = 4 << 10 614 b.SetBytes(n) 615 buf := NewBuffer(make([]byte, n)) 616 for i := 0; i < b.N; i++ { 617 buf.Reset() 618 for i := 0; i < n; i++ { 619 buf.WriteByte('x') 620 } 621 } 622} 623 624func BenchmarkWriteRune(b *testing.B) { 625 const n = 4 << 10 626 const r = '☺' 627 b.SetBytes(int64(n * utf8.RuneLen(r))) 628 buf := NewBuffer(make([]byte, n*utf8.UTFMax)) 629 for i := 0; i < b.N; i++ { 630 buf.Reset() 631 for i := 0; i < n; i++ { 632 buf.WriteRune(r) 633 } 634 } 635} 636 637// From Issue 5154. 638func BenchmarkBufferNotEmptyWriteRead(b *testing.B) { 639 buf := make([]byte, 1024) 640 for i := 0; i < b.N; i++ { 641 var b Buffer 642 b.Write(buf[0:1]) 643 for i := 0; i < 5<<10; i++ { 644 b.Write(buf) 645 b.Read(buf) 646 } 647 } 648} 649 650// Check that we don't compact too often. From Issue 5154. 651func BenchmarkBufferFullSmallReads(b *testing.B) { 652 buf := make([]byte, 1024) 653 for i := 0; i < b.N; i++ { 654 var b Buffer 655 b.Write(buf) 656 for b.Len()+20 < b.Cap() { 657 b.Write(buf[:10]) 658 } 659 for i := 0; i < 5<<10; i++ { 660 b.Read(buf[:1]) 661 b.Write(buf[:1]) 662 } 663 } 664} 665