| 1 |
747 |
jeremybenn |
// 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 bufio_test
|
| 6 |
|
|
|
| 7 |
|
|
import (
|
| 8 |
|
|
. "bufio"
|
| 9 |
|
|
"bytes"
|
| 10 |
|
|
"fmt"
|
| 11 |
|
|
"io"
|
| 12 |
|
|
"io/ioutil"
|
| 13 |
|
|
"strings"
|
| 14 |
|
|
"testing"
|
| 15 |
|
|
"testing/iotest"
|
| 16 |
|
|
"unicode/utf8"
|
| 17 |
|
|
)
|
| 18 |
|
|
|
| 19 |
|
|
// Reads from a reader and rot13s the result.
|
| 20 |
|
|
type rot13Reader struct {
|
| 21 |
|
|
r io.Reader
|
| 22 |
|
|
}
|
| 23 |
|
|
|
| 24 |
|
|
func newRot13Reader(r io.Reader) *rot13Reader {
|
| 25 |
|
|
r13 := new(rot13Reader)
|
| 26 |
|
|
r13.r = r
|
| 27 |
|
|
return r13
|
| 28 |
|
|
}
|
| 29 |
|
|
|
| 30 |
|
|
func (r13 *rot13Reader) Read(p []byte) (int, error) {
|
| 31 |
|
|
n, e := r13.r.Read(p)
|
| 32 |
|
|
if e != nil {
|
| 33 |
|
|
return n, e
|
| 34 |
|
|
}
|
| 35 |
|
|
for i := 0; i < n; i++ {
|
| 36 |
|
|
c := p[i] | 0x20 // lowercase byte
|
| 37 |
|
|
if 'a' <= c && c <= 'm' {
|
| 38 |
|
|
p[i] += 13
|
| 39 |
|
|
} else if 'n' <= c && c <= 'z' {
|
| 40 |
|
|
p[i] -= 13
|
| 41 |
|
|
}
|
| 42 |
|
|
}
|
| 43 |
|
|
return n, nil
|
| 44 |
|
|
}
|
| 45 |
|
|
|
| 46 |
|
|
// Call ReadByte to accumulate the text of a file
|
| 47 |
|
|
func readBytes(buf *Reader) string {
|
| 48 |
|
|
var b [1000]byte
|
| 49 |
|
|
nb := 0
|
| 50 |
|
|
for {
|
| 51 |
|
|
c, e := buf.ReadByte()
|
| 52 |
|
|
if e == io.EOF {
|
| 53 |
|
|
break
|
| 54 |
|
|
}
|
| 55 |
|
|
if e == nil {
|
| 56 |
|
|
b[nb] = c
|
| 57 |
|
|
nb++
|
| 58 |
|
|
} else if e != iotest.ErrTimeout {
|
| 59 |
|
|
panic("Data: " + e.Error())
|
| 60 |
|
|
}
|
| 61 |
|
|
}
|
| 62 |
|
|
return string(b[0:nb])
|
| 63 |
|
|
}
|
| 64 |
|
|
|
| 65 |
|
|
func TestReaderSimple(t *testing.T) {
|
| 66 |
|
|
data := "hello world"
|
| 67 |
|
|
b := NewReader(bytes.NewBufferString(data))
|
| 68 |
|
|
if s := readBytes(b); s != "hello world" {
|
| 69 |
|
|
t.Errorf("simple hello world test failed: got %q", s)
|
| 70 |
|
|
}
|
| 71 |
|
|
|
| 72 |
|
|
b = NewReader(newRot13Reader(bytes.NewBufferString(data)))
|
| 73 |
|
|
if s := readBytes(b); s != "uryyb jbeyq" {
|
| 74 |
|
|
t.Errorf("rot13 hello world test failed: got %q", s)
|
| 75 |
|
|
}
|
| 76 |
|
|
}
|
| 77 |
|
|
|
| 78 |
|
|
type readMaker struct {
|
| 79 |
|
|
name string
|
| 80 |
|
|
fn func(io.Reader) io.Reader
|
| 81 |
|
|
}
|
| 82 |
|
|
|
| 83 |
|
|
var readMakers = []readMaker{
|
| 84 |
|
|
{"full", func(r io.Reader) io.Reader { return r }},
|
| 85 |
|
|
{"byte", iotest.OneByteReader},
|
| 86 |
|
|
{"half", iotest.HalfReader},
|
| 87 |
|
|
{"data+err", iotest.DataErrReader},
|
| 88 |
|
|
{"timeout", iotest.TimeoutReader},
|
| 89 |
|
|
}
|
| 90 |
|
|
|
| 91 |
|
|
// Call ReadString (which ends up calling everything else)
|
| 92 |
|
|
// to accumulate the text of a file.
|
| 93 |
|
|
func readLines(b *Reader) string {
|
| 94 |
|
|
s := ""
|
| 95 |
|
|
for {
|
| 96 |
|
|
s1, e := b.ReadString('\n')
|
| 97 |
|
|
if e == io.EOF {
|
| 98 |
|
|
break
|
| 99 |
|
|
}
|
| 100 |
|
|
if e != nil && e != iotest.ErrTimeout {
|
| 101 |
|
|
panic("GetLines: " + e.Error())
|
| 102 |
|
|
}
|
| 103 |
|
|
s += s1
|
| 104 |
|
|
}
|
| 105 |
|
|
return s
|
| 106 |
|
|
}
|
| 107 |
|
|
|
| 108 |
|
|
// Call Read to accumulate the text of a file
|
| 109 |
|
|
func reads(buf *Reader, m int) string {
|
| 110 |
|
|
var b [1000]byte
|
| 111 |
|
|
nb := 0
|
| 112 |
|
|
for {
|
| 113 |
|
|
n, e := buf.Read(b[nb : nb+m])
|
| 114 |
|
|
nb += n
|
| 115 |
|
|
if e == io.EOF {
|
| 116 |
|
|
break
|
| 117 |
|
|
}
|
| 118 |
|
|
}
|
| 119 |
|
|
return string(b[0:nb])
|
| 120 |
|
|
}
|
| 121 |
|
|
|
| 122 |
|
|
type bufReader struct {
|
| 123 |
|
|
name string
|
| 124 |
|
|
fn func(*Reader) string
|
| 125 |
|
|
}
|
| 126 |
|
|
|
| 127 |
|
|
var bufreaders = []bufReader{
|
| 128 |
|
|
{"1", func(b *Reader) string { return reads(b, 1) }},
|
| 129 |
|
|
{"2", func(b *Reader) string { return reads(b, 2) }},
|
| 130 |
|
|
{"3", func(b *Reader) string { return reads(b, 3) }},
|
| 131 |
|
|
{"4", func(b *Reader) string { return reads(b, 4) }},
|
| 132 |
|
|
{"5", func(b *Reader) string { return reads(b, 5) }},
|
| 133 |
|
|
{"7", func(b *Reader) string { return reads(b, 7) }},
|
| 134 |
|
|
{"bytes", readBytes},
|
| 135 |
|
|
{"lines", readLines},
|
| 136 |
|
|
}
|
| 137 |
|
|
|
| 138 |
|
|
const minReadBufferSize = 16
|
| 139 |
|
|
|
| 140 |
|
|
var bufsizes = []int{
|
| 141 |
|
|
minReadBufferSize, 23, 32, 46, 64, 93, 128, 1024, 4096,
|
| 142 |
|
|
}
|
| 143 |
|
|
|
| 144 |
|
|
func TestReader(t *testing.T) {
|
| 145 |
|
|
var texts [31]string
|
| 146 |
|
|
str := ""
|
| 147 |
|
|
all := ""
|
| 148 |
|
|
for i := 0; i < len(texts)-1; i++ {
|
| 149 |
|
|
texts[i] = str + "\n"
|
| 150 |
|
|
all += texts[i]
|
| 151 |
|
|
str += string(i%26 + 'a')
|
| 152 |
|
|
}
|
| 153 |
|
|
texts[len(texts)-1] = all
|
| 154 |
|
|
|
| 155 |
|
|
for h := 0; h < len(texts); h++ {
|
| 156 |
|
|
text := texts[h]
|
| 157 |
|
|
for i := 0; i < len(readMakers); i++ {
|
| 158 |
|
|
for j := 0; j < len(bufreaders); j++ {
|
| 159 |
|
|
for k := 0; k < len(bufsizes); k++ {
|
| 160 |
|
|
readmaker := readMakers[i]
|
| 161 |
|
|
bufreader := bufreaders[j]
|
| 162 |
|
|
bufsize := bufsizes[k]
|
| 163 |
|
|
read := readmaker.fn(bytes.NewBufferString(text))
|
| 164 |
|
|
buf := NewReaderSize(read, bufsize)
|
| 165 |
|
|
s := bufreader.fn(buf)
|
| 166 |
|
|
if s != text {
|
| 167 |
|
|
t.Errorf("reader=%s fn=%s bufsize=%d want=%q got=%q",
|
| 168 |
|
|
readmaker.name, bufreader.name, bufsize, text, s)
|
| 169 |
|
|
}
|
| 170 |
|
|
}
|
| 171 |
|
|
}
|
| 172 |
|
|
}
|
| 173 |
|
|
}
|
| 174 |
|
|
}
|
| 175 |
|
|
|
| 176 |
|
|
// A StringReader delivers its data one string segment at a time via Read.
|
| 177 |
|
|
type StringReader struct {
|
| 178 |
|
|
data []string
|
| 179 |
|
|
step int
|
| 180 |
|
|
}
|
| 181 |
|
|
|
| 182 |
|
|
func (r *StringReader) Read(p []byte) (n int, err error) {
|
| 183 |
|
|
if r.step < len(r.data) {
|
| 184 |
|
|
s := r.data[r.step]
|
| 185 |
|
|
n = copy(p, s)
|
| 186 |
|
|
r.step++
|
| 187 |
|
|
} else {
|
| 188 |
|
|
err = io.EOF
|
| 189 |
|
|
}
|
| 190 |
|
|
return
|
| 191 |
|
|
}
|
| 192 |
|
|
|
| 193 |
|
|
func readRuneSegments(t *testing.T, segments []string) {
|
| 194 |
|
|
got := ""
|
| 195 |
|
|
want := strings.Join(segments, "")
|
| 196 |
|
|
r := NewReader(&StringReader{data: segments})
|
| 197 |
|
|
for {
|
| 198 |
|
|
r, _, err := r.ReadRune()
|
| 199 |
|
|
if err != nil {
|
| 200 |
|
|
if err != io.EOF {
|
| 201 |
|
|
return
|
| 202 |
|
|
}
|
| 203 |
|
|
break
|
| 204 |
|
|
}
|
| 205 |
|
|
got += string(r)
|
| 206 |
|
|
}
|
| 207 |
|
|
if got != want {
|
| 208 |
|
|
t.Errorf("segments=%v got=%s want=%s", segments, got, want)
|
| 209 |
|
|
}
|
| 210 |
|
|
}
|
| 211 |
|
|
|
| 212 |
|
|
var segmentList = [][]string{
|
| 213 |
|
|
{},
|
| 214 |
|
|
{""},
|
| 215 |
|
|
{"日", "本語"},
|
| 216 |
|
|
{"\u65e5", "\u672c", "\u8a9e"},
|
| 217 |
|
|
{"\U000065e5", "\U0000672c", "\U00008a9e"},
|
| 218 |
|
|
{"\xe6", "\x97\xa5\xe6", "\x9c\xac\xe8\xaa\x9e"},
|
| 219 |
|
|
{"Hello", ", ", "World", "!"},
|
| 220 |
|
|
{"Hello", ", ", "", "World", "!"},
|
| 221 |
|
|
}
|
| 222 |
|
|
|
| 223 |
|
|
func TestReadRune(t *testing.T) {
|
| 224 |
|
|
for _, s := range segmentList {
|
| 225 |
|
|
readRuneSegments(t, s)
|
| 226 |
|
|
}
|
| 227 |
|
|
}
|
| 228 |
|
|
|
| 229 |
|
|
func TestUnreadRune(t *testing.T) {
|
| 230 |
|
|
got := ""
|
| 231 |
|
|
segments := []string{"Hello, world:", "日本語"}
|
| 232 |
|
|
data := strings.Join(segments, "")
|
| 233 |
|
|
r := NewReader(&StringReader{data: segments})
|
| 234 |
|
|
// Normal execution.
|
| 235 |
|
|
for {
|
| 236 |
|
|
r1, _, err := r.ReadRune()
|
| 237 |
|
|
if err != nil {
|
| 238 |
|
|
if err != io.EOF {
|
| 239 |
|
|
t.Error("unexpected EOF")
|
| 240 |
|
|
}
|
| 241 |
|
|
break
|
| 242 |
|
|
}
|
| 243 |
|
|
got += string(r1)
|
| 244 |
|
|
// Put it back and read it again
|
| 245 |
|
|
if err = r.UnreadRune(); err != nil {
|
| 246 |
|
|
t.Error("unexpected error on UnreadRune:", err)
|
| 247 |
|
|
}
|
| 248 |
|
|
r2, _, err := r.ReadRune()
|
| 249 |
|
|
if err != nil {
|
| 250 |
|
|
t.Error("unexpected error reading after unreading:", err)
|
| 251 |
|
|
}
|
| 252 |
|
|
if r1 != r2 {
|
| 253 |
|
|
t.Errorf("incorrect rune after unread: got %c wanted %c", r1, r2)
|
| 254 |
|
|
}
|
| 255 |
|
|
}
|
| 256 |
|
|
if got != data {
|
| 257 |
|
|
t.Errorf("want=%q got=%q", data, got)
|
| 258 |
|
|
}
|
| 259 |
|
|
}
|
| 260 |
|
|
|
| 261 |
|
|
// Test that UnreadRune fails if the preceding operation was not a ReadRune.
|
| 262 |
|
|
func TestUnreadRuneError(t *testing.T) {
|
| 263 |
|
|
buf := make([]byte, 3) // All runes in this test are 3 bytes long
|
| 264 |
|
|
r := NewReader(&StringReader{data: []string{"日本語日本語日本語"}})
|
| 265 |
|
|
if r.UnreadRune() == nil {
|
| 266 |
|
|
t.Error("expected error on UnreadRune from fresh buffer")
|
| 267 |
|
|
}
|
| 268 |
|
|
_, _, err := r.ReadRune()
|
| 269 |
|
|
if err != nil {
|
| 270 |
|
|
t.Error("unexpected error on ReadRune (1):", err)
|
| 271 |
|
|
}
|
| 272 |
|
|
if err = r.UnreadRune(); err != nil {
|
| 273 |
|
|
t.Error("unexpected error on UnreadRune (1):", err)
|
| 274 |
|
|
}
|
| 275 |
|
|
if r.UnreadRune() == nil {
|
| 276 |
|
|
t.Error("expected error after UnreadRune (1)")
|
| 277 |
|
|
}
|
| 278 |
|
|
// Test error after Read.
|
| 279 |
|
|
_, _, err = r.ReadRune() // reset state
|
| 280 |
|
|
if err != nil {
|
| 281 |
|
|
t.Error("unexpected error on ReadRune (2):", err)
|
| 282 |
|
|
}
|
| 283 |
|
|
_, err = r.Read(buf)
|
| 284 |
|
|
if err != nil {
|
| 285 |
|
|
t.Error("unexpected error on Read (2):", err)
|
| 286 |
|
|
}
|
| 287 |
|
|
if r.UnreadRune() == nil {
|
| 288 |
|
|
t.Error("expected error after Read (2)")
|
| 289 |
|
|
}
|
| 290 |
|
|
// Test error after ReadByte.
|
| 291 |
|
|
_, _, err = r.ReadRune() // reset state
|
| 292 |
|
|
if err != nil {
|
| 293 |
|
|
t.Error("unexpected error on ReadRune (2):", err)
|
| 294 |
|
|
}
|
| 295 |
|
|
for _ = range buf {
|
| 296 |
|
|
_, err = r.ReadByte()
|
| 297 |
|
|
if err != nil {
|
| 298 |
|
|
t.Error("unexpected error on ReadByte (2):", err)
|
| 299 |
|
|
}
|
| 300 |
|
|
}
|
| 301 |
|
|
if r.UnreadRune() == nil {
|
| 302 |
|
|
t.Error("expected error after ReadByte")
|
| 303 |
|
|
}
|
| 304 |
|
|
// Test error after UnreadByte.
|
| 305 |
|
|
_, _, err = r.ReadRune() // reset state
|
| 306 |
|
|
if err != nil {
|
| 307 |
|
|
t.Error("unexpected error on ReadRune (3):", err)
|
| 308 |
|
|
}
|
| 309 |
|
|
_, err = r.ReadByte()
|
| 310 |
|
|
if err != nil {
|
| 311 |
|
|
t.Error("unexpected error on ReadByte (3):", err)
|
| 312 |
|
|
}
|
| 313 |
|
|
err = r.UnreadByte()
|
| 314 |
|
|
if err != nil {
|
| 315 |
|
|
t.Error("unexpected error on UnreadByte (3):", err)
|
| 316 |
|
|
}
|
| 317 |
|
|
if r.UnreadRune() == nil {
|
| 318 |
|
|
t.Error("expected error after UnreadByte (3)")
|
| 319 |
|
|
}
|
| 320 |
|
|
}
|
| 321 |
|
|
|
| 322 |
|
|
func TestUnreadRuneAtEOF(t *testing.T) {
|
| 323 |
|
|
// UnreadRune/ReadRune should error at EOF (was a bug; used to panic)
|
| 324 |
|
|
r := NewReader(strings.NewReader("x"))
|
| 325 |
|
|
r.ReadRune()
|
| 326 |
|
|
r.ReadRune()
|
| 327 |
|
|
r.UnreadRune()
|
| 328 |
|
|
_, _, err := r.ReadRune()
|
| 329 |
|
|
if err == nil {
|
| 330 |
|
|
t.Error("expected error at EOF")
|
| 331 |
|
|
} else if err != io.EOF {
|
| 332 |
|
|
t.Error("expected EOF; got", err)
|
| 333 |
|
|
}
|
| 334 |
|
|
}
|
| 335 |
|
|
|
| 336 |
|
|
func TestReadWriteRune(t *testing.T) {
|
| 337 |
|
|
const NRune = 1000
|
| 338 |
|
|
byteBuf := new(bytes.Buffer)
|
| 339 |
|
|
w := NewWriter(byteBuf)
|
| 340 |
|
|
// Write the runes out using WriteRune
|
| 341 |
|
|
buf := make([]byte, utf8.UTFMax)
|
| 342 |
|
|
for r := rune(0); r < NRune; r++ {
|
| 343 |
|
|
size := utf8.EncodeRune(buf, r)
|
| 344 |
|
|
nbytes, err := w.WriteRune(r)
|
| 345 |
|
|
if err != nil {
|
| 346 |
|
|
t.Fatalf("WriteRune(0x%x) error: %s", r, err)
|
| 347 |
|
|
}
|
| 348 |
|
|
if nbytes != size {
|
| 349 |
|
|
t.Fatalf("WriteRune(0x%x) expected %d, got %d", r, size, nbytes)
|
| 350 |
|
|
}
|
| 351 |
|
|
}
|
| 352 |
|
|
w.Flush()
|
| 353 |
|
|
|
| 354 |
|
|
r := NewReader(byteBuf)
|
| 355 |
|
|
// Read them back with ReadRune
|
| 356 |
|
|
for r1 := rune(0); r1 < NRune; r1++ {
|
| 357 |
|
|
size := utf8.EncodeRune(buf, r1)
|
| 358 |
|
|
nr, nbytes, err := r.ReadRune()
|
| 359 |
|
|
if nr != r1 || nbytes != size || err != nil {
|
| 360 |
|
|
t.Fatalf("ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)", r1, nr, nbytes, r1, size, err)
|
| 361 |
|
|
}
|
| 362 |
|
|
}
|
| 363 |
|
|
}
|
| 364 |
|
|
|
| 365 |
|
|
func TestWriter(t *testing.T) {
|
| 366 |
|
|
var data [8192]byte
|
| 367 |
|
|
|
| 368 |
|
|
for i := 0; i < len(data); i++ {
|
| 369 |
|
|
data[i] = byte(' ' + i%('~'-' '))
|
| 370 |
|
|
}
|
| 371 |
|
|
w := new(bytes.Buffer)
|
| 372 |
|
|
for i := 0; i < len(bufsizes); i++ {
|
| 373 |
|
|
for j := 0; j < len(bufsizes); j++ {
|
| 374 |
|
|
nwrite := bufsizes[i]
|
| 375 |
|
|
bs := bufsizes[j]
|
| 376 |
|
|
|
| 377 |
|
|
// Write nwrite bytes using buffer size bs.
|
| 378 |
|
|
// Check that the right amount makes it out
|
| 379 |
|
|
// and that the data is correct.
|
| 380 |
|
|
|
| 381 |
|
|
w.Reset()
|
| 382 |
|
|
buf := NewWriterSize(w, bs)
|
| 383 |
|
|
context := fmt.Sprintf("nwrite=%d bufsize=%d", nwrite, bs)
|
| 384 |
|
|
n, e1 := buf.Write(data[0:nwrite])
|
| 385 |
|
|
if e1 != nil || n != nwrite {
|
| 386 |
|
|
t.Errorf("%s: buf.Write %d = %d, %v", context, nwrite, n, e1)
|
| 387 |
|
|
continue
|
| 388 |
|
|
}
|
| 389 |
|
|
if e := buf.Flush(); e != nil {
|
| 390 |
|
|
t.Errorf("%s: buf.Flush = %v", context, e)
|
| 391 |
|
|
}
|
| 392 |
|
|
|
| 393 |
|
|
written := w.Bytes()
|
| 394 |
|
|
if len(written) != nwrite {
|
| 395 |
|
|
t.Errorf("%s: %d bytes written", context, len(written))
|
| 396 |
|
|
}
|
| 397 |
|
|
for l := 0; l < len(written); l++ {
|
| 398 |
|
|
if written[i] != data[i] {
|
| 399 |
|
|
t.Errorf("wrong bytes written")
|
| 400 |
|
|
t.Errorf("want=%q", data[0:len(written)])
|
| 401 |
|
|
t.Errorf("have=%q", written)
|
| 402 |
|
|
}
|
| 403 |
|
|
}
|
| 404 |
|
|
}
|
| 405 |
|
|
}
|
| 406 |
|
|
}
|
| 407 |
|
|
|
| 408 |
|
|
// Check that write errors are returned properly.
|
| 409 |
|
|
|
| 410 |
|
|
type errorWriterTest struct {
|
| 411 |
|
|
n, m int
|
| 412 |
|
|
err error
|
| 413 |
|
|
expect error
|
| 414 |
|
|
}
|
| 415 |
|
|
|
| 416 |
|
|
func (w errorWriterTest) Write(p []byte) (int, error) {
|
| 417 |
|
|
return len(p) * w.n / w.m, w.err
|
| 418 |
|
|
}
|
| 419 |
|
|
|
| 420 |
|
|
var errorWriterTests = []errorWriterTest{
|
| 421 |
|
|
{0, 1, nil, io.ErrShortWrite},
|
| 422 |
|
|
{1, 2, nil, io.ErrShortWrite},
|
| 423 |
|
|
{1, 1, nil, nil},
|
| 424 |
|
|
{0, 1, io.ErrClosedPipe, io.ErrClosedPipe},
|
| 425 |
|
|
{1, 2, io.ErrClosedPipe, io.ErrClosedPipe},
|
| 426 |
|
|
{1, 1, io.ErrClosedPipe, io.ErrClosedPipe},
|
| 427 |
|
|
}
|
| 428 |
|
|
|
| 429 |
|
|
func TestWriteErrors(t *testing.T) {
|
| 430 |
|
|
for _, w := range errorWriterTests {
|
| 431 |
|
|
buf := NewWriter(w)
|
| 432 |
|
|
_, e := buf.Write([]byte("hello world"))
|
| 433 |
|
|
if e != nil {
|
| 434 |
|
|
t.Errorf("Write hello to %v: %v", w, e)
|
| 435 |
|
|
continue
|
| 436 |
|
|
}
|
| 437 |
|
|
e = buf.Flush()
|
| 438 |
|
|
if e != w.expect {
|
| 439 |
|
|
t.Errorf("Flush %v: got %v, wanted %v", w, e, w.expect)
|
| 440 |
|
|
}
|
| 441 |
|
|
}
|
| 442 |
|
|
}
|
| 443 |
|
|
|
| 444 |
|
|
func TestNewReaderSizeIdempotent(t *testing.T) {
|
| 445 |
|
|
const BufSize = 1000
|
| 446 |
|
|
b := NewReaderSize(bytes.NewBufferString("hello world"), BufSize)
|
| 447 |
|
|
// Does it recognize itself?
|
| 448 |
|
|
b1 := NewReaderSize(b, BufSize)
|
| 449 |
|
|
if b1 != b {
|
| 450 |
|
|
t.Error("NewReaderSize did not detect underlying Reader")
|
| 451 |
|
|
}
|
| 452 |
|
|
// Does it wrap if existing buffer is too small?
|
| 453 |
|
|
b2 := NewReaderSize(b, 2*BufSize)
|
| 454 |
|
|
if b2 == b {
|
| 455 |
|
|
t.Error("NewReaderSize did not enlarge buffer")
|
| 456 |
|
|
}
|
| 457 |
|
|
}
|
| 458 |
|
|
|
| 459 |
|
|
func TestNewWriterSizeIdempotent(t *testing.T) {
|
| 460 |
|
|
const BufSize = 1000
|
| 461 |
|
|
b := NewWriterSize(new(bytes.Buffer), BufSize)
|
| 462 |
|
|
// Does it recognize itself?
|
| 463 |
|
|
b1 := NewWriterSize(b, BufSize)
|
| 464 |
|
|
if b1 != b {
|
| 465 |
|
|
t.Error("NewWriterSize did not detect underlying Writer")
|
| 466 |
|
|
}
|
| 467 |
|
|
// Does it wrap if existing buffer is too small?
|
| 468 |
|
|
b2 := NewWriterSize(b, 2*BufSize)
|
| 469 |
|
|
if b2 == b {
|
| 470 |
|
|
t.Error("NewWriterSize did not enlarge buffer")
|
| 471 |
|
|
}
|
| 472 |
|
|
}
|
| 473 |
|
|
|
| 474 |
|
|
func TestWriteString(t *testing.T) {
|
| 475 |
|
|
const BufSize = 8
|
| 476 |
|
|
buf := new(bytes.Buffer)
|
| 477 |
|
|
b := NewWriterSize(buf, BufSize)
|
| 478 |
|
|
b.WriteString("0") // easy
|
| 479 |
|
|
b.WriteString("123456") // still easy
|
| 480 |
|
|
b.WriteString("7890") // easy after flush
|
| 481 |
|
|
b.WriteString("abcdefghijklmnopqrstuvwxy") // hard
|
| 482 |
|
|
b.WriteString("z")
|
| 483 |
|
|
if err := b.Flush(); err != nil {
|
| 484 |
|
|
t.Error("WriteString", err)
|
| 485 |
|
|
}
|
| 486 |
|
|
s := "01234567890abcdefghijklmnopqrstuvwxyz"
|
| 487 |
|
|
if string(buf.Bytes()) != s {
|
| 488 |
|
|
t.Errorf("WriteString wants %q gets %q", s, string(buf.Bytes()))
|
| 489 |
|
|
}
|
| 490 |
|
|
}
|
| 491 |
|
|
|
| 492 |
|
|
func TestBufferFull(t *testing.T) {
|
| 493 |
|
|
const longString = "And now, hello, world! It is the time for all good men to come to the aid of their party"
|
| 494 |
|
|
buf := NewReaderSize(strings.NewReader(longString), minReadBufferSize)
|
| 495 |
|
|
line, err := buf.ReadSlice('!')
|
| 496 |
|
|
if string(line) != "And now, hello, " || err != ErrBufferFull {
|
| 497 |
|
|
t.Errorf("first ReadSlice(,) = %q, %v", line, err)
|
| 498 |
|
|
}
|
| 499 |
|
|
line, err = buf.ReadSlice('!')
|
| 500 |
|
|
if string(line) != "world!" || err != nil {
|
| 501 |
|
|
t.Errorf("second ReadSlice(,) = %q, %v", line, err)
|
| 502 |
|
|
}
|
| 503 |
|
|
}
|
| 504 |
|
|
|
| 505 |
|
|
func TestPeek(t *testing.T) {
|
| 506 |
|
|
p := make([]byte, 10)
|
| 507 |
|
|
// string is 16 (minReadBufferSize) long.
|
| 508 |
|
|
buf := NewReaderSize(strings.NewReader("abcdefghijklmnop"), minReadBufferSize)
|
| 509 |
|
|
if s, err := buf.Peek(1); string(s) != "a" || err != nil {
|
| 510 |
|
|
t.Fatalf("want %q got %q, err=%v", "a", string(s), err)
|
| 511 |
|
|
}
|
| 512 |
|
|
if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {
|
| 513 |
|
|
t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err)
|
| 514 |
|
|
}
|
| 515 |
|
|
if _, err := buf.Peek(32); err != ErrBufferFull {
|
| 516 |
|
|
t.Fatalf("want ErrBufFull got %v", err)
|
| 517 |
|
|
}
|
| 518 |
|
|
if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil {
|
| 519 |
|
|
t.Fatalf("want %q got %q, err=%v", "abc", string(p[0:3]), err)
|
| 520 |
|
|
}
|
| 521 |
|
|
if s, err := buf.Peek(1); string(s) != "d" || err != nil {
|
| 522 |
|
|
t.Fatalf("want %q got %q, err=%v", "d", string(s), err)
|
| 523 |
|
|
}
|
| 524 |
|
|
if s, err := buf.Peek(2); string(s) != "de" || err != nil {
|
| 525 |
|
|
t.Fatalf("want %q got %q, err=%v", "de", string(s), err)
|
| 526 |
|
|
}
|
| 527 |
|
|
if _, err := buf.Read(p[0:3]); string(p[0:3]) != "def" || err != nil {
|
| 528 |
|
|
t.Fatalf("want %q got %q, err=%v", "def", string(p[0:3]), err)
|
| 529 |
|
|
}
|
| 530 |
|
|
if s, err := buf.Peek(4); string(s) != "ghij" || err != nil {
|
| 531 |
|
|
t.Fatalf("want %q got %q, err=%v", "ghij", string(s), err)
|
| 532 |
|
|
}
|
| 533 |
|
|
if _, err := buf.Read(p[0:]); string(p[0:]) != "ghijklmnop" || err != nil {
|
| 534 |
|
|
t.Fatalf("want %q got %q, err=%v", "ghijklmnop", string(p[0:minReadBufferSize]), err)
|
| 535 |
|
|
}
|
| 536 |
|
|
if s, err := buf.Peek(0); string(s) != "" || err != nil {
|
| 537 |
|
|
t.Fatalf("want %q got %q, err=%v", "", string(s), err)
|
| 538 |
|
|
}
|
| 539 |
|
|
if _, err := buf.Peek(1); err != io.EOF {
|
| 540 |
|
|
t.Fatalf("want EOF got %v", err)
|
| 541 |
|
|
}
|
| 542 |
|
|
}
|
| 543 |
|
|
|
| 544 |
|
|
func TestPeekThenUnreadRune(t *testing.T) {
|
| 545 |
|
|
// This sequence used to cause a crash.
|
| 546 |
|
|
r := NewReader(strings.NewReader("x"))
|
| 547 |
|
|
r.ReadRune()
|
| 548 |
|
|
r.Peek(1)
|
| 549 |
|
|
r.UnreadRune()
|
| 550 |
|
|
r.ReadRune() // Used to panic here
|
| 551 |
|
|
}
|
| 552 |
|
|
|
| 553 |
|
|
var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy")
|
| 554 |
|
|
var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy")
|
| 555 |
|
|
var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n")
|
| 556 |
|
|
|
| 557 |
|
|
// TestReader wraps a []byte and returns reads of a specific length.
|
| 558 |
|
|
type testReader struct {
|
| 559 |
|
|
data []byte
|
| 560 |
|
|
stride int
|
| 561 |
|
|
}
|
| 562 |
|
|
|
| 563 |
|
|
func (t *testReader) Read(buf []byte) (n int, err error) {
|
| 564 |
|
|
n = t.stride
|
| 565 |
|
|
if n > len(t.data) {
|
| 566 |
|
|
n = len(t.data)
|
| 567 |
|
|
}
|
| 568 |
|
|
if n > len(buf) {
|
| 569 |
|
|
n = len(buf)
|
| 570 |
|
|
}
|
| 571 |
|
|
copy(buf, t.data)
|
| 572 |
|
|
t.data = t.data[n:]
|
| 573 |
|
|
if len(t.data) == 0 {
|
| 574 |
|
|
err = io.EOF
|
| 575 |
|
|
}
|
| 576 |
|
|
return
|
| 577 |
|
|
}
|
| 578 |
|
|
|
| 579 |
|
|
func testReadLine(t *testing.T, input []byte) {
|
| 580 |
|
|
//for stride := 1; stride < len(input); stride++ {
|
| 581 |
|
|
for stride := 1; stride < 2; stride++ {
|
| 582 |
|
|
done := 0
|
| 583 |
|
|
reader := testReader{input, stride}
|
| 584 |
|
|
l := NewReaderSize(&reader, len(input)+1)
|
| 585 |
|
|
for {
|
| 586 |
|
|
line, isPrefix, err := l.ReadLine()
|
| 587 |
|
|
if len(line) > 0 && err != nil {
|
| 588 |
|
|
t.Errorf("ReadLine returned both data and error: %s", err)
|
| 589 |
|
|
}
|
| 590 |
|
|
if isPrefix {
|
| 591 |
|
|
t.Errorf("ReadLine returned prefix")
|
| 592 |
|
|
}
|
| 593 |
|
|
if err != nil {
|
| 594 |
|
|
if err != io.EOF {
|
| 595 |
|
|
t.Fatalf("Got unknown error: %s", err)
|
| 596 |
|
|
}
|
| 597 |
|
|
break
|
| 598 |
|
|
}
|
| 599 |
|
|
if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) {
|
| 600 |
|
|
t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line)
|
| 601 |
|
|
}
|
| 602 |
|
|
done += len(line)
|
| 603 |
|
|
}
|
| 604 |
|
|
if done != len(testOutput) {
|
| 605 |
|
|
t.Errorf("ReadLine didn't return everything: got: %d, want: %d (stride: %d)", done, len(testOutput), stride)
|
| 606 |
|
|
}
|
| 607 |
|
|
}
|
| 608 |
|
|
}
|
| 609 |
|
|
|
| 610 |
|
|
func TestReadLine(t *testing.T) {
|
| 611 |
|
|
testReadLine(t, testInput)
|
| 612 |
|
|
testReadLine(t, testInputrn)
|
| 613 |
|
|
}
|
| 614 |
|
|
|
| 615 |
|
|
func TestLineTooLong(t *testing.T) {
|
| 616 |
|
|
data := make([]byte, 0)
|
| 617 |
|
|
for i := 0; i < minReadBufferSize*5/2; i++ {
|
| 618 |
|
|
data = append(data, '0'+byte(i%10))
|
| 619 |
|
|
}
|
| 620 |
|
|
buf := bytes.NewBuffer(data)
|
| 621 |
|
|
l := NewReaderSize(buf, minReadBufferSize)
|
| 622 |
|
|
line, isPrefix, err := l.ReadLine()
|
| 623 |
|
|
if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
|
| 624 |
|
|
t.Errorf("bad result for first line: got %q want %q %v", line, data[:minReadBufferSize], err)
|
| 625 |
|
|
}
|
| 626 |
|
|
data = data[len(line):]
|
| 627 |
|
|
line, isPrefix, err = l.ReadLine()
|
| 628 |
|
|
if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
|
| 629 |
|
|
t.Errorf("bad result for second line: got %q want %q %v", line, data[:minReadBufferSize], err)
|
| 630 |
|
|
}
|
| 631 |
|
|
data = data[len(line):]
|
| 632 |
|
|
line, isPrefix, err = l.ReadLine()
|
| 633 |
|
|
if isPrefix || !bytes.Equal(line, data[:minReadBufferSize/2]) || err != nil {
|
| 634 |
|
|
t.Errorf("bad result for third line: got %q want %q %v", line, data[:minReadBufferSize/2], err)
|
| 635 |
|
|
}
|
| 636 |
|
|
line, isPrefix, err = l.ReadLine()
|
| 637 |
|
|
if isPrefix || err == nil {
|
| 638 |
|
|
t.Errorf("expected no more lines: %x %s", line, err)
|
| 639 |
|
|
}
|
| 640 |
|
|
}
|
| 641 |
|
|
|
| 642 |
|
|
func TestReadAfterLines(t *testing.T) {
|
| 643 |
|
|
line1 := "this is line1"
|
| 644 |
|
|
restData := "this is line2\nthis is line 3\n"
|
| 645 |
|
|
inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData))
|
| 646 |
|
|
outbuf := new(bytes.Buffer)
|
| 647 |
|
|
maxLineLength := len(line1) + len(restData)/2
|
| 648 |
|
|
l := NewReaderSize(inbuf, maxLineLength)
|
| 649 |
|
|
line, isPrefix, err := l.ReadLine()
|
| 650 |
|
|
if isPrefix || err != nil || string(line) != line1 {
|
| 651 |
|
|
t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line))
|
| 652 |
|
|
}
|
| 653 |
|
|
n, err := io.Copy(outbuf, l)
|
| 654 |
|
|
if int(n) != len(restData) || err != nil {
|
| 655 |
|
|
t.Errorf("bad result for Read: n=%d err=%v", n, err)
|
| 656 |
|
|
}
|
| 657 |
|
|
if outbuf.String() != restData {
|
| 658 |
|
|
t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData)
|
| 659 |
|
|
}
|
| 660 |
|
|
}
|
| 661 |
|
|
|
| 662 |
|
|
func TestReadEmptyBuffer(t *testing.T) {
|
| 663 |
|
|
l := NewReaderSize(new(bytes.Buffer), minReadBufferSize)
|
| 664 |
|
|
line, isPrefix, err := l.ReadLine()
|
| 665 |
|
|
if err != io.EOF {
|
| 666 |
|
|
t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
|
| 667 |
|
|
}
|
| 668 |
|
|
}
|
| 669 |
|
|
|
| 670 |
|
|
func TestLinesAfterRead(t *testing.T) {
|
| 671 |
|
|
l := NewReaderSize(bytes.NewBuffer([]byte("foo")), minReadBufferSize)
|
| 672 |
|
|
_, err := ioutil.ReadAll(l)
|
| 673 |
|
|
if err != nil {
|
| 674 |
|
|
t.Error(err)
|
| 675 |
|
|
return
|
| 676 |
|
|
}
|
| 677 |
|
|
|
| 678 |
|
|
line, isPrefix, err := l.ReadLine()
|
| 679 |
|
|
if err != io.EOF {
|
| 680 |
|
|
t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
|
| 681 |
|
|
}
|
| 682 |
|
|
}
|
| 683 |
|
|
|
| 684 |
|
|
func TestReadLineNonNilLineOrError(t *testing.T) {
|
| 685 |
|
|
r := NewReader(strings.NewReader("line 1\n"))
|
| 686 |
|
|
for i := 0; i < 2; i++ {
|
| 687 |
|
|
l, _, err := r.ReadLine()
|
| 688 |
|
|
if l != nil && err != nil {
|
| 689 |
|
|
t.Fatalf("on line %d/2; ReadLine=%#v, %v; want non-nil line or Error, but not both",
|
| 690 |
|
|
i+1, l, err)
|
| 691 |
|
|
}
|
| 692 |
|
|
}
|
| 693 |
|
|
}
|
| 694 |
|
|
|
| 695 |
|
|
type readLineResult struct {
|
| 696 |
|
|
line []byte
|
| 697 |
|
|
isPrefix bool
|
| 698 |
|
|
err error
|
| 699 |
|
|
}
|
| 700 |
|
|
|
| 701 |
|
|
var readLineNewlinesTests = []struct {
|
| 702 |
|
|
input string
|
| 703 |
|
|
expect []readLineResult
|
| 704 |
|
|
}{
|
| 705 |
|
|
{"012345678901234\r\n012345678901234\r\n", []readLineResult{
|
| 706 |
|
|
{[]byte("012345678901234"), true, nil},
|
| 707 |
|
|
{nil, false, nil},
|
| 708 |
|
|
{[]byte("012345678901234"), true, nil},
|
| 709 |
|
|
{nil, false, nil},
|
| 710 |
|
|
{nil, false, io.EOF},
|
| 711 |
|
|
}},
|
| 712 |
|
|
{"0123456789012345\r012345678901234\r", []readLineResult{
|
| 713 |
|
|
{[]byte("0123456789012345"), true, nil},
|
| 714 |
|
|
{[]byte("\r012345678901234"), true, nil},
|
| 715 |
|
|
{[]byte("\r"), false, nil},
|
| 716 |
|
|
{nil, false, io.EOF},
|
| 717 |
|
|
}},
|
| 718 |
|
|
}
|
| 719 |
|
|
|
| 720 |
|
|
func TestReadLineNewlines(t *testing.T) {
|
| 721 |
|
|
for _, e := range readLineNewlinesTests {
|
| 722 |
|
|
testReadLineNewlines(t, e.input, e.expect)
|
| 723 |
|
|
}
|
| 724 |
|
|
}
|
| 725 |
|
|
|
| 726 |
|
|
func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) {
|
| 727 |
|
|
b := NewReaderSize(strings.NewReader(input), minReadBufferSize)
|
| 728 |
|
|
for i, e := range expect {
|
| 729 |
|
|
line, isPrefix, err := b.ReadLine()
|
| 730 |
|
|
if bytes.Compare(line, e.line) != 0 {
|
| 731 |
|
|
t.Errorf("%q call %d, line == %q, want %q", input, i, line, e.line)
|
| 732 |
|
|
return
|
| 733 |
|
|
}
|
| 734 |
|
|
if isPrefix != e.isPrefix {
|
| 735 |
|
|
t.Errorf("%q call %d, isPrefix == %v, want %v", input, i, isPrefix, e.isPrefix)
|
| 736 |
|
|
return
|
| 737 |
|
|
}
|
| 738 |
|
|
if err != e.err {
|
| 739 |
|
|
t.Errorf("%q call %d, err == %v, want %v", input, i, err, e.err)
|
| 740 |
|
|
return
|
| 741 |
|
|
}
|
| 742 |
|
|
}
|
| 743 |
|
|
}
|