Created
June 5, 2015 06:15
-
-
Save davecheney/f3f8c627f7c13df1f72d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package bytes | |
| import ( | |
| "io" | |
| "math/rand" | |
| "testing" | |
| ) | |
| const N = 10000 // make this bigger for a larger (and slower) test | |
| var data string // test data for write tests | |
| var testBytes []byte // test data; same as data but as a slice. | |
| func init() { | |
| testBytes = make([]byte, N) | |
| for i := 0; i < N; i++ { | |
| testBytes[i] = 'a' + byte(i%26) | |
| } | |
| data = string(testBytes) | |
| } | |
| func (b *Buffer) Bytes() []byte { | |
| x := *b | |
| return []byte(x) | |
| } | |
| func (b *Buffer) Reset() { | |
| b.Truncate(0) | |
| } | |
| func (b *Buffer) Truncate(n int) { | |
| *b = (*b)[:n] | |
| } | |
| func (b *Buffer) String() string { | |
| if b == nil { | |
| return "<nil>" | |
| } | |
| return string(*b) | |
| } | |
| func (b *Buffer) Len() int { return len(*b) } | |
| func (b *Buffer) Cap() int { return cap(*b) } | |
| func (b *Buffer) WriteString(s string) (int, error) { | |
| return b.Write([]byte(s)) | |
| } | |
| func (b *Buffer) WriteByte(c byte) error { | |
| *b = append(*b, c) | |
| return nil | |
| } | |
| func (b *Buffer) ReadByte() (byte, error) { | |
| if b.Len() == 0 { | |
| return 0, io.EOF | |
| } | |
| c := (*b)[0] | |
| *b = (*b)[1:] | |
| return c, nil | |
| } | |
| func NewBuffer(b []byte) *Buffer { | |
| x := Buffer(b) | |
| return &x | |
| } | |
| func NewBufferString(s string) *Buffer { | |
| return NewBuffer([]byte(s)) | |
| } | |
| // Verify that contents of buf match the string s. | |
| func check(t *testing.T, testname string, buf *Buffer, s string) { | |
| bytes := buf.Bytes() | |
| str := buf.String() | |
| if buf.Len() != len(bytes) { | |
| t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d", testname, buf.Len(), len(bytes)) | |
| } | |
| if buf.Len() != len(str) { | |
| t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d", testname, buf.Len(), len(str)) | |
| } | |
| if buf.Len() != len(s) { | |
| t.Errorf("%s: buf.Len() == %d, len(s) == %d", testname, buf.Len(), len(s)) | |
| } | |
| if string(bytes) != s { | |
| t.Errorf("%s: string(buf.Bytes()) == %q, s == %q", testname, string(bytes), s) | |
| } | |
| } | |
| // Fill buf through n writes of string fus. | |
| // The initial contents of buf corresponds to the string s; | |
| // the result is the final contents of buf returned as a string. | |
| func fillString(t *testing.T, testname string, buf *Buffer, s string, n int, fus string) string { | |
| check(t, testname+" (fill 1)", buf, s) | |
| for ; n > 0; n-- { | |
| m, err := buf.WriteString(fus) | |
| if m != len(fus) { | |
| t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fus)) | |
| } | |
| if err != nil { | |
| t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) | |
| } | |
| s += fus | |
| check(t, testname+" (fill 4)", buf, s) | |
| } | |
| return s | |
| } | |
| // Fill buf through n writes of byte slice fub. | |
| // The initial contents of buf corresponds to the string s; | |
| // the result is the final contents of buf returned as a string. | |
| func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub []byte) string { | |
| check(t, testname+" (fill 1)", buf, s) | |
| for ; n > 0; n-- { | |
| m, err := buf.Write(fub) | |
| if m != len(fub) { | |
| t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fub)) | |
| } | |
| if err != nil { | |
| t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) | |
| } | |
| s += string(fub) | |
| check(t, testname+" (fill 4)", buf, s) | |
| } | |
| return s | |
| } | |
| func TestNewBuffer(t *testing.T) { | |
| buf := NewBuffer(testBytes) | |
| check(t, "NewBuffer", buf, data) | |
| } | |
| func TestNewBufferString(t *testing.T) { | |
| buf := NewBufferString(data) | |
| check(t, "NewBufferString", buf, data) | |
| } | |
| // Empty buf through repeated reads into fub. | |
| // The initial contents of buf corresponds to the string s. | |
| func empty(t *testing.T, testname string, buf *Buffer, s string, fub []byte) { | |
| check(t, testname+" (empty 1)", buf, s) | |
| for { | |
| n, err := buf.Read(fub) | |
| if n == 0 { | |
| break | |
| } | |
| if err != nil { | |
| t.Errorf(testname+" (empty 2): err should always be nil, found err == %s", err) | |
| } | |
| s = s[n:] | |
| check(t, testname+" (empty 3)", buf, s) | |
| } | |
| check(t, testname+" (empty 4)", buf, "") | |
| } | |
| func TestBasicOperations(t *testing.T) { | |
| var buf Buffer | |
| for i := 0; i < 5; i++ { | |
| check(t, "TestBasicOperations (1)", &buf, "") | |
| buf.Reset() | |
| check(t, "TestBasicOperations (2)", &buf, "") | |
| buf.Truncate(0) | |
| check(t, "TestBasicOperations (3)", &buf, "") | |
| n, err := buf.Write([]byte(data[0:1])) | |
| if n != 1 { | |
| t.Errorf("wrote 1 byte, but n == %d", n) | |
| } | |
| if err != nil { | |
| t.Errorf("err should always be nil, but err == %s", err) | |
| } | |
| check(t, "TestBasicOperations (4)", &buf, "a") | |
| buf.WriteByte(data[1]) | |
| check(t, "TestBasicOperations (5)", &buf, "ab") | |
| n, err = buf.Write([]byte(data[2:26])) | |
| if n != 24 { | |
| t.Errorf("wrote 25 bytes, but n == %d", n) | |
| } | |
| check(t, "TestBasicOperations (6)", &buf, string(data[0:26])) | |
| buf.Truncate(26) | |
| check(t, "TestBasicOperations (7)", &buf, string(data[0:26])) | |
| buf.Truncate(20) | |
| check(t, "TestBasicOperations (8)", &buf, string(data[0:20])) | |
| empty(t, "TestBasicOperations (9)", &buf, string(data[0:20]), make([]byte, 5)) | |
| empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100)) | |
| buf.WriteByte(data[1]) | |
| c, err := buf.ReadByte() | |
| if err != nil { | |
| t.Error("ReadByte unexpected eof") | |
| } | |
| if c != data[1] { | |
| t.Errorf("ReadByte wrong value c=%v", c) | |
| } | |
| c, err = buf.ReadByte() | |
| if err == nil { | |
| t.Error("ReadByte unexpected not eof") | |
| } | |
| } | |
| } | |
| func TestLargeStringWrites(t *testing.T) { | |
| var buf Buffer | |
| limit := 30 | |
| if testing.Short() { | |
| limit = 9 | |
| } | |
| for i := 3; i < limit; i += 3 { | |
| s := fillString(t, "TestLargeWrites (1)", &buf, "", 5, data) | |
| empty(t, "TestLargeStringWrites (2)", &buf, s, make([]byte, len(data)/i)) | |
| } | |
| check(t, "TestLargeStringWrites (3)", &buf, "") | |
| } | |
| func TestLargeByteWrites(t *testing.T) { | |
| var buf Buffer | |
| limit := 30 | |
| if testing.Short() { | |
| limit = 9 | |
| } | |
| for i := 3; i < limit; i += 3 { | |
| s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes) | |
| empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(data)/i)) | |
| } | |
| check(t, "TestLargeByteWrites (3)", &buf, "") | |
| } | |
| func TestLargeStringReads(t *testing.T) { | |
| var buf Buffer | |
| for i := 3; i < 30; i += 3 { | |
| s := fillString(t, "TestLargeReads (1)", &buf, "", 5, data[0:len(data)/i]) | |
| empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data))) | |
| } | |
| check(t, "TestLargeStringReads (3)", &buf, "") | |
| } | |
| func TestLargeByteReads(t *testing.T) { | |
| var buf Buffer | |
| for i := 3; i < 30; i += 3 { | |
| s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) | |
| empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data))) | |
| } | |
| check(t, "TestLargeByteReads (3)", &buf, "") | |
| } | |
| func TestMixedReadsAndWrites(t *testing.T) { | |
| var buf Buffer | |
| s := "" | |
| for i := 0; i < 50; i++ { | |
| wlen := rand.Intn(len(data)) | |
| if i%2 == 0 { | |
| s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen]) | |
| } else { | |
| s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen]) | |
| } | |
| rlen := rand.Intn(len(data)) | |
| fub := make([]byte, rlen) | |
| n, _ := buf.Read(fub) | |
| s = s[n:] | |
| } | |
| empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len())) | |
| } | |
| func TestCapWithPreallocatedSlice(t *testing.T) { | |
| buf := NewBuffer(make([]byte, 10)) | |
| n := buf.Cap() | |
| if n != 10 { | |
| t.Errorf("expected 10, got %d", n) | |
| } | |
| } | |
| func TestCapWithSliceAndWrittenData(t *testing.T) { | |
| buf := NewBuffer(make([]byte, 0, 10)) | |
| buf.Write([]byte("test")) | |
| n := buf.Cap() | |
| if n != 10 { | |
| t.Errorf("expected 10, got %d", n) | |
| } | |
| } | |
| func TestNil(t *testing.T) { | |
| var b *Buffer | |
| if b.String() != "<nil>" { | |
| t.Errorf("expected <nil>; got %q", b.String()) | |
| } | |
| } | |
| // Was a bug: used to give EOF reading empty slice at EOF. | |
| func TestReadEmptyAtEOF(t *testing.T) { | |
| b := new(Buffer) | |
| slice := make([]byte, 0) | |
| n, err := b.Read(slice) | |
| if err != nil { | |
| t.Errorf("read error: %v", err) | |
| } | |
| if n != 0 { | |
| t.Errorf("wrong count; got %d want 0", n) | |
| } | |
| } | |
| // From Issue 5154. | |
| func BenchmarkBufferNotEmptyWriteRead(b *testing.B) { | |
| buf := make([]byte, 1024) | |
| for i := 0; i < b.N; i++ { | |
| var b Buffer | |
| b.Write(buf[0:1]) | |
| for i := 0; i < 5<<10; i++ { | |
| b.Write(buf) | |
| b.Read(buf) | |
| } | |
| } | |
| } | |
| // Check that we don't compact too often. From Issue 5154. | |
| func BenchmarkBufferFullSmallReads(b *testing.B) { | |
| buf := make([]byte, 1024) | |
| for i := 0; i < b.N; i++ { | |
| var b Buffer | |
| b.Write(buf) | |
| for b.Len()+20 < b.Cap() { | |
| b.Write(buf[:10]) | |
| } | |
| for i := 0; i < 5<<10; i++ { | |
| b.Read(buf[:1]) | |
| b.Write(buf[:1]) | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment