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