Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 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 | |
Russ Cox | 3b864e4 | 2009-08-12 13:18:37 -0700 | [diff] [blame] | 5 | package bytes_test |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 6 | |
| 7 | import ( |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 8 | . "bytes" |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame] | 9 | "io" |
Rob Pike | 30aa701 | 2011-11-08 15:40:58 -0800 | [diff] [blame] | 10 | "math/rand" |
Rob Pike | 1255a63 | 2012-07-12 20:52:19 -0700 | [diff] [blame] | 11 | "runtime" |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 12 | "testing" |
Rob Pike | 30aa701 | 2011-11-08 15:40:58 -0800 | [diff] [blame] | 13 | "unicode/utf8" |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 14 | ) |
| 15 | |
Andrew Gerrand | 749a445 | 2012-10-10 11:59:39 +1100 | [diff] [blame] | 16 | const N = 10000 // make this bigger for a larger (and slower) test |
| 17 | var data string // test data for write tests |
| 18 | var testBytes []byte // test data; same as data but as a slice. |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 19 | |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 20 | func init() { |
Andrew Gerrand | 749a445 | 2012-10-10 11:59:39 +1100 | [diff] [blame] | 21 | testBytes = make([]byte, N) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 22 | for i := 0; i < N; i++ { |
Andrew Gerrand | 749a445 | 2012-10-10 11:59:39 +1100 | [diff] [blame] | 23 | testBytes[i] = 'a' + byte(i%26) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 24 | } |
Andrew Gerrand | 749a445 | 2012-10-10 11:59:39 +1100 | [diff] [blame] | 25 | data = string(testBytes) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 26 | } |
| 27 | |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 28 | // Verify that contents of buf match the string s. |
Russ Cox | 832e72b | 2009-06-29 20:53:05 -0700 | [diff] [blame] | 29 | func check(t *testing.T, testname string, buf *Buffer, s string) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 30 | bytes := buf.Bytes() |
| 31 | str := buf.String() |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 32 | if buf.Len() != len(bytes) { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 33 | t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d", testname, buf.Len(), len(bytes)) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 34 | } |
| 35 | |
| 36 | if buf.Len() != len(str) { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 37 | t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d", testname, buf.Len(), len(str)) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 38 | } |
| 39 | |
| 40 | if buf.Len() != len(s) { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 41 | t.Errorf("%s: buf.Len() == %d, len(s) == %d", testname, buf.Len(), len(s)) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 42 | } |
| 43 | |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 44 | if string(bytes) != s { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 45 | t.Errorf("%s: string(buf.Bytes()) == %q, s == %q", testname, string(bytes), s) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 46 | } |
| 47 | } |
| 48 | |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 49 | // Fill buf through n writes of string fus. |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 50 | // The initial contents of buf corresponds to the string s; |
| 51 | // the result is the final contents of buf returned as a string. |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 52 | func fillString(t *testing.T, testname string, buf *Buffer, s string, n int, fus string) string { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 53 | check(t, testname+" (fill 1)", buf, s) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 54 | for ; n > 0; n-- { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 55 | m, err := buf.WriteString(fus) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 56 | if m != len(fus) { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 57 | t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fus)) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 58 | } |
| 59 | if err != nil { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 60 | t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 61 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 62 | s += fus |
| 63 | check(t, testname+" (fill 4)", buf, s) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 64 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 65 | return s |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 66 | } |
| 67 | |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 68 | // Fill buf through n writes of byte slice fub. |
| 69 | // The initial contents of buf corresponds to the string s; |
| 70 | // the result is the final contents of buf returned as a string. |
| 71 | func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub []byte) string { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 72 | check(t, testname+" (fill 1)", buf, s) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 73 | for ; n > 0; n-- { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 74 | m, err := buf.Write(fub) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 75 | if m != len(fub) { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 76 | t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fub)) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 77 | } |
| 78 | if err != nil { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 79 | t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 80 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 81 | s += string(fub) |
| 82 | check(t, testname+" (fill 4)", buf, s) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 83 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 84 | return s |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 85 | } |
| 86 | |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 87 | func TestNewBuffer(t *testing.T) { |
Andrew Gerrand | 749a445 | 2012-10-10 11:59:39 +1100 | [diff] [blame] | 88 | buf := NewBuffer(testBytes) |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 89 | check(t, "NewBuffer", buf, data) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 90 | } |
| 91 | |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 92 | func TestNewBufferString(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 93 | buf := NewBufferString(data) |
| 94 | check(t, "NewBufferString", buf, data) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 95 | } |
| 96 | |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 97 | // Empty buf through repeated reads into fub. |
| 98 | // The initial contents of buf corresponds to the string s. |
Russ Cox | 832e72b | 2009-06-29 20:53:05 -0700 | [diff] [blame] | 99 | func empty(t *testing.T, testname string, buf *Buffer, s string, fub []byte) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 100 | check(t, testname+" (empty 1)", buf, s) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 101 | |
| 102 | for { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 103 | n, err := buf.Read(fub) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 104 | if n == 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 105 | break |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 106 | } |
| 107 | if err != nil { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 108 | t.Errorf(testname+" (empty 2): err should always be nil, found err == %s", err) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 109 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 110 | s = s[n:] |
| 111 | check(t, testname+" (empty 3)", buf, s) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 112 | } |
| 113 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 114 | check(t, testname+" (empty 4)", buf, "") |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 115 | } |
| 116 | |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 117 | func TestBasicOperations(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 118 | var buf Buffer |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 119 | |
| 120 | for i := 0; i < 5; i++ { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 121 | check(t, "TestBasicOperations (1)", &buf, "") |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 122 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 123 | buf.Reset() |
| 124 | check(t, "TestBasicOperations (2)", &buf, "") |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 125 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 126 | buf.Truncate(0) |
| 127 | check(t, "TestBasicOperations (3)", &buf, "") |
Robert Griesemer | 28db3e8 | 2009-05-14 10:14:29 -0700 | [diff] [blame] | 128 | |
Russ Cox | d86ab01 | 2010-10-26 21:52:54 -0700 | [diff] [blame] | 129 | n, err := buf.Write([]byte(data[0:1])) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 130 | if n != 1 { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 131 | t.Errorf("wrote 1 byte, but n == %d", n) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 132 | } |
| 133 | if err != nil { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 134 | t.Errorf("err should always be nil, but err == %s", err) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 135 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 136 | check(t, "TestBasicOperations (4)", &buf, "a") |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 137 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 138 | buf.WriteByte(data[1]) |
| 139 | check(t, "TestBasicOperations (5)", &buf, "ab") |
Robert Griesemer | 472e191 | 2009-05-14 17:03:47 -0700 | [diff] [blame] | 140 | |
Russ Cox | d86ab01 | 2010-10-26 21:52:54 -0700 | [diff] [blame] | 141 | n, err = buf.Write([]byte(data[2:26])) |
Robert Griesemer | 472e191 | 2009-05-14 17:03:47 -0700 | [diff] [blame] | 142 | if n != 24 { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 143 | t.Errorf("wrote 25 bytes, but n == %d", n) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 144 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 145 | check(t, "TestBasicOperations (6)", &buf, string(data[0:26])) |
Robert Griesemer | 28db3e8 | 2009-05-14 10:14:29 -0700 | [diff] [blame] | 146 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 147 | buf.Truncate(26) |
| 148 | check(t, "TestBasicOperations (7)", &buf, string(data[0:26])) |
Robert Griesemer | 28db3e8 | 2009-05-14 10:14:29 -0700 | [diff] [blame] | 149 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 150 | buf.Truncate(20) |
| 151 | check(t, "TestBasicOperations (8)", &buf, string(data[0:20])) |
Robert Griesemer | 472e191 | 2009-05-14 17:03:47 -0700 | [diff] [blame] | 152 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 153 | empty(t, "TestBasicOperations (9)", &buf, string(data[0:20]), make([]byte, 5)) |
| 154 | empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100)) |
Scott Schwartz | 08aab44 | 2009-06-19 16:29:30 -0700 | [diff] [blame] | 155 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 156 | buf.WriteByte(data[1]) |
| 157 | c, err := buf.ReadByte() |
Scott Schwartz | 08aab44 | 2009-06-19 16:29:30 -0700 | [diff] [blame] | 158 | if err != nil { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 159 | t.Error("ReadByte unexpected eof") |
Scott Schwartz | 08aab44 | 2009-06-19 16:29:30 -0700 | [diff] [blame] | 160 | } |
| 161 | if c != data[1] { |
Rob Pike | 1ce6245 | 2010-12-07 16:42:54 -0500 | [diff] [blame] | 162 | t.Errorf("ReadByte wrong value c=%v", c) |
Scott Schwartz | 08aab44 | 2009-06-19 16:29:30 -0700 | [diff] [blame] | 163 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 164 | c, err = buf.ReadByte() |
Scott Schwartz | 08aab44 | 2009-06-19 16:29:30 -0700 | [diff] [blame] | 165 | if err == nil { |
Rob Pike | 1959c3a | 2010-09-23 13:48:56 +1000 | [diff] [blame] | 166 | t.Error("ReadByte unexpected not eof") |
Scott Schwartz | 08aab44 | 2009-06-19 16:29:30 -0700 | [diff] [blame] | 167 | } |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 168 | } |
| 169 | } |
| 170 | |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 171 | func TestLargeStringWrites(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 172 | var buf Buffer |
Rob Pike | f0cf7d2 | 2011-03-25 16:31:10 -0700 | [diff] [blame] | 173 | limit := 30 |
| 174 | if testing.Short() { |
| 175 | limit = 9 |
| 176 | } |
| 177 | for i := 3; i < limit; i += 3 { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 178 | s := fillString(t, "TestLargeWrites (1)", &buf, "", 5, data) |
| 179 | empty(t, "TestLargeStringWrites (2)", &buf, s, make([]byte, len(data)/i)) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 180 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 181 | check(t, "TestLargeStringWrites (3)", &buf, "") |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 182 | } |
| 183 | |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 184 | func TestLargeByteWrites(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 185 | var buf Buffer |
Rob Pike | f0cf7d2 | 2011-03-25 16:31:10 -0700 | [diff] [blame] | 186 | limit := 30 |
| 187 | if testing.Short() { |
| 188 | limit = 9 |
| 189 | } |
| 190 | for i := 3; i < limit; i += 3 { |
Andrew Gerrand | 749a445 | 2012-10-10 11:59:39 +1100 | [diff] [blame] | 191 | s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes) |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 192 | empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(data)/i)) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 193 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 194 | check(t, "TestLargeByteWrites (3)", &buf, "") |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 195 | } |
| 196 | |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 197 | func TestLargeStringReads(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 198 | var buf Buffer |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 199 | for i := 3; i < 30; i += 3 { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 200 | s := fillString(t, "TestLargeReads (1)", &buf, "", 5, data[0:len(data)/i]) |
| 201 | empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data))) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 202 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 203 | check(t, "TestLargeStringReads (3)", &buf, "") |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 204 | } |
| 205 | |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 206 | func TestLargeByteReads(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 207 | var buf Buffer |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 208 | for i := 3; i < 30; i += 3 { |
Andrew Gerrand | 749a445 | 2012-10-10 11:59:39 +1100 | [diff] [blame] | 209 | s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 210 | empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data))) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 211 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 212 | check(t, "TestLargeByteReads (3)", &buf, "") |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 213 | } |
| 214 | |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 215 | func TestMixedReadsAndWrites(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 216 | var buf Buffer |
| 217 | s := "" |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 218 | for i := 0; i < 50; i++ { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 219 | wlen := rand.Intn(len(data)) |
Russ Cox | 650bff6 | 2009-10-06 14:55:39 -0700 | [diff] [blame] | 220 | if i%2 == 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 221 | s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen]) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 222 | } else { |
Andrew Gerrand | 749a445 | 2012-10-10 11:59:39 +1100 | [diff] [blame] | 223 | s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen]) |
Rob Pike | 6efd7e6 | 2009-09-21 12:59:14 -0700 | [diff] [blame] | 224 | } |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 225 | |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 226 | rlen := rand.Intn(len(data)) |
| 227 | fub := make([]byte, rlen) |
| 228 | n, _ := buf.Read(fub) |
| 229 | s = s[n:] |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 230 | } |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 231 | empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len())) |
Robert Griesemer | eea33fc | 2009-05-05 12:00:52 -0700 | [diff] [blame] | 232 | } |
Rob Pike | 63e668d | 2009-10-31 13:28:22 -0700 | [diff] [blame] | 233 | |
Cristian Staretu | 90554be | 2015-04-01 18:59:51 +0300 | [diff] [blame] | 234 | func TestCapWithPreallocatedSlice(t *testing.T) { |
| 235 | buf := NewBuffer(make([]byte, 10)) |
| 236 | n := buf.Cap() |
| 237 | if n != 10 { |
| 238 | t.Errorf("expected 10, got %d", n) |
| 239 | } |
| 240 | } |
| 241 | |
| 242 | func TestCapWithSliceAndWrittenData(t *testing.T) { |
| 243 | buf := NewBuffer(make([]byte, 0, 10)) |
| 244 | buf.Write([]byte("test")) |
| 245 | n := buf.Cap() |
| 246 | if n != 10 { |
| 247 | t.Errorf("expected 10, got %d", n) |
| 248 | } |
| 249 | } |
| 250 | |
Rob Pike | 63e668d | 2009-10-31 13:28:22 -0700 | [diff] [blame] | 251 | func TestNil(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 252 | var b *Buffer |
Rob Pike | 63e668d | 2009-10-31 13:28:22 -0700 | [diff] [blame] | 253 | if b.String() != "<nil>" { |
Evan Shaw | c9bf30c | 2011-01-27 14:00:31 -0800 | [diff] [blame] | 254 | t.Errorf("expected <nil>; got %q", b.String()) |
Rob Pike | 63e668d | 2009-10-31 13:28:22 -0700 | [diff] [blame] | 255 | } |
| 256 | } |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 257 | |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 258 | func TestReadFrom(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 259 | var buf Buffer |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 260 | for i := 3; i < 30; i += 3 { |
Andrew Gerrand | 749a445 | 2012-10-10 11:59:39 +1100 | [diff] [blame] | 261 | s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 262 | var b Buffer |
| 263 | b.ReadFrom(&buf) |
| 264 | empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data))) |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 265 | } |
| 266 | } |
| 267 | |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 268 | func TestWriteTo(t *testing.T) { |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 269 | var buf Buffer |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 270 | for i := 3; i < 30; i += 3 { |
Evan Shaw | eae25d4 | 2012-10-12 14:43:50 +1100 | [diff] [blame] | 271 | s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[0:len(testBytes)/i]) |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 272 | var b Buffer |
| 273 | buf.WriteTo(&b) |
Evan Shaw | eae25d4 | 2012-10-12 14:43:50 +1100 | [diff] [blame] | 274 | empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(data))) |
Rob Pike | bc3e347 | 2009-12-03 12:56:16 -0800 | [diff] [blame] | 275 | } |
| 276 | } |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 277 | |
| 278 | func TestRuneIO(t *testing.T) { |
| 279 | const NRune = 1000 |
Nigel Tao | c753404 | 2013-01-07 10:48:06 +1100 | [diff] [blame] | 280 | // Built a test slice while we write the data |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 281 | b := make([]byte, utf8.UTFMax*NRune) |
| 282 | var buf Buffer |
| 283 | n := 0 |
Russ Cox | 8f57181 | 2011-10-25 22:22:09 -0700 | [diff] [blame] | 284 | for r := rune(0); r < NRune; r++ { |
Adam Langley | 3cb4bdb | 2010-11-30 16:59:43 -0500 | [diff] [blame] | 285 | size := utf8.EncodeRune(b[n:], r) |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 286 | nbytes, err := buf.WriteRune(r) |
| 287 | if err != nil { |
Rob Pike | 42cfe48f | 2010-12-06 14:38:25 -0500 | [diff] [blame] | 288 | t.Fatalf("WriteRune(%U) error: %s", r, err) |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 289 | } |
| 290 | if nbytes != size { |
Rob Pike | 42cfe48f | 2010-12-06 14:38:25 -0500 | [diff] [blame] | 291 | t.Fatalf("WriteRune(%U) expected %d, got %d", r, size, nbytes) |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 292 | } |
| 293 | n += size |
| 294 | } |
| 295 | b = b[0:n] |
| 296 | |
| 297 | // Check the resulting bytes |
| 298 | if !Equal(buf.Bytes(), b) { |
| 299 | t.Fatalf("incorrect result from WriteRune: %q not %q", buf.Bytes(), b) |
| 300 | } |
| 301 | |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 302 | p := make([]byte, utf8.UTFMax) |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 303 | // Read it back with ReadRune |
Russ Cox | 8f57181 | 2011-10-25 22:22:09 -0700 | [diff] [blame] | 304 | for r := rune(0); r < NRune; r++ { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 305 | size := utf8.EncodeRune(p, r) |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 306 | nr, nbytes, err := buf.ReadRune() |
| 307 | if nr != r || nbytes != size || err != nil { |
Rob Pike | 42cfe48f | 2010-12-06 14:38:25 -0500 | [diff] [blame] | 308 | t.Fatalf("ReadRune(%U) got %U,%d not %U,%d (err=%s)", r, nr, nbytes, r, size, err) |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 309 | } |
| 310 | } |
| 311 | |
| 312 | // Check that UnreadRune works |
| 313 | buf.Reset() |
| 314 | buf.Write(b) |
Russ Cox | 8f57181 | 2011-10-25 22:22:09 -0700 | [diff] [blame] | 315 | for r := rune(0); r < NRune; r++ { |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 316 | r1, size, _ := buf.ReadRune() |
| 317 | if err := buf.UnreadRune(); err != nil { |
Rob Pike | 42cfe48f | 2010-12-06 14:38:25 -0500 | [diff] [blame] | 318 | t.Fatalf("UnreadRune(%U) got error %q", r, err) |
Roger Peppe | 415545e | 2010-12-06 14:10:10 -0500 | [diff] [blame] | 319 | } |
| 320 | r2, nbytes, err := buf.ReadRune() |
| 321 | if r1 != r2 || r1 != r || nbytes != size || err != nil { |
Rob Pike | 42cfe48f | 2010-12-06 14:38:25 -0500 | [diff] [blame] | 322 | t.Fatalf("ReadRune(%U) after UnreadRune got %U,%d not %U,%d (err=%s)", r, r2, nbytes, r, size, err) |
Rob Pike | 0ac5ef7 | 2010-03-05 11:34:53 -0800 | [diff] [blame] | 323 | } |
| 324 | } |
| 325 | } |
Russ Cox | 78551a9 | 2010-04-26 10:02:01 -0700 | [diff] [blame] | 326 | |
Russ Cox | 78551a9 | 2010-04-26 10:02:01 -0700 | [diff] [blame] | 327 | func TestNext(t *testing.T) { |
| 328 | b := []byte{0, 1, 2, 3, 4} |
| 329 | tmp := make([]byte, 5) |
| 330 | for i := 0; i <= 5; i++ { |
| 331 | for j := i; j <= 5; j++ { |
| 332 | for k := 0; k <= 6; k++ { |
| 333 | // 0 <= i <= j <= 5; 0 <= k <= 6 |
| 334 | // Check that if we start with a buffer |
| 335 | // of length j at offset i and ask for |
| 336 | // Next(k), we get the right bytes. |
| 337 | buf := NewBuffer(b[0:j]) |
| 338 | n, _ := buf.Read(tmp[0:i]) |
| 339 | if n != i { |
| 340 | t.Fatalf("Read %d returned %d", i, n) |
| 341 | } |
| 342 | bb := buf.Next(k) |
| 343 | want := k |
| 344 | if want > j-i { |
| 345 | want = j - i |
| 346 | } |
| 347 | if len(bb) != want { |
| 348 | t.Fatalf("in %d,%d: len(Next(%d)) == %d", i, j, k, len(bb)) |
| 349 | } |
| 350 | for l, v := range bb { |
| 351 | if v != byte(l+i) { |
| 352 | t.Fatalf("in %d,%d: Next(%d)[%d] = %d, want %d", i, j, k, l, v, l+i) |
| 353 | } |
| 354 | } |
| 355 | } |
| 356 | } |
| 357 | } |
| 358 | } |
Evan Shaw | c9bf30c | 2011-01-27 14:00:31 -0800 | [diff] [blame] | 359 | |
| 360 | var readBytesTests = []struct { |
Evan Shaw | bbfad5f | 2011-02-11 12:39:18 -0500 | [diff] [blame] | 361 | buffer string |
Evan Shaw | c9bf30c | 2011-01-27 14:00:31 -0800 | [diff] [blame] | 362 | delim byte |
Evan Shaw | bbfad5f | 2011-02-11 12:39:18 -0500 | [diff] [blame] | 363 | expected []string |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame] | 364 | err error |
Evan Shaw | c9bf30c | 2011-01-27 14:00:31 -0800 | [diff] [blame] | 365 | }{ |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame] | 366 | {"", 0, []string{""}, io.EOF}, |
Evan Shaw | bbfad5f | 2011-02-11 12:39:18 -0500 | [diff] [blame] | 367 | {"a\x00", 0, []string{"a\x00"}, nil}, |
| 368 | {"abbbaaaba", 'b', []string{"ab", "b", "b", "aaab"}, nil}, |
| 369 | {"hello\x01world", 1, []string{"hello\x01"}, nil}, |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame] | 370 | {"foo\nbar", 0, []string{"foo\nbar"}, io.EOF}, |
Evan Shaw | bbfad5f | 2011-02-11 12:39:18 -0500 | [diff] [blame] | 371 | {"alpha\nbeta\ngamma\n", '\n', []string{"alpha\n", "beta\n", "gamma\n"}, nil}, |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame] | 372 | {"alpha\nbeta\ngamma", '\n', []string{"alpha\n", "beta\n", "gamma"}, io.EOF}, |
Evan Shaw | c9bf30c | 2011-01-27 14:00:31 -0800 | [diff] [blame] | 373 | } |
| 374 | |
| 375 | func TestReadBytes(t *testing.T) { |
| 376 | for _, test := range readBytesTests { |
Evan Shaw | bbfad5f | 2011-02-11 12:39:18 -0500 | [diff] [blame] | 377 | buf := NewBufferString(test.buffer) |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame] | 378 | var err error |
Evan Shaw | bbfad5f | 2011-02-11 12:39:18 -0500 | [diff] [blame] | 379 | for _, expected := range test.expected { |
| 380 | var bytes []byte |
| 381 | bytes, err = buf.ReadBytes(test.delim) |
| 382 | if string(bytes) != expected { |
| 383 | t.Errorf("expected %q, got %q", expected, bytes) |
| 384 | } |
| 385 | if err != nil { |
| 386 | break |
| 387 | } |
| 388 | } |
| 389 | if err != test.err { |
| 390 | t.Errorf("expected error %v, got %v", test.err, err) |
Evan Shaw | c9bf30c | 2011-01-27 14:00:31 -0800 | [diff] [blame] | 391 | } |
| 392 | } |
| 393 | } |
Rob Pike | 6a88f1c | 2011-12-26 23:49:24 -0800 | [diff] [blame] | 394 | |
Rémy Oudompheng | b1c4a8e | 2012-12-03 14:04:18 +0100 | [diff] [blame] | 395 | func TestReadString(t *testing.T) { |
| 396 | for _, test := range readBytesTests { |
| 397 | buf := NewBufferString(test.buffer) |
| 398 | var err error |
| 399 | for _, expected := range test.expected { |
| 400 | var s string |
| 401 | s, err = buf.ReadString(test.delim) |
| 402 | if s != expected { |
| 403 | t.Errorf("expected %q, got %q", expected, s) |
| 404 | } |
| 405 | if err != nil { |
| 406 | break |
| 407 | } |
| 408 | } |
| 409 | if err != test.err { |
| 410 | t.Errorf("expected error %v, got %v", test.err, err) |
| 411 | } |
| 412 | } |
| 413 | } |
| 414 | |
| 415 | func BenchmarkReadString(b *testing.B) { |
| 416 | const n = 32 << 10 |
| 417 | |
| 418 | data := make([]byte, n) |
| 419 | data[n-1] = 'x' |
| 420 | b.SetBytes(int64(n)) |
| 421 | for i := 0; i < b.N; i++ { |
| 422 | buf := NewBuffer(data) |
| 423 | _, err := buf.ReadString('x') |
| 424 | if err != nil { |
| 425 | b.Fatal(err) |
| 426 | } |
| 427 | } |
| 428 | } |
| 429 | |
Rob Pike | 1255a63 | 2012-07-12 20:52:19 -0700 | [diff] [blame] | 430 | func TestGrow(t *testing.T) { |
| 431 | x := []byte{'x'} |
| 432 | y := []byte{'y'} |
| 433 | tmp := make([]byte, 72) |
| 434 | for _, startLen := range []int{0, 100, 1000, 10000, 100000} { |
| 435 | xBytes := Repeat(x, startLen) |
| 436 | for _, growLen := range []int{0, 100, 1000, 10000, 100000} { |
| 437 | buf := NewBuffer(xBytes) |
| 438 | // If we read, this affects buf.off, which is good to test. |
| 439 | readBytes, _ := buf.Read(tmp) |
| 440 | buf.Grow(growLen) |
| 441 | yBytes := Repeat(y, growLen) |
| 442 | // Check no allocation occurs in write, as long as we're single-threaded. |
| 443 | var m1, m2 runtime.MemStats |
| 444 | runtime.ReadMemStats(&m1) |
| 445 | buf.Write(yBytes) |
| 446 | runtime.ReadMemStats(&m2) |
| 447 | if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs { |
| 448 | t.Errorf("allocation occurred during write") |
| 449 | } |
| 450 | // Check that buffer has correct data. |
| 451 | if !Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) { |
| 452 | t.Errorf("bad initial data at %d %d", startLen, growLen) |
| 453 | } |
| 454 | if !Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) { |
| 455 | t.Errorf("bad written data at %d %d", startLen, growLen) |
| 456 | } |
| 457 | } |
| 458 | } |
| 459 | } |
| 460 | |
Rob Pike | 6a88f1c | 2011-12-26 23:49:24 -0800 | [diff] [blame] | 461 | // Was a bug: used to give EOF reading empty slice at EOF. |
| 462 | func TestReadEmptyAtEOF(t *testing.T) { |
| 463 | b := new(Buffer) |
| 464 | slice := make([]byte, 0) |
| 465 | n, err := b.Read(slice) |
| 466 | if err != nil { |
| 467 | t.Errorf("read error: %v", err) |
| 468 | } |
| 469 | if n != 0 { |
| 470 | t.Errorf("wrong count; got %d want 0", n) |
| 471 | } |
| 472 | } |
Stéphane Travostino | 53e342f | 2013-01-11 17:02:21 +1100 | [diff] [blame] | 473 | |
| 474 | func TestUnreadByte(t *testing.T) { |
| 475 | b := new(Buffer) |
| 476 | b.WriteString("abcdefghijklmnopqrstuvwxyz") |
| 477 | |
| 478 | _, err := b.ReadBytes('m') |
| 479 | if err != nil { |
| 480 | t.Fatalf("ReadBytes: %v", err) |
| 481 | } |
| 482 | |
| 483 | err = b.UnreadByte() |
| 484 | if err != nil { |
| 485 | t.Fatalf("UnreadByte: %v", err) |
| 486 | } |
| 487 | c, err := b.ReadByte() |
| 488 | if err != nil { |
| 489 | t.Fatalf("ReadByte: %v", err) |
| 490 | } |
| 491 | if c != 'm' { |
| 492 | t.Errorf("ReadByte = %q; want %q", c, 'm') |
| 493 | } |
| 494 | } |
Brad Fitzpatrick | 994f596 | 2013-03-29 12:39:19 -0700 | [diff] [blame] | 495 | |
| 496 | // Tests that we occasionally compact. Issue 5154. |
| 497 | func TestBufferGrowth(t *testing.T) { |
| 498 | var b Buffer |
| 499 | buf := make([]byte, 1024) |
| 500 | b.Write(buf[0:1]) |
| 501 | var cap0 int |
| 502 | for i := 0; i < 5<<10; i++ { |
| 503 | b.Write(buf) |
| 504 | b.Read(buf) |
| 505 | if i == 0 { |
| 506 | cap0 = b.Cap() |
| 507 | } |
| 508 | } |
| 509 | cap1 := b.Cap() |
Brad Fitzpatrick | 43e38d5 | 2013-03-29 13:49:14 -0700 | [diff] [blame] | 510 | // (*Buffer).grow allows for 2x capacity slop before sliding, |
| 511 | // so set our error threshold at 3x. |
| 512 | if cap1 > cap0*3 { |
| 513 | t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0) |
Brad Fitzpatrick | 994f596 | 2013-03-29 12:39:19 -0700 | [diff] [blame] | 514 | } |
| 515 | } |
| 516 | |
| 517 | // From Issue 5154. |
| 518 | func BenchmarkBufferNotEmptyWriteRead(b *testing.B) { |
| 519 | buf := make([]byte, 1024) |
| 520 | for i := 0; i < b.N; i++ { |
| 521 | var b Buffer |
| 522 | b.Write(buf[0:1]) |
| 523 | for i := 0; i < 5<<10; i++ { |
| 524 | b.Write(buf) |
| 525 | b.Read(buf) |
| 526 | } |
| 527 | } |
| 528 | } |
Robert Obryk | 461e7b7 | 2013-03-29 14:17:09 -0700 | [diff] [blame] | 529 | |
| 530 | // Check that we don't compact too often. From Issue 5154. |
| 531 | func BenchmarkBufferFullSmallReads(b *testing.B) { |
| 532 | buf := make([]byte, 1024) |
| 533 | for i := 0; i < b.N; i++ { |
| 534 | var b Buffer |
| 535 | b.Write(buf) |
| 536 | for b.Len()+20 < b.Cap() { |
| 537 | b.Write(buf[:10]) |
| 538 | } |
| 539 | for i := 0; i < 5<<10; i++ { |
| 540 | b.Read(buf[:1]) |
| 541 | b.Write(buf[:1]) |
| 542 | } |
| 543 | } |
| 544 | } |