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 "io"
11 "math/rand"
12 "strconv"
13 "testing"
14 "unicode/utf8"
15 )
16
17 const N = 10000
18 var testString string
19 var testBytes []byte
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
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
55
56
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
74
75
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
103
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
277
278 func TestReadFromPanicReader(t *testing.T) {
279
280
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
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
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
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
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
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
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
392 buf.Reset()
393
394
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
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
421
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
436
437
438
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
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
549 if allocs != 0 {
550 t.Errorf("allocation occurred during write")
551 }
552
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
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
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
603 b.WriteString("abcdefghijklmnopqrstuvwxyz")
604
605
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
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
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
644
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
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
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)]
728 bb.Write(b)
729 }
730 }
731
View as plain text