]> Cypherpunks.ru repositories - gostls13.git/blob - src/bytes/buffer_test.go
bytes: add Buffer.Available and Buffer.AvailableBuffer
[gostls13.git] / src / bytes / buffer_test.go
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(nil)
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 }