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