1// Copyright 2009 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45package bytes_test67import (8 . "bytes"9 "fmt"10 "internal/testenv"11 "io"12 "math/rand"13 "strconv"14 "testing"15 "unicode/utf8"16)1718const N = 10000 // make this bigger for a larger (and slower) test19var testString string // test data for write tests20var testBytes []byte // test data; same as testString but as a slice.2122type negativeReader struct{}2324func (r *negativeReader) Read([]byte) (int, error) { return -1, nil }2526func 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}3334// 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 }4142 if buf.Len() != len(str) {43 t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d", testname, buf.Len(), len(str))44 }4546 if buf.Len() != len(s) {47 t.Errorf("%s: buf.Len() == %d, len(s) == %d", testname, buf.Len(), len(s))48 }4950 if string(bytes) != s {51 t.Errorf("%s: string(buf.Bytes()) == %q, s == %q", testname, string(bytes), s)52 }53}5455// 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 += fus69 check(t, testname+" (fill 4)", buf, s)70 }71 return s72}7374// 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 s91}9293func TestNewBuffer(t *testing.T) {94 buf := NewBuffer(testBytes)95 check(t, "NewBuffer", buf, testString)96}9798var buf Buffer99100// Calling NewBuffer and immediately shallow copying the Buffer struct101// 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}113114func TestNewBufferString(t *testing.T) {115 buf := NewBufferString(testString)116 check(t, "NewBufferString", buf, testString)117}118119// 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)123124 for {125 n, err := buf.Read(fub)126 if n == 0 {127 break128 }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 }135136 check(t, testname+" (empty 4)", buf, "")137}138139func TestBasicOperations(t *testing.T) {140 var buf Buffer141142 for i := 0; i < 5; i++ {143 check(t, "TestBasicOperations (1)", &buf, "")144145 buf.Reset()146 check(t, "TestBasicOperations (2)", &buf, "")147148 buf.Truncate(0)149 check(t, "TestBasicOperations (3)", &buf, "")150151 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")156157 buf.WriteByte(testString[1])158 check(t, "TestBasicOperations (5)", &buf, "ab")159160 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])165166 buf.Truncate(26)167 check(t, "TestBasicOperations (7)", &buf, testString[0:26])168169 buf.Truncate(20)170 check(t, "TestBasicOperations (8)", &buf, testString[0:20])171172 empty(t, "TestBasicOperations (9)", &buf, testString[0:20], make([]byte, 5))173 empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100))174175 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}186187func TestLargeStringWrites(t *testing.T) {188 var buf Buffer189 limit := 30190 if testing.Short() {191 limit = 9192 }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}199200func TestLargeByteWrites(t *testing.T) {201 var buf Buffer202 limit := 30203 if testing.Short() {204 limit = 9205 }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}212213func TestLargeStringReads(t *testing.T) {214 var buf Buffer215 for i := 3; i < 30; i += 3 {216 s := fillString(t, "TestLargeReads (1)", &buf, "", 5, testString[:len(testString)/i])217 empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(testString)))218 }219 check(t, "TestLargeStringReads (3)", &buf, "")220}221222func TestLargeByteReads(t *testing.T) {223 var buf Buffer224 for i := 3; i < 30; i += 3 {225 s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[:len(testBytes)/i])226 empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(testString)))227 }228 check(t, "TestLargeByteReads (3)", &buf, "")229}230231func TestMixedReadsAndWrites(t *testing.T) {232 var buf Buffer233 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 }241242 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}249250func 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}257258func 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}266267func TestNil(t *testing.T) {268 var b *Buffer269 if b.String() != "<nil>" {270 t.Errorf("expected <nil>; got %q", b.String())271 }272}273274func TestReadFrom(t *testing.T) {275 var buf Buffer276 for i := 3; i < 30; i += 3 {277 s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[:len(testBytes)/i])278 var b Buffer279 b.ReadFrom(&buf)280 empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(testString)))281 }282}283284type panicReader struct{ panic bool }285286func (r panicReader) Read(p []byte) (int, error) {287 if r.panic {288 panic("oops")289 }290 return 0, io.EOF291}292293// Make sure that an empty Buffer remains empty when294// it is "grown" before a Read that panics295func TestReadFromPanicReader(t *testing.T) {296297 // First verify non-panic behaviour298 var buf Buffer299 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, "")307308 // Confirm that when Reader panics, the empty buffer remains empty309 var buf2 Buffer310 defer func() {311 recover()312 check(t, "TestReadFromPanicReader (2)", &buf2, "")313 }()314 buf2.ReadFrom(panicReader{panic: true})315}316317func TestReadFromNegativeReader(t *testing.T) {318 var b Buffer319 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 errNegativeRead325 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 }()333334 b.ReadFrom(new(negativeReader))335}336337func TestWriteTo(t *testing.T) {338 var buf Buffer339 for i := 3; i < 30; i += 3 {340 s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[:len(testBytes)/i])341 var b Buffer342 buf.WriteTo(&b)343 empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(testString)))344 }345}346347func TestWriteAppend(t *testing.T) {348 var got Buffer349 var want []byte350 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 }359360 // 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}373374func TestRuneIO(t *testing.T) {375 const NRune = 1000376 // Built a test slice while we write the data377 b := make([]byte, utf8.UTFMax*NRune)378 var buf Buffer379 n := 0380 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 += size390 }391 b = b[0:n]392393 // Check the resulting bytes394 if !Equal(buf.Bytes(), b) {395 t.Fatalf("incorrect result from WriteRune: %q not %q", buf.Bytes(), b)396 }397398 p := make([]byte, utf8.UTFMax)399 // Read it back with ReadRune400 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 }407408 // Check that UnreadRune works409 buf.Reset()410411 // check at EOF412 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 }421422 // check not at EOF423 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}435436func TestWriteInvalidRune(t *testing.T) {437 // Invalid runes, including negative ones, should be written as438 // utf8.RuneError.439 for _, r := range []rune{-1, utf8.MaxRune + 1} {440 var buf Buffer441 buf.WriteRune(r)442 check(t, fmt.Sprintf("TestWriteInvalidRune (%d)", r), &buf, "\uFFFD")443 }444}445446func 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 <= 6453 // Check that if we start with a buffer454 // of length j at offset i and ask for455 // 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 := k463 if want > j-i {464 want = j - i465 }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}478479var readBytesTests = []struct {480 buffer string481 delim byte482 expected []string483 err error484}{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}493494func TestReadBytes(t *testing.T) {495 for _, test := range readBytesTests {496 buf := NewBufferString(test.buffer)497 var err error498 for _, expected := range test.expected {499 var bytes []byte500 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 break506 }507 }508 if err != test.err {509 t.Errorf("expected error %v, got %v", test.err, err)510 }511 }512}513514func TestReadString(t *testing.T) {515 for _, test := range readBytesTests {516 buf := NewBufferString(test.buffer)517 var err error518 for _, expected := range test.expected {519 var s string520 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 break526 }527 }528 if err != test.err {529 t.Errorf("expected error %v, got %v", test.err, err)530 }531 }532}533534var peekTests = []struct {535 buffer string536 skip int537 n int538 expected string539 err error540}{541 {"", 0, 0, "", nil},542 {"aaa", 0, 3, "aaa", nil},543 {"foobar", 0, 2, "fo", nil},544 {"a", 0, 2, "a", io.EOF},545 {"helloworld", 4, 3, "owo", nil},546 {"helloworld", 5, 5, "world", nil},547 {"helloworld", 5, 6, "world", io.EOF},548 {"helloworld", 10, 1, "", io.EOF},549}550551func TestPeek(t *testing.T) {552 for _, test := range peekTests {553 buf := NewBufferString(test.buffer)554 buf.Next(test.skip)555 bytes, err := buf.Peek(test.n)556 if string(bytes) != test.expected {557 t.Errorf("expected %q, got %q", test.expected, bytes)558 }559 if err != test.err {560 t.Errorf("expected error %v, got %v", test.err, err)561 }562 if buf.Len() != len(test.buffer)-test.skip {563 t.Errorf("bad length after peek: %d, want %d", buf.Len(), len(test.buffer)-test.skip)564 }565 }566}567568func BenchmarkReadString(b *testing.B) {569 const n = 32 << 10570571 data := make([]byte, n)572 data[n-1] = 'x'573 b.SetBytes(int64(n))574 for i := 0; i < b.N; i++ {575 buf := NewBuffer(data)576 _, err := buf.ReadString('x')577 if err != nil {578 b.Fatal(err)579 }580 }581}582583func TestGrow(t *testing.T) {584 x := []byte{'x'}585 y := []byte{'y'}586 tmp := make([]byte, 72)587 for _, growLen := range []int{0, 100, 1000, 10000, 100000} {588 for _, startLen := range []int{0, 100, 1000, 10000, 100000} {589 xBytes := Repeat(x, startLen)590591 buf := NewBuffer(xBytes)592 // If we read, this affects buf.off, which is good to test.593 readBytes, _ := buf.Read(tmp)594 yBytes := Repeat(y, growLen)595 allocs := testing.AllocsPerRun(100, func() {596 buf.Grow(growLen)597 buf.Write(yBytes)598 })599 // Check no allocation occurs in write, as long as we're single-threaded.600 if allocs != 0 {601 t.Errorf("allocation occurred during write")602 }603 // Check that buffer has correct data.604 if !Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) {605 t.Errorf("bad initial data at %d %d", startLen, growLen)606 }607 if !Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) {608 t.Errorf("bad written data at %d %d", startLen, growLen)609 }610 }611 }612}613614func TestGrowOverflow(t *testing.T) {615 defer func() {616 if err := recover(); err != ErrTooLarge {617 t.Errorf("after too-large Grow, recover() = %v; want %v", err, ErrTooLarge)618 }619 }()620621 buf := NewBuffer(make([]byte, 1))622 const maxInt = int(^uint(0) >> 1)623 buf.Grow(maxInt)624}625626// Was a bug: used to give EOF reading empty slice at EOF.627func TestReadEmptyAtEOF(t *testing.T) {628 b := new(Buffer)629 slice := make([]byte, 0)630 n, err := b.Read(slice)631 if err != nil {632 t.Errorf("read error: %v", err)633 }634 if n != 0 {635 t.Errorf("wrong count; got %d want 0", n)636 }637}638639func TestUnreadByte(t *testing.T) {640 b := new(Buffer)641642 // check at EOF643 if err := b.UnreadByte(); err == nil {644 t.Fatal("UnreadByte at EOF: got no error")645 }646 if _, err := b.ReadByte(); err == nil {647 t.Fatal("ReadByte at EOF: got no error")648 }649 if err := b.UnreadByte(); err == nil {650 t.Fatal("UnreadByte after ReadByte at EOF: got no error")651 }652653 // check not at EOF654 b.WriteString("abcdefghijklmnopqrstuvwxyz")655656 // after unsuccessful read657 if n, err := b.Read(nil); n != 0 || err != nil {658 t.Fatalf("Read(nil) = %d,%v; want 0,nil", n, err)659 }660 if err := b.UnreadByte(); err == nil {661 t.Fatal("UnreadByte after Read(nil): got no error")662 }663664 // after successful read665 if _, err := b.ReadBytes('m'); err != nil {666 t.Fatalf("ReadBytes: %v", err)667 }668 if err := b.UnreadByte(); err != nil {669 t.Fatalf("UnreadByte: %v", err)670 }671 c, err := b.ReadByte()672 if err != nil {673 t.Fatalf("ReadByte: %v", err)674 }675 if c != 'm' {676 t.Errorf("ReadByte = %q; want %q", c, 'm')677 }678}679680// Tests that we occasionally compact. Issue 5154.681func TestBufferGrowth(t *testing.T) {682 var b Buffer683 buf := make([]byte, 1024)684 b.Write(buf[0:1])685 var cap0 int686 for i := 0; i < 5<<10; i++ {687 b.Write(buf)688 b.Read(buf)689 if i == 0 {690 cap0 = b.Cap()691 }692 }693 cap1 := b.Cap()694 // (*Buffer).grow allows for 2x capacity slop before sliding,695 // so set our error threshold at 3x.696 if cap1 > cap0*3 {697 t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0)698 }699}700701func BenchmarkWriteByte(b *testing.B) {702 const n = 4 << 10703 b.SetBytes(n)704 buf := NewBuffer(make([]byte, n))705 for i := 0; i < b.N; i++ {706 buf.Reset()707 for i := 0; i < n; i++ {708 buf.WriteByte('x')709 }710 }711}712713func BenchmarkWriteRune(b *testing.B) {714 const n = 4 << 10715 const r = '☺'716 b.SetBytes(int64(n * utf8.RuneLen(r)))717 buf := NewBuffer(make([]byte, n*utf8.UTFMax))718 for i := 0; i < b.N; i++ {719 buf.Reset()720 for i := 0; i < n; i++ {721 buf.WriteRune(r)722 }723 }724}725726// From Issue 5154.727func BenchmarkBufferNotEmptyWriteRead(b *testing.B) {728 buf := make([]byte, 1024)729 for i := 0; i < b.N; i++ {730 var b Buffer731 b.Write(buf[0:1])732 for i := 0; i < 5<<10; i++ {733 b.Write(buf)734 b.Read(buf)735 }736 }737}738739// Check that we don't compact too often. From Issue 5154.740func BenchmarkBufferFullSmallReads(b *testing.B) {741 buf := make([]byte, 1024)742 for i := 0; i < b.N; i++ {743 var b Buffer744 b.Write(buf)745 for b.Len()+20 < b.Cap() {746 b.Write(buf[:10])747 }748 for i := 0; i < 5<<10; i++ {749 b.Read(buf[:1])750 b.Write(buf[:1])751 }752 }753}754755func BenchmarkBufferWriteBlock(b *testing.B) {756 block := make([]byte, 1024)757 for _, n := range []int{1 << 12, 1 << 16, 1 << 20} {758 b.Run(fmt.Sprintf("N%d", n), func(b *testing.B) {759 b.ReportAllocs()760 for i := 0; i < b.N; i++ {761 var bb Buffer762 for bb.Len() < n {763 bb.Write(block)764 }765 }766 })767 }768}769770func BenchmarkBufferAppendNoCopy(b *testing.B) {771 var bb Buffer772 bb.Grow(16 << 20)773 b.SetBytes(int64(bb.Available()))774 b.ReportAllocs()775 for i := 0; i < b.N; i++ {776 bb.Reset()777 b := bb.AvailableBuffer()778 b = b[:cap(b)] // use max capacity to simulate a large append operation779 bb.Write(b) // should be nearly infinitely fast780 }781}
Findings
✓ No findings reported for this file.