Source file
src/bytes/buffer_test.go
Documentation: bytes
1
2
3
4
5 package bytes_test
6
7 import (
8 . "bytes"
9 "fmt"
10 "internal/testenv"
11 "io"
12 "math/rand"
13 "strconv"
14 "testing"
15 "unicode/utf8"
16 )
17
18 const N = 10000
19 var testString string
20 var testBytes []byte
21
22 type negativeReader struct{}
23
24 func (r *negativeReader) Read([]byte) (int, error) { return -1, nil }
25
26 func 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
35 func 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
56
57
58 func 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
75
76
77 func 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
93 func TestNewBuffer(t *testing.T) {
94 buf := NewBuffer(testBytes)
95 check(t, "NewBuffer", buf, testString)
96 }
97
98 var buf Buffer
99
100
101
102
103 func 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
114 func TestNewBufferString(t *testing.T) {
115 buf := NewBufferString(testString)
116 check(t, "NewBufferString", buf, testString)
117 }
118
119
120
121 func 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
139 func 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
187 func 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
200 func 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
213 func 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
222 func 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
231 func 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
250 func 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
258 func 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
267 func 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
274 func 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
284 type panicReader struct{ panic bool }
285
286 func (r panicReader) Read(p []byte) (int, error) {
287 if r.panic {
288 panic("oops")
289 }
290 return 0, io.EOF
291 }
292
293
294
295 func TestReadFromPanicReader(t *testing.T) {
296
297
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
309 var buf2 Buffer
310 defer func() {
311 recover()
312 check(t, "TestReadFromPanicReader (2)", &buf2, "")
313 }()
314 buf2.ReadFrom(panicReader{panic: true})
315 }
316
317 func 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
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
337 func 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
347 func 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
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
374 func TestRuneIO(t *testing.T) {
375 const NRune = 1000
376
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
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
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
409 buf.Reset()
410
411
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
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
436 func TestWriteInvalidRune(t *testing.T) {
437
438
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
446 func 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
453
454
455
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
479 var 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
494 func 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
514 func 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
534 func 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
549 func 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
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
566 if allocs != 0 {
567 t.Errorf("allocation occurred during write")
568 }
569
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
580 func 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
593 func 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
605 func TestUnreadByte(t *testing.T) {
606 b := new(Buffer)
607
608
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
620 b.WriteString("abcdefghijklmnopqrstuvwxyz")
621
622
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
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
647 func 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
661
662 if cap1 > cap0*3 {
663 t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0)
664 }
665 }
666
667 func 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
679 func 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
693 func 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
706 func 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
721 func 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
736 func 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)]
745 bb.Write(b)
746 }
747 }
748
View as plain text