blob: 49803009f96baaab9c50bd8af20d88c1b0f90464 [file] [log] [blame]
Russ Cox7c9e2c22008-09-12 16:42:53 -07001// 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
Rob Piked3c61fc2011-03-16 10:12:25 -07005package bufio_test
Russ Cox7c9e2c22008-09-12 16:42:53 -07006
7import (
Rob Piked3c61fc2011-03-16 10:12:25 -07008 . "bufio"
Robert Griesemer5a1d3322009-12-15 15:33:31 -08009 "bytes"
Brad Fitzpatrickdc71ace2013-03-21 19:59:49 -070010 "errors"
Robert Griesemer5a1d3322009-12-15 15:33:31 -080011 "fmt"
12 "io"
Adam Langley6392fc72011-04-13 15:12:28 -040013 "io/ioutil"
Robert Griesemer5a1d3322009-12-15 15:33:31 -080014 "strings"
15 "testing"
16 "testing/iotest"
Robert Griesemer7b6bc3e2014-04-10 21:46:00 -070017 "time"
Rob Pike30aa7012011-11-08 15:40:58 -080018 "unicode/utf8"
Russ Cox7c9e2c22008-09-12 16:42:53 -070019)
20
Russ Cox7c9e2c22008-09-12 16:42:53 -070021// Reads from a reader and rot13s the result.
Rob Pike33f3ed72009-01-15 16:22:57 -080022type rot13Reader struct {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080023 r io.Reader
Russ Cox7c9e2c22008-09-12 16:42:53 -070024}
25
Rob Pikec8b47c62009-05-08 11:22:57 -070026func newRot13Reader(r io.Reader) *rot13Reader {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080027 r13 := new(rot13Reader)
28 r13.r = r
29 return r13
Russ Cox7c9e2c22008-09-12 16:42:53 -070030}
31
Russ Coxc2049d22011-11-01 22:04:37 -040032func (r13 *rot13Reader) Read(p []byte) (int, error) {
Robin Eklindf36a53c2013-01-07 11:15:53 +110033 n, err := r13.r.Read(p)
34 if err != nil {
35 return n, err
Russ Cox7c9e2c22008-09-12 16:42:53 -070036 }
37 for i := 0; i < n; i++ {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080038 c := p[i] | 0x20 // lowercase byte
Russ Coxbe869ba2009-05-18 13:31:56 -070039 if 'a' <= c && c <= 'm' {
Robert Griesemer40621d52009-11-09 12:07:39 -080040 p[i] += 13
Russ Coxbe869ba2009-05-18 13:31:56 -070041 } else if 'n' <= c && c <= 'z' {
Robert Griesemer40621d52009-11-09 12:07:39 -080042 p[i] -= 13
Russ Cox7c9e2c22008-09-12 16:42:53 -070043 }
44 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -080045 return n, nil
Russ Cox7c9e2c22008-09-12 16:42:53 -070046}
47
Russ Coxbe869ba2009-05-18 13:31:56 -070048// Call ReadByte to accumulate the text of a file
49func readBytes(buf *Reader) string {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080050 var b [1000]byte
51 nb := 0
Russ Coxbe869ba2009-05-18 13:31:56 -070052 for {
Robin Eklindf36a53c2013-01-07 11:15:53 +110053 c, err := buf.ReadByte()
54 if err == io.EOF {
Robert Griesemer40621d52009-11-09 12:07:39 -080055 break
Russ Coxbe869ba2009-05-18 13:31:56 -070056 }
Robin Eklindf36a53c2013-01-07 11:15:53 +110057 if err == nil {
Graham Millerf795bdb2011-06-27 16:12:04 -040058 b[nb] = c
59 nb++
Robin Eklindf36a53c2013-01-07 11:15:53 +110060 } else if err != iotest.ErrTimeout {
61 panic("Data: " + err.Error())
Russ Coxbe869ba2009-05-18 13:31:56 -070062 }
Russ Coxbe869ba2009-05-18 13:31:56 -070063 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -080064 return string(b[0:nb])
Russ Coxbe869ba2009-05-18 13:31:56 -070065}
66
67func TestReaderSimple(t *testing.T) {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080068 data := "hello world"
Brad Fitzpatricka18f4ab2014-01-27 11:05:01 -080069 b := NewReader(strings.NewReader(data))
Russ Coxbe869ba2009-05-18 13:31:56 -070070 if s := readBytes(b); s != "hello world" {
Robert Griesemer40621d52009-11-09 12:07:39 -080071 t.Errorf("simple hello world test failed: got %q", s)
Russ Coxbe869ba2009-05-18 13:31:56 -070072 }
73
Brad Fitzpatricka18f4ab2014-01-27 11:05:01 -080074 b = NewReader(newRot13Reader(strings.NewReader(data)))
Russ Coxbe869ba2009-05-18 13:31:56 -070075 if s := readBytes(b); s != "uryyb jbeyq" {
Rob Pike1959c3a2010-09-23 13:48:56 +100076 t.Errorf("rot13 hello world test failed: got %q", s)
Russ Coxbe869ba2009-05-18 13:31:56 -070077 }
78}
79
Rob Pike33f3ed72009-01-15 16:22:57 -080080type readMaker struct {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080081 name string
82 fn func(io.Reader) io.Reader
Russ Cox7c9e2c22008-09-12 16:42:53 -070083}
Robert Griesemer646a2c52009-11-04 17:04:21 -080084
85var readMakers = []readMaker{
Robert Griesemer34788912010-10-22 10:06:33 -070086 {"full", func(r io.Reader) io.Reader { return r }},
87 {"byte", iotest.OneByteReader},
88 {"half", iotest.HalfReader},
89 {"data+err", iotest.DataErrReader},
Graham Millerf795bdb2011-06-27 16:12:04 -040090 {"timeout", iotest.TimeoutReader},
Russ Coxbe2edb52009-03-03 08:39:12 -080091}
Russ Cox7c9e2c22008-09-12 16:42:53 -070092
Russ Cox4b409282009-08-27 11:20:15 -070093// Call ReadString (which ends up calling everything else)
Russ Cox7c9e2c22008-09-12 16:42:53 -070094// to accumulate the text of a file.
Rob Pike01712ae2009-05-08 11:52:39 -070095func readLines(b *Reader) string {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080096 s := ""
Russ Cox7c9e2c22008-09-12 16:42:53 -070097 for {
Robin Eklindf36a53c2013-01-07 11:15:53 +110098 s1, err := b.ReadString('\n')
99 if err == io.EOF {
Robert Griesemer40621d52009-11-09 12:07:39 -0800100 break
Russ Cox7c9e2c22008-09-12 16:42:53 -0700101 }
Robin Eklindf36a53c2013-01-07 11:15:53 +1100102 if err != nil && err != iotest.ErrTimeout {
103 panic("GetLines: " + err.Error())
Russ Cox7c9e2c22008-09-12 16:42:53 -0700104 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800105 s += s1
Russ Cox7c9e2c22008-09-12 16:42:53 -0700106 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800107 return s
Russ Cox7c9e2c22008-09-12 16:42:53 -0700108}
109
Russ Cox7c9e2c22008-09-12 16:42:53 -0700110// Call Read to accumulate the text of a file
Rob Pike01712ae2009-05-08 11:52:39 -0700111func reads(buf *Reader, m int) string {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800112 var b [1000]byte
113 nb := 0
Russ Cox7c9e2c22008-09-12 16:42:53 -0700114 for {
Robin Eklindf36a53c2013-01-07 11:15:53 +1100115 n, err := buf.Read(b[nb : nb+m])
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800116 nb += n
Robin Eklindf36a53c2013-01-07 11:15:53 +1100117 if err == io.EOF {
Robert Griesemer40621d52009-11-09 12:07:39 -0800118 break
Russ Cox7c9e2c22008-09-12 16:42:53 -0700119 }
120 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800121 return string(b[0:nb])
Russ Cox7c9e2c22008-09-12 16:42:53 -0700122}
123
Rob Pike33f3ed72009-01-15 16:22:57 -0800124type bufReader struct {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800125 name string
126 fn func(*Reader) string
Russ Coxbe2edb52009-03-03 08:39:12 -0800127}
Russ Cox7c9e2c22008-09-12 16:42:53 -0700128
Robert Griesemer646a2c52009-11-04 17:04:21 -0800129var bufreaders = []bufReader{
Robert Griesemer34788912010-10-22 10:06:33 -0700130 {"1", func(b *Reader) string { return reads(b, 1) }},
131 {"2", func(b *Reader) string { return reads(b, 2) }},
132 {"3", func(b *Reader) string { return reads(b, 3) }},
133 {"4", func(b *Reader) string { return reads(b, 4) }},
134 {"5", func(b *Reader) string { return reads(b, 5) }},
135 {"7", func(b *Reader) string { return reads(b, 7) }},
136 {"bytes", readBytes},
137 {"lines", readLines},
Robert Griesemer646a2c52009-11-04 17:04:21 -0800138}
139
Rob Pike64776da2011-12-13 15:07:17 -0800140const minReadBufferSize = 16
141
Robert Griesemer646a2c52009-11-04 17:04:21 -0800142var bufsizes = []int{
Shawn Smith4d239bc2014-01-01 22:26:22 +1100143 0, minReadBufferSize, 23, 32, 46, 64, 93, 128, 1024, 4096,
Russ Coxbe2edb52009-03-03 08:39:12 -0800144}
Russ Cox7c9e2c22008-09-12 16:42:53 -0700145
Rob Pike01712ae2009-05-08 11:52:39 -0700146func TestReader(t *testing.T) {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800147 var texts [31]string
148 str := ""
149 all := ""
Russ Cox7c9e2c22008-09-12 16:42:53 -0700150 for i := 0; i < len(texts)-1; i++ {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800151 texts[i] = str + "\n"
152 all += texts[i]
153 str += string(i%26 + 'a')
Russ Cox7c9e2c22008-09-12 16:42:53 -0700154 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800155 texts[len(texts)-1] = all
Russ Cox983f06b2008-10-07 12:31:31 -0700156
Russ Cox7c9e2c22008-09-12 16:42:53 -0700157 for h := 0; h < len(texts); h++ {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800158 text := texts[h]
Rob Pike33f3ed72009-01-15 16:22:57 -0800159 for i := 0; i < len(readMakers); i++ {
Russ Cox7c9e2c22008-09-12 16:42:53 -0700160 for j := 0; j < len(bufreaders); j++ {
Russ Cox7c9e2c22008-09-12 16:42:53 -0700161 for k := 0; k < len(bufsizes); k++ {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800162 readmaker := readMakers[i]
163 bufreader := bufreaders[j]
164 bufsize := bufsizes[k]
Brad Fitzpatricka18f4ab2014-01-27 11:05:01 -0800165 read := readmaker.fn(strings.NewReader(text))
Rob Pikebb7b1a12012-02-08 13:07:13 +1100166 buf := NewReaderSize(read, bufsize)
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800167 s := bufreader.fn(buf)
Russ Cox7c9e2c22008-09-12 16:42:53 -0700168 if s != text {
Russ Cox0f83fa32008-11-24 15:17:47 -0800169 t.Errorf("reader=%s fn=%s bufsize=%d want=%q got=%q",
Robert Griesemer40621d52009-11-09 12:07:39 -0800170 readmaker.name, bufreader.name, bufsize, text, s)
Russ Cox7c9e2c22008-09-12 16:42:53 -0700171 }
172 }
173 }
174 }
175 }
176}
177
Robert Griesemer7b6bc3e2014-04-10 21:46:00 -0700178type zeroReader struct{}
179
180func (zeroReader) Read(p []byte) (int, error) {
181 return 0, nil
182}
183
184func TestZeroReader(t *testing.T) {
185 var z zeroReader
186 r := NewReader(z)
187
188 c := make(chan error)
189 go func() {
190 _, err := r.ReadByte()
191 c <- err
192 }()
193
194 select {
195 case err := <-c:
196 if err == nil {
197 t.Error("error expected")
198 } else if err != io.ErrNoProgress {
199 t.Error("unexpected error:", err)
200 }
201 case <-time.After(time.Second):
202 t.Error("test timed out (endless loop in ReadByte?)")
203 }
204}
205
Robert Griesemer5876cb02009-08-06 12:05:16 -0700206// A StringReader delivers its data one string segment at a time via Read.
207type StringReader struct {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800208 data []string
209 step int
Robert Griesemer5876cb02009-08-06 12:05:16 -0700210}
211
Russ Coxc2049d22011-11-01 22:04:37 -0400212func (r *StringReader) Read(p []byte) (n int, err error) {
Robert Griesemer5876cb02009-08-06 12:05:16 -0700213 if r.step < len(r.data) {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800214 s := r.data[r.step]
Russ Coxd86ab012010-10-26 21:52:54 -0700215 n = copy(p, s)
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800216 r.step++
Robert Griesemer5876cb02009-08-06 12:05:16 -0700217 } else {
Russ Coxc2049d22011-11-01 22:04:37 -0400218 err = io.EOF
Robert Griesemer5876cb02009-08-06 12:05:16 -0700219 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800220 return
Robert Griesemer5876cb02009-08-06 12:05:16 -0700221}
222
223func readRuneSegments(t *testing.T, segments []string) {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800224 got := ""
225 want := strings.Join(segments, "")
226 r := NewReader(&StringReader{data: segments})
Robert Griesemer5876cb02009-08-06 12:05:16 -0700227 for {
Russ Cox9f6d0362011-10-25 22:23:34 -0700228 r, _, err := r.ReadRune()
Robert Griesemer5876cb02009-08-06 12:05:16 -0700229 if err != nil {
Russ Coxc2049d22011-11-01 22:04:37 -0400230 if err != io.EOF {
Robert Griesemer40621d52009-11-09 12:07:39 -0800231 return
Robert Griesemer5876cb02009-08-06 12:05:16 -0700232 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800233 break
Robert Griesemer5876cb02009-08-06 12:05:16 -0700234 }
Russ Cox9f6d0362011-10-25 22:23:34 -0700235 got += string(r)
Robert Griesemer5876cb02009-08-06 12:05:16 -0700236 }
237 if got != want {
Robert Griesemer40621d52009-11-09 12:07:39 -0800238 t.Errorf("segments=%v got=%s want=%s", segments, got, want)
Robert Griesemer5876cb02009-08-06 12:05:16 -0700239 }
240}
241
Robert Griesemer646a2c52009-11-04 17:04:21 -0800242var segmentList = [][]string{
Robert Griesemer34788912010-10-22 10:06:33 -0700243 {},
244 {""},
245 {"日", "本語"},
246 {"\u65e5", "\u672c", "\u8a9e"},
247 {"\U000065e5", "\U0000672c", "\U00008a9e"},
248 {"\xe6", "\x97\xa5\xe6", "\x9c\xac\xe8\xaa\x9e"},
249 {"Hello", ", ", "World", "!"},
250 {"Hello", ", ", "", "World", "!"},
Robert Griesemer5876cb02009-08-06 12:05:16 -0700251}
252
253func TestReadRune(t *testing.T) {
254 for _, s := range segmentList {
Robert Griesemer40621d52009-11-09 12:07:39 -0800255 readRuneSegments(t, s)
Robert Griesemer5876cb02009-08-06 12:05:16 -0700256 }
257}
258
Rob Pikeacb695f2010-09-12 17:40:27 +1000259func TestUnreadRune(t *testing.T) {
Rob Pikeacb695f2010-09-12 17:40:27 +1000260 segments := []string{"Hello, world:", "日本語"}
Rob Pikeacb695f2010-09-12 17:40:27 +1000261 r := NewReader(&StringReader{data: segments})
Robert Griesemer8bd92422014-04-09 14:19:13 -0700262 got := ""
263 want := strings.Join(segments, "")
Rob Pikeacb695f2010-09-12 17:40:27 +1000264 // Normal execution.
265 for {
Russ Cox9f6d0362011-10-25 22:23:34 -0700266 r1, _, err := r.ReadRune()
Rob Pikeacb695f2010-09-12 17:40:27 +1000267 if err != nil {
Russ Coxc2049d22011-11-01 22:04:37 -0400268 if err != io.EOF {
Robert Griesemer8bd92422014-04-09 14:19:13 -0700269 t.Error("unexpected error on ReadRune:", err)
Rob Pikeacb695f2010-09-12 17:40:27 +1000270 }
271 break
272 }
Russ Cox9f6d0362011-10-25 22:23:34 -0700273 got += string(r1)
Robert Griesemer8bd92422014-04-09 14:19:13 -0700274 // Put it back and read it again.
Rob Pikeacb695f2010-09-12 17:40:27 +1000275 if err = r.UnreadRune(); err != nil {
Robert Griesemer8bd92422014-04-09 14:19:13 -0700276 t.Fatal("unexpected error on UnreadRune:", err)
Rob Pikeacb695f2010-09-12 17:40:27 +1000277 }
Russ Cox9f6d0362011-10-25 22:23:34 -0700278 r2, _, err := r.ReadRune()
Rob Pikeacb695f2010-09-12 17:40:27 +1000279 if err != nil {
Robert Griesemer8bd92422014-04-09 14:19:13 -0700280 t.Fatal("unexpected error reading after unreading:", err)
Rob Pikeacb695f2010-09-12 17:40:27 +1000281 }
Russ Cox9f6d0362011-10-25 22:23:34 -0700282 if r1 != r2 {
Robert Griesemer8bd92422014-04-09 14:19:13 -0700283 t.Fatalf("incorrect rune after unread: got %c, want %c", r1, r2)
Rob Pikeacb695f2010-09-12 17:40:27 +1000284 }
285 }
Robert Griesemer8bd92422014-04-09 14:19:13 -0700286 if got != want {
287 t.Errorf("got %q, want %q", got, want)
Rob Pikeacb695f2010-09-12 17:40:27 +1000288 }
289}
290
Shawn Smith4d239bc2014-01-01 22:26:22 +1100291func TestUnreadByte(t *testing.T) {
Shawn Smith4d239bc2014-01-01 22:26:22 +1100292 segments := []string{"Hello, ", "world"}
293 r := NewReader(&StringReader{data: segments})
Robert Griesemer8bd92422014-04-09 14:19:13 -0700294 got := ""
295 want := strings.Join(segments, "")
Shawn Smith4d239bc2014-01-01 22:26:22 +1100296 // Normal execution.
297 for {
298 b1, err := r.ReadByte()
299 if err != nil {
300 if err != io.EOF {
Robert Griesemer8bd92422014-04-09 14:19:13 -0700301 t.Error("unexpected error on ReadByte:", err)
Shawn Smith4d239bc2014-01-01 22:26:22 +1100302 }
303 break
304 }
305 got += string(b1)
Robert Griesemer8bd92422014-04-09 14:19:13 -0700306 // Put it back and read it again.
Shawn Smith4d239bc2014-01-01 22:26:22 +1100307 if err = r.UnreadByte(); err != nil {
Robert Griesemer8bd92422014-04-09 14:19:13 -0700308 t.Fatal("unexpected error on UnreadByte:", err)
Shawn Smith4d239bc2014-01-01 22:26:22 +1100309 }
310 b2, err := r.ReadByte()
311 if err != nil {
Robert Griesemer8bd92422014-04-09 14:19:13 -0700312 t.Fatal("unexpected error reading after unreading:", err)
Shawn Smith4d239bc2014-01-01 22:26:22 +1100313 }
314 if b1 != b2 {
Robert Griesemer8bd92422014-04-09 14:19:13 -0700315 t.Fatalf("incorrect byte after unread: got %q, want %q", b1, b2)
Shawn Smith4d239bc2014-01-01 22:26:22 +1100316 }
317 }
318 if got != want {
Robert Griesemer8bd92422014-04-09 14:19:13 -0700319 t.Errorf("got %q, want %q", got, want)
320 }
321}
322
323func TestUnreadByteMultiple(t *testing.T) {
324 segments := []string{"Hello, ", "world"}
325 data := strings.Join(segments, "")
326 for n := 0; n <= len(data); n++ {
327 r := NewReader(&StringReader{data: segments})
328 // Read n bytes.
329 for i := 0; i < n; i++ {
330 b, err := r.ReadByte()
331 if err != nil {
332 t.Fatalf("n = %d: unexpected error on ReadByte: %v", n, err)
333 }
334 if b != data[i] {
335 t.Fatalf("n = %d: incorrect byte returned from ReadByte: got %q, want %q", n, b, data[i])
336 }
337 }
338 // Unread one byte if there is one.
339 if n > 0 {
340 if err := r.UnreadByte(); err != nil {
341 t.Errorf("n = %d: unexpected error on UnreadByte: %v", n, err)
342 }
343 }
344 // Test that we cannot unread any further.
345 if err := r.UnreadByte(); err == nil {
346 t.Errorf("n = %d: expected error on UnreadByte", n)
347 }
Shawn Smith4d239bc2014-01-01 22:26:22 +1100348 }
349}
350
Robert Griesemer9144d872014-04-25 09:46:07 -0600351func TestUnreadByteOthers(t *testing.T) {
352 // A list of readers to use in conjuction with UnreadByte.
353 var readers = []func(*Reader, byte) ([]byte, error){
354 (*Reader).ReadBytes,
355 (*Reader).ReadSlice,
356 func(r *Reader, delim byte) ([]byte, error) {
357 data, err := r.ReadString(delim)
358 return []byte(data), err
359 },
360 // ReadLine doesn't fit the data/pattern easily
361 // so we leave it out. It should be covered via
362 // the ReadSlice test since ReadLine simply calls
363 // ReadSlice, and it's that function that handles
364 // the last byte.
365 }
366
367 // Try all readers with UnreadByte.
368 for rno, read := range readers {
369 // Some input data that is longer than the minimum reader buffer size.
370 const n = 10
371 var buf bytes.Buffer
372 for i := 0; i < n; i++ {
373 buf.WriteString("abcdefg")
374 }
375
376 r := NewReaderSize(&buf, minReadBufferSize)
377 readTo := func(delim byte, want string) {
378 data, err := read(r, delim)
379 if err != nil {
380 t.Fatalf("#%d: unexpected error reading to %c: %v", rno, delim, err)
381 }
382 if got := string(data); got != want {
383 t.Fatalf("#%d: got %q, want %q", rno, got, want)
384 }
385 }
386
387 // Read the data with occasional UnreadByte calls.
388 for i := 0; i < n; i++ {
389 readTo('d', "abcd")
390 for j := 0; j < 3; j++ {
391 if err := r.UnreadByte(); err != nil {
392 t.Fatalf("#%d: unexpected error on UnreadByte: %v", rno, err)
393 }
394 readTo('d', "d")
395 }
396 readTo('g', "efg")
397 }
398
399 // All data should have been read.
400 _, err := r.ReadByte()
401 if err != io.EOF {
402 t.Errorf("#%d: got error %v; want EOF", rno, err)
403 }
404 }
405}
406
Rob Pikeacb695f2010-09-12 17:40:27 +1000407// Test that UnreadRune fails if the preceding operation was not a ReadRune.
408func TestUnreadRuneError(t *testing.T) {
409 buf := make([]byte, 3) // All runes in this test are 3 bytes long
410 r := NewReader(&StringReader{data: []string{"日本語日本語日本語"}})
411 if r.UnreadRune() == nil {
412 t.Error("expected error on UnreadRune from fresh buffer")
413 }
414 _, _, err := r.ReadRune()
415 if err != nil {
416 t.Error("unexpected error on ReadRune (1):", err)
417 }
418 if err = r.UnreadRune(); err != nil {
419 t.Error("unexpected error on UnreadRune (1):", err)
420 }
421 if r.UnreadRune() == nil {
422 t.Error("expected error after UnreadRune (1)")
423 }
424 // Test error after Read.
425 _, _, err = r.ReadRune() // reset state
426 if err != nil {
427 t.Error("unexpected error on ReadRune (2):", err)
428 }
429 _, err = r.Read(buf)
430 if err != nil {
431 t.Error("unexpected error on Read (2):", err)
432 }
433 if r.UnreadRune() == nil {
434 t.Error("expected error after Read (2)")
435 }
436 // Test error after ReadByte.
437 _, _, err = r.ReadRune() // reset state
438 if err != nil {
439 t.Error("unexpected error on ReadRune (2):", err)
440 }
441 for _ = range buf {
442 _, err = r.ReadByte()
443 if err != nil {
444 t.Error("unexpected error on ReadByte (2):", err)
445 }
446 }
447 if r.UnreadRune() == nil {
448 t.Error("expected error after ReadByte")
449 }
450 // Test error after UnreadByte.
451 _, _, err = r.ReadRune() // reset state
452 if err != nil {
453 t.Error("unexpected error on ReadRune (3):", err)
454 }
455 _, err = r.ReadByte()
456 if err != nil {
457 t.Error("unexpected error on ReadByte (3):", err)
458 }
459 err = r.UnreadByte()
460 if err != nil {
461 t.Error("unexpected error on UnreadByte (3):", err)
462 }
463 if r.UnreadRune() == nil {
464 t.Error("expected error after UnreadByte (3)")
465 }
466}
467
Rob Pikee4393452010-09-24 12:28:14 +1000468func TestUnreadRuneAtEOF(t *testing.T) {
469 // UnreadRune/ReadRune should error at EOF (was a bug; used to panic)
470 r := NewReader(strings.NewReader("x"))
471 r.ReadRune()
472 r.ReadRune()
473 r.UnreadRune()
474 _, _, err := r.ReadRune()
475 if err == nil {
476 t.Error("expected error at EOF")
Russ Coxc2049d22011-11-01 22:04:37 -0400477 } else if err != io.EOF {
Rob Pikee4393452010-09-24 12:28:14 +1000478 t.Error("expected EOF; got", err)
479 }
480}
481
Rob Pike8c9944d2010-03-05 14:03:17 -0800482func TestReadWriteRune(t *testing.T) {
483 const NRune = 1000
484 byteBuf := new(bytes.Buffer)
485 w := NewWriter(byteBuf)
486 // Write the runes out using WriteRune
487 buf := make([]byte, utf8.UTFMax)
Russ Cox9f6d0362011-10-25 22:23:34 -0700488 for r := rune(0); r < NRune; r++ {
489 size := utf8.EncodeRune(buf, r)
490 nbytes, err := w.WriteRune(r)
Rob Pike8c9944d2010-03-05 14:03:17 -0800491 if err != nil {
Russ Cox9f6d0362011-10-25 22:23:34 -0700492 t.Fatalf("WriteRune(0x%x) error: %s", r, err)
Rob Pike8c9944d2010-03-05 14:03:17 -0800493 }
494 if nbytes != size {
Russ Cox9f6d0362011-10-25 22:23:34 -0700495 t.Fatalf("WriteRune(0x%x) expected %d, got %d", r, size, nbytes)
Rob Pike8c9944d2010-03-05 14:03:17 -0800496 }
497 }
498 w.Flush()
499
500 r := NewReader(byteBuf)
501 // Read them back with ReadRune
Russ Cox9f6d0362011-10-25 22:23:34 -0700502 for r1 := rune(0); r1 < NRune; r1++ {
503 size := utf8.EncodeRune(buf, r1)
Rob Pike8c9944d2010-03-05 14:03:17 -0800504 nr, nbytes, err := r.ReadRune()
Russ Cox9f6d0362011-10-25 22:23:34 -0700505 if nr != r1 || nbytes != size || err != nil {
506 t.Fatalf("ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)", r1, nr, nbytes, r1, size, err)
Rob Pike8c9944d2010-03-05 14:03:17 -0800507 }
508 }
509}
510
Rob Pike01712ae2009-05-08 11:52:39 -0700511func TestWriter(t *testing.T) {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800512 var data [8192]byte
Russ Cox7c9e2c22008-09-12 16:42:53 -0700513
Russ Cox7c9e2c22008-09-12 16:42:53 -0700514 for i := 0; i < len(data); i++ {
Robert Griesemer40621d52009-11-09 12:07:39 -0800515 data[i] = byte(' ' + i%('~'-' '))
Russ Cox7c9e2c22008-09-12 16:42:53 -0700516 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800517 w := new(bytes.Buffer)
Russ Cox7c9e2c22008-09-12 16:42:53 -0700518 for i := 0; i < len(bufsizes); i++ {
519 for j := 0; j < len(bufsizes); j++ {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800520 nwrite := bufsizes[i]
521 bs := bufsizes[j]
Russ Cox983f06b2008-10-07 12:31:31 -0700522
Russ Coxbe869ba2009-05-18 13:31:56 -0700523 // Write nwrite bytes using buffer size bs.
524 // Check that the right amount makes it out
525 // and that the data is correct.
Russ Cox7c9e2c22008-09-12 16:42:53 -0700526
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800527 w.Reset()
Rob Pikebb7b1a12012-02-08 13:07:13 +1100528 buf := NewWriterSize(w, bs)
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800529 context := fmt.Sprintf("nwrite=%d bufsize=%d", nwrite, bs)
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800530 n, e1 := buf.Write(data[0:nwrite])
Russ Coxbe869ba2009-05-18 13:31:56 -0700531 if e1 != nil || n != nwrite {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800532 t.Errorf("%s: buf.Write %d = %d, %v", context, nwrite, n, e1)
533 continue
Russ Coxbe869ba2009-05-18 13:31:56 -0700534 }
Rob Pikebb7b1a12012-02-08 13:07:13 +1100535 if e := buf.Flush(); e != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800536 t.Errorf("%s: buf.Flush = %v", context, e)
Russ Coxbe869ba2009-05-18 13:31:56 -0700537 }
Russ Cox983f06b2008-10-07 12:31:31 -0700538
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800539 written := w.Bytes()
Russ Coxbe869ba2009-05-18 13:31:56 -0700540 if len(written) != nwrite {
Robert Griesemer40621d52009-11-09 12:07:39 -0800541 t.Errorf("%s: %d bytes written", context, len(written))
Russ Coxbe869ba2009-05-18 13:31:56 -0700542 }
543 for l := 0; l < len(written); l++ {
544 if written[i] != data[i] {
Rob Pike1ce62452010-12-07 16:42:54 -0500545 t.Errorf("wrong bytes written")
546 t.Errorf("want=%q", data[0:len(written)])
547 t.Errorf("have=%q", written)
Russ Cox7c9e2c22008-09-12 16:42:53 -0700548 }
549 }
550 }
551 }
552}
553
Russ Coxbe869ba2009-05-18 13:31:56 -0700554// Check that write errors are returned properly.
555
556type errorWriterTest struct {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800557 n, m int
Russ Coxc2049d22011-11-01 22:04:37 -0400558 err error
559 expect error
Russ Coxbe869ba2009-05-18 13:31:56 -0700560}
561
Russ Coxc2049d22011-11-01 22:04:37 -0400562func (w errorWriterTest) Write(p []byte) (int, error) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800563 return len(p) * w.n / w.m, w.err
Russ Coxbe869ba2009-05-18 13:31:56 -0700564}
565
Robert Griesemer646a2c52009-11-04 17:04:21 -0800566var errorWriterTests = []errorWriterTest{
Robert Griesemer34788912010-10-22 10:06:33 -0700567 {0, 1, nil, io.ErrShortWrite},
568 {1, 2, nil, io.ErrShortWrite},
569 {1, 1, nil, nil},
Russ Coxfd34e782011-11-13 22:42:42 -0500570 {0, 1, io.ErrClosedPipe, io.ErrClosedPipe},
571 {1, 2, io.ErrClosedPipe, io.ErrClosedPipe},
572 {1, 1, io.ErrClosedPipe, io.ErrClosedPipe},
Russ Coxbe869ba2009-05-18 13:31:56 -0700573}
574
575func TestWriteErrors(t *testing.T) {
Russ Coxca6a0fe2009-09-15 09:41:59 -0700576 for _, w := range errorWriterTests {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800577 buf := NewWriter(w)
Russ Cox9750adb2010-02-25 16:01:29 -0800578 _, e := buf.Write([]byte("hello world"))
Russ Coxbe869ba2009-05-18 13:31:56 -0700579 if e != nil {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800580 t.Errorf("Write hello to %v: %v", w, e)
581 continue
Russ Coxbe869ba2009-05-18 13:31:56 -0700582 }
Brad Fitzpatrickdc71ace2013-03-21 19:59:49 -0700583 // Two flushes, to verify the error is sticky.
584 for i := 0; i < 2; i++ {
585 e = buf.Flush()
586 if e != w.expect {
587 t.Errorf("Flush %d/2 %v: got %v, wanted %v", i+1, w, e, w.expect)
588 }
Russ Coxbe869ba2009-05-18 13:31:56 -0700589 }
590 }
591}
592
Rob Pike01712ae2009-05-08 11:52:39 -0700593func TestNewReaderSizeIdempotent(t *testing.T) {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800594 const BufSize = 1000
Brad Fitzpatricka18f4ab2014-01-27 11:05:01 -0800595 b := NewReaderSize(strings.NewReader("hello world"), BufSize)
Rob Pikeee196952009-04-06 21:42:14 -0700596 // Does it recognize itself?
Rob Pikebb7b1a12012-02-08 13:07:13 +1100597 b1 := NewReaderSize(b, BufSize)
Rob Pikeee196952009-04-06 21:42:14 -0700598 if b1 != b {
Robert Griesemer40621d52009-11-09 12:07:39 -0800599 t.Error("NewReaderSize did not detect underlying Reader")
Rob Pikeee196952009-04-06 21:42:14 -0700600 }
601 // Does it wrap if existing buffer is too small?
Rob Pikebb7b1a12012-02-08 13:07:13 +1100602 b2 := NewReaderSize(b, 2*BufSize)
Rob Pikeee196952009-04-06 21:42:14 -0700603 if b2 == b {
Robert Griesemer40621d52009-11-09 12:07:39 -0800604 t.Error("NewReaderSize did not enlarge buffer")
Rob Pikeee196952009-04-06 21:42:14 -0700605 }
606}
607
Rob Pike01712ae2009-05-08 11:52:39 -0700608func TestNewWriterSizeIdempotent(t *testing.T) {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800609 const BufSize = 1000
Rob Pikebb7b1a12012-02-08 13:07:13 +1100610 b := NewWriterSize(new(bytes.Buffer), BufSize)
Rob Pikeee196952009-04-06 21:42:14 -0700611 // Does it recognize itself?
Rob Pikebb7b1a12012-02-08 13:07:13 +1100612 b1 := NewWriterSize(b, BufSize)
Rob Pikeee196952009-04-06 21:42:14 -0700613 if b1 != b {
Robert Griesemer40621d52009-11-09 12:07:39 -0800614 t.Error("NewWriterSize did not detect underlying Writer")
Rob Pikeee196952009-04-06 21:42:14 -0700615 }
616 // Does it wrap if existing buffer is too small?
Rob Pikebb7b1a12012-02-08 13:07:13 +1100617 b2 := NewWriterSize(b, 2*BufSize)
Rob Pikeee196952009-04-06 21:42:14 -0700618 if b2 == b {
Robert Griesemer40621d52009-11-09 12:07:39 -0800619 t.Error("NewWriterSize did not enlarge buffer")
Rob Pikeee196952009-04-06 21:42:14 -0700620 }
621}
Rob Pike2495c142009-08-03 18:28:05 -0700622
623func TestWriteString(t *testing.T) {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800624 const BufSize = 8
625 buf := new(bytes.Buffer)
Rob Pikebb7b1a12012-02-08 13:07:13 +1100626 b := NewWriterSize(buf, BufSize)
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800627 b.WriteString("0") // easy
628 b.WriteString("123456") // still easy
629 b.WriteString("7890") // easy after flush
630 b.WriteString("abcdefghijklmnopqrstuvwxy") // hard
631 b.WriteString("z")
Rob Piked3c61fc2011-03-16 10:12:25 -0700632 if err := b.Flush(); err != nil {
633 t.Error("WriteString", err)
Rob Pike2495c142009-08-03 18:28:05 -0700634 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800635 s := "01234567890abcdefghijklmnopqrstuvwxyz"
Rob Piked5be41f2009-09-16 15:15:00 -0700636 if string(buf.Bytes()) != s {
Robert Griesemer40621d52009-11-09 12:07:39 -0800637 t.Errorf("WriteString wants %q gets %q", s, string(buf.Bytes()))
Rob Pike2495c142009-08-03 18:28:05 -0700638 }
639}
Russ Cox041d9782010-06-02 16:17:18 -0700640
641func TestBufferFull(t *testing.T) {
Rob Pike64776da2011-12-13 15:07:17 -0800642 const longString = "And now, hello, world! It is the time for all good men to come to the aid of their party"
Rob Pikebb7b1a12012-02-08 13:07:13 +1100643 buf := NewReaderSize(strings.NewReader(longString), minReadBufferSize)
Rob Pike64776da2011-12-13 15:07:17 -0800644 line, err := buf.ReadSlice('!')
645 if string(line) != "And now, hello, " || err != ErrBufferFull {
Russ Cox041d9782010-06-02 16:17:18 -0700646 t.Errorf("first ReadSlice(,) = %q, %v", line, err)
647 }
Rob Pike64776da2011-12-13 15:07:17 -0800648 line, err = buf.ReadSlice('!')
649 if string(line) != "world!" || err != nil {
Russ Cox041d9782010-06-02 16:17:18 -0700650 t.Errorf("second ReadSlice(,) = %q, %v", line, err)
651 }
652}
Nigel Tao27e24902010-08-04 09:44:02 +1000653
654func TestPeek(t *testing.T) {
655 p := make([]byte, 10)
Rob Pike64776da2011-12-13 15:07:17 -0800656 // string is 16 (minReadBufferSize) long.
Rob Pikebb7b1a12012-02-08 13:07:13 +1100657 buf := NewReaderSize(strings.NewReader("abcdefghijklmnop"), minReadBufferSize)
Nigel Tao27e24902010-08-04 09:44:02 +1000658 if s, err := buf.Peek(1); string(s) != "a" || err != nil {
659 t.Fatalf("want %q got %q, err=%v", "a", string(s), err)
660 }
661 if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {
662 t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err)
663 }
Shawn Smith4d239bc2014-01-01 22:26:22 +1100664 if _, err := buf.Peek(-1); err != ErrNegativeCount {
665 t.Fatalf("want ErrNegativeCount got %v", err)
666 }
Rob Pike64776da2011-12-13 15:07:17 -0800667 if _, err := buf.Peek(32); err != ErrBufferFull {
Nigel Tao27e24902010-08-04 09:44:02 +1000668 t.Fatalf("want ErrBufFull got %v", err)
669 }
670 if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil {
671 t.Fatalf("want %q got %q, err=%v", "abc", string(p[0:3]), err)
672 }
673 if s, err := buf.Peek(1); string(s) != "d" || err != nil {
674 t.Fatalf("want %q got %q, err=%v", "d", string(s), err)
675 }
676 if s, err := buf.Peek(2); string(s) != "de" || err != nil {
677 t.Fatalf("want %q got %q, err=%v", "de", string(s), err)
678 }
679 if _, err := buf.Read(p[0:3]); string(p[0:3]) != "def" || err != nil {
680 t.Fatalf("want %q got %q, err=%v", "def", string(p[0:3]), err)
681 }
682 if s, err := buf.Peek(4); string(s) != "ghij" || err != nil {
683 t.Fatalf("want %q got %q, err=%v", "ghij", string(s), err)
684 }
Rob Pike64776da2011-12-13 15:07:17 -0800685 if _, err := buf.Read(p[0:]); string(p[0:]) != "ghijklmnop" || err != nil {
686 t.Fatalf("want %q got %q, err=%v", "ghijklmnop", string(p[0:minReadBufferSize]), err)
Nigel Tao27e24902010-08-04 09:44:02 +1000687 }
688 if s, err := buf.Peek(0); string(s) != "" || err != nil {
689 t.Fatalf("want %q got %q, err=%v", "", string(s), err)
690 }
Russ Coxc2049d22011-11-01 22:04:37 -0400691 if _, err := buf.Peek(1); err != io.EOF {
Nigel Tao27e24902010-08-04 09:44:02 +1000692 t.Fatalf("want EOF got %v", err)
693 }
Brad Fitzpatrick88f8af12012-02-16 10:15:36 +1100694
695 // Test for issue 3022, not exposing a reader's error on a successful Peek.
696 buf = NewReaderSize(dataAndEOFReader("abcd"), 32)
697 if s, err := buf.Peek(2); string(s) != "ab" || err != nil {
698 t.Errorf(`Peek(2) on "abcd", EOF = %q, %v; want "ab", nil`, string(s), err)
699 }
700 if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {
701 t.Errorf(`Peek(4) on "abcd", EOF = %q, %v; want "abcd", nil`, string(s), err)
702 }
703 if n, err := buf.Read(p[0:5]); string(p[0:n]) != "abcd" || err != nil {
704 t.Fatalf("Read after peek = %q, %v; want abcd, EOF", p[0:n], err)
705 }
706 if n, err := buf.Read(p[0:1]); string(p[0:n]) != "" || err != io.EOF {
707 t.Fatalf(`second Read after peek = %q, %v; want "", EOF`, p[0:n], err)
708 }
709}
710
711type dataAndEOFReader string
712
713func (r dataAndEOFReader) Read(p []byte) (int, error) {
714 return copy(p, r), io.EOF
Nigel Tao27e24902010-08-04 09:44:02 +1000715}
Rob Pike52e3c992010-10-13 17:12:43 -0700716
717func TestPeekThenUnreadRune(t *testing.T) {
718 // This sequence used to cause a crash.
719 r := NewReader(strings.NewReader("x"))
720 r.ReadRune()
721 r.Peek(1)
722 r.UnreadRune()
723 r.ReadRune() // Used to panic here
724}
Adam Langley6392fc72011-04-13 15:12:28 -0400725
726var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy")
727var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy")
728var 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")
729
730// TestReader wraps a []byte and returns reads of a specific length.
731type testReader struct {
732 data []byte
733 stride int
734}
735
Russ Coxc2049d22011-11-01 22:04:37 -0400736func (t *testReader) Read(buf []byte) (n int, err error) {
Adam Langley6392fc72011-04-13 15:12:28 -0400737 n = t.stride
738 if n > len(t.data) {
739 n = len(t.data)
740 }
741 if n > len(buf) {
742 n = len(buf)
743 }
744 copy(buf, t.data)
745 t.data = t.data[n:]
746 if len(t.data) == 0 {
Russ Coxc2049d22011-11-01 22:04:37 -0400747 err = io.EOF
Adam Langley6392fc72011-04-13 15:12:28 -0400748 }
749 return
750}
751
752func testReadLine(t *testing.T, input []byte) {
753 //for stride := 1; stride < len(input); stride++ {
754 for stride := 1; stride < 2; stride++ {
755 done := 0
756 reader := testReader{input, stride}
Rob Pikebb7b1a12012-02-08 13:07:13 +1100757 l := NewReaderSize(&reader, len(input)+1)
Adam Langley6392fc72011-04-13 15:12:28 -0400758 for {
759 line, isPrefix, err := l.ReadLine()
760 if len(line) > 0 && err != nil {
761 t.Errorf("ReadLine returned both data and error: %s", err)
762 }
763 if isPrefix {
764 t.Errorf("ReadLine returned prefix")
765 }
766 if err != nil {
Russ Coxc2049d22011-11-01 22:04:37 -0400767 if err != io.EOF {
Adam Langley6392fc72011-04-13 15:12:28 -0400768 t.Fatalf("Got unknown error: %s", err)
769 }
770 break
771 }
772 if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) {
773 t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line)
774 }
775 done += len(line)
776 }
777 if done != len(testOutput) {
778 t.Errorf("ReadLine didn't return everything: got: %d, want: %d (stride: %d)", done, len(testOutput), stride)
779 }
780 }
781}
782
783func TestReadLine(t *testing.T) {
784 testReadLine(t, testInput)
785 testReadLine(t, testInputrn)
786}
787
788func TestLineTooLong(t *testing.T) {
Rob Pike64776da2011-12-13 15:07:17 -0800789 data := make([]byte, 0)
790 for i := 0; i < minReadBufferSize*5/2; i++ {
791 data = append(data, '0'+byte(i%10))
792 }
Brad Fitzpatricka18f4ab2014-01-27 11:05:01 -0800793 buf := bytes.NewReader(data)
Rob Pikebb7b1a12012-02-08 13:07:13 +1100794 l := NewReaderSize(buf, minReadBufferSize)
Adam Langley6392fc72011-04-13 15:12:28 -0400795 line, isPrefix, err := l.ReadLine()
Rob Pike64776da2011-12-13 15:07:17 -0800796 if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
797 t.Errorf("bad result for first line: got %q want %q %v", line, data[:minReadBufferSize], err)
Adam Langley6392fc72011-04-13 15:12:28 -0400798 }
Rob Pike64776da2011-12-13 15:07:17 -0800799 data = data[len(line):]
Adam Langley6392fc72011-04-13 15:12:28 -0400800 line, isPrefix, err = l.ReadLine()
Rob Pike64776da2011-12-13 15:07:17 -0800801 if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
802 t.Errorf("bad result for second line: got %q want %q %v", line, data[:minReadBufferSize], err)
Adam Langley6392fc72011-04-13 15:12:28 -0400803 }
Rob Pike64776da2011-12-13 15:07:17 -0800804 data = data[len(line):]
Adam Langley6392fc72011-04-13 15:12:28 -0400805 line, isPrefix, err = l.ReadLine()
Rob Pike64776da2011-12-13 15:07:17 -0800806 if isPrefix || !bytes.Equal(line, data[:minReadBufferSize/2]) || err != nil {
807 t.Errorf("bad result for third line: got %q want %q %v", line, data[:minReadBufferSize/2], err)
Adam Langley6392fc72011-04-13 15:12:28 -0400808 }
809 line, isPrefix, err = l.ReadLine()
810 if isPrefix || err == nil {
811 t.Errorf("expected no more lines: %x %s", line, err)
812 }
813}
814
815func TestReadAfterLines(t *testing.T) {
Rob Pike64776da2011-12-13 15:07:17 -0800816 line1 := "this is line1"
817 restData := "this is line2\nthis is line 3\n"
Brad Fitzpatricka18f4ab2014-01-27 11:05:01 -0800818 inbuf := bytes.NewReader([]byte(line1 + "\n" + restData))
Adam Langley6392fc72011-04-13 15:12:28 -0400819 outbuf := new(bytes.Buffer)
820 maxLineLength := len(line1) + len(restData)/2
Rob Pikebb7b1a12012-02-08 13:07:13 +1100821 l := NewReaderSize(inbuf, maxLineLength)
Adam Langley6392fc72011-04-13 15:12:28 -0400822 line, isPrefix, err := l.ReadLine()
823 if isPrefix || err != nil || string(line) != line1 {
824 t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line))
825 }
826 n, err := io.Copy(outbuf, l)
827 if int(n) != len(restData) || err != nil {
828 t.Errorf("bad result for Read: n=%d err=%v", n, err)
829 }
830 if outbuf.String() != restData {
831 t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData)
832 }
833}
834
835func TestReadEmptyBuffer(t *testing.T) {
Rob Pikebb7b1a12012-02-08 13:07:13 +1100836 l := NewReaderSize(new(bytes.Buffer), minReadBufferSize)
Adam Langley6392fc72011-04-13 15:12:28 -0400837 line, isPrefix, err := l.ReadLine()
Russ Coxc2049d22011-11-01 22:04:37 -0400838 if err != io.EOF {
Adam Langley6392fc72011-04-13 15:12:28 -0400839 t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
840 }
841}
842
843func TestLinesAfterRead(t *testing.T) {
Brad Fitzpatricka18f4ab2014-01-27 11:05:01 -0800844 l := NewReaderSize(bytes.NewReader([]byte("foo")), minReadBufferSize)
Adam Langley6392fc72011-04-13 15:12:28 -0400845 _, err := ioutil.ReadAll(l)
846 if err != nil {
847 t.Error(err)
848 return
849 }
850
851 line, isPrefix, err := l.ReadLine()
Russ Coxc2049d22011-11-01 22:04:37 -0400852 if err != io.EOF {
Adam Langley6392fc72011-04-13 15:12:28 -0400853 t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
854 }
855}
Andrew Gerrand56f94842011-08-25 08:44:12 +1000856
Brad Fitzpatrickbd43eac2011-11-02 08:30:50 -0700857func TestReadLineNonNilLineOrError(t *testing.T) {
858 r := NewReader(strings.NewReader("line 1\n"))
859 for i := 0; i < 2; i++ {
860 l, _, err := r.ReadLine()
861 if l != nil && err != nil {
862 t.Fatalf("on line %d/2; ReadLine=%#v, %v; want non-nil line or Error, but not both",
863 i+1, l, err)
864 }
865 }
866}
867
Andrew Gerrand56f94842011-08-25 08:44:12 +1000868type readLineResult struct {
869 line []byte
870 isPrefix bool
Russ Coxc2049d22011-11-01 22:04:37 -0400871 err error
Andrew Gerrand56f94842011-08-25 08:44:12 +1000872}
873
874var readLineNewlinesTests = []struct {
Rob Pike64776da2011-12-13 15:07:17 -0800875 input string
876 expect []readLineResult
Andrew Gerrand56f94842011-08-25 08:44:12 +1000877}{
Rob Pike64776da2011-12-13 15:07:17 -0800878 {"012345678901234\r\n012345678901234\r\n", []readLineResult{
879 {[]byte("012345678901234"), true, nil},
Andrew Gerrand56f94842011-08-25 08:44:12 +1000880 {nil, false, nil},
Rob Pike64776da2011-12-13 15:07:17 -0800881 {[]byte("012345678901234"), true, nil},
Andrew Gerrand56f94842011-08-25 08:44:12 +1000882 {nil, false, nil},
Russ Coxc2049d22011-11-01 22:04:37 -0400883 {nil, false, io.EOF},
Andrew Gerrand56f94842011-08-25 08:44:12 +1000884 }},
Rob Pike64776da2011-12-13 15:07:17 -0800885 {"0123456789012345\r012345678901234\r", []readLineResult{
886 {[]byte("0123456789012345"), true, nil},
887 {[]byte("\r012345678901234"), true, nil},
Andrew Gerrand56f94842011-08-25 08:44:12 +1000888 {[]byte("\r"), false, nil},
Russ Coxc2049d22011-11-01 22:04:37 -0400889 {nil, false, io.EOF},
Andrew Gerrand56f94842011-08-25 08:44:12 +1000890 }},
891}
892
893func TestReadLineNewlines(t *testing.T) {
894 for _, e := range readLineNewlinesTests {
Rob Pike64776da2011-12-13 15:07:17 -0800895 testReadLineNewlines(t, e.input, e.expect)
Andrew Gerrand56f94842011-08-25 08:44:12 +1000896 }
897}
898
Rob Pike64776da2011-12-13 15:07:17 -0800899func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) {
Rob Pikebb7b1a12012-02-08 13:07:13 +1100900 b := NewReaderSize(strings.NewReader(input), minReadBufferSize)
Andrew Gerrand56f94842011-08-25 08:44:12 +1000901 for i, e := range expect {
902 line, isPrefix, err := b.ReadLine()
Matthew Dempsky46811d22013-01-07 10:03:49 +1100903 if !bytes.Equal(line, e.line) {
Andrew Gerrand56f94842011-08-25 08:44:12 +1000904 t.Errorf("%q call %d, line == %q, want %q", input, i, line, e.line)
905 return
906 }
907 if isPrefix != e.isPrefix {
908 t.Errorf("%q call %d, isPrefix == %v, want %v", input, i, isPrefix, e.isPrefix)
909 return
910 }
911 if err != e.err {
912 t.Errorf("%q call %d, err == %v, want %v", input, i, err, e.err)
913 return
914 }
915 }
916}
Michael Chatene289a2b2012-09-27 16:31:03 +1000917
Michael Chaten2a4818d2012-10-19 11:22:51 +1100918func createTestInput(n int) []byte {
919 input := make([]byte, n)
Michael Chatene289a2b2012-09-27 16:31:03 +1000920 for i := range input {
921 // 101 and 251 are arbitrary prime numbers.
922 // The idea is to create an input sequence
923 // which doesn't repeat too frequently.
924 input[i] = byte(i % 251)
925 if i%101 == 0 {
926 input[i] ^= byte(i / 101)
927 }
928 }
Michael Chaten2a4818d2012-10-19 11:22:51 +1100929 return input
930}
931
932func TestReaderWriteTo(t *testing.T) {
933 input := createTestInput(8192)
Brad Fitzpatricka18f4ab2014-01-27 11:05:01 -0800934 r := NewReader(onlyReader{bytes.NewReader(input)})
Michael Chatene289a2b2012-09-27 16:31:03 +1000935 w := new(bytes.Buffer)
936 if n, err := r.WriteTo(w); err != nil || n != int64(len(input)) {
937 t.Fatalf("r.WriteTo(w) = %d, %v, want %d, nil", n, err, len(input))
938 }
939
940 for i, val := range w.Bytes() {
941 if val != input[i] {
942 t.Errorf("after write: out[%d] = %#x, want %#x", i, val, input[i])
943 }
944 }
945}
946
947type errorWriterToTest struct {
948 rn, wn int
949 rerr, werr error
950 expected error
951}
952
953func (r errorWriterToTest) Read(p []byte) (int, error) {
954 return len(p) * r.rn, r.rerr
955}
956
957func (w errorWriterToTest) Write(p []byte) (int, error) {
958 return len(p) * w.wn, w.werr
959}
960
961var errorWriterToTests = []errorWriterToTest{
962 {1, 0, nil, io.ErrClosedPipe, io.ErrClosedPipe},
963 {0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe},
964 {0, 0, io.ErrUnexpectedEOF, io.ErrClosedPipe, io.ErrClosedPipe},
965 {0, 1, io.EOF, nil, nil},
966}
967
968func TestReaderWriteToErrors(t *testing.T) {
969 for i, rw := range errorWriterToTests {
970 r := NewReader(rw)
971 if _, err := r.WriteTo(rw); err != rw.expected {
972 t.Errorf("r.WriteTo(errorWriterToTests[%d]) = _, %v, want _,%v", i, err, rw.expected)
973 }
974 }
975}
976
Michael Chaten2a4818d2012-10-19 11:22:51 +1100977func TestWriterReadFrom(t *testing.T) {
978 ws := []func(io.Writer) io.Writer{
Nigel Tao0ba5ec52012-10-20 13:02:29 +1100979 func(w io.Writer) io.Writer { return onlyWriter{w} },
Michael Chaten2a4818d2012-10-19 11:22:51 +1100980 func(w io.Writer) io.Writer { return w },
981 }
982
983 rs := []func(io.Reader) io.Reader{
984 iotest.DataErrReader,
985 func(r io.Reader) io.Reader { return r },
986 }
987
988 for ri, rfunc := range rs {
989 for wi, wfunc := range ws {
990 input := createTestInput(8192)
991 b := new(bytes.Buffer)
992 w := NewWriter(wfunc(b))
Brad Fitzpatricka18f4ab2014-01-27 11:05:01 -0800993 r := rfunc(bytes.NewReader(input))
Michael Chaten2a4818d2012-10-19 11:22:51 +1100994 if n, err := w.ReadFrom(r); err != nil || n != int64(len(input)) {
995 t.Errorf("ws[%d],rs[%d]: w.ReadFrom(r) = %d, %v, want %d, nil", wi, ri, n, err, len(input))
996 continue
997 }
Andrew Gerrand93c6d0e2013-07-25 11:29:13 +1000998 if err := w.Flush(); err != nil {
999 t.Errorf("Flush returned %v", err)
1000 continue
1001 }
Michael Chaten2a4818d2012-10-19 11:22:51 +11001002 if got, want := b.String(), string(input); got != want {
1003 t.Errorf("ws[%d], rs[%d]:\ngot %q\nwant %q\n", wi, ri, got, want)
1004 }
1005 }
1006 }
1007}
1008
1009type errorReaderFromTest struct {
1010 rn, wn int
1011 rerr, werr error
1012 expected error
1013}
1014
1015func (r errorReaderFromTest) Read(p []byte) (int, error) {
1016 return len(p) * r.rn, r.rerr
1017}
1018
1019func (w errorReaderFromTest) Write(p []byte) (int, error) {
1020 return len(p) * w.wn, w.werr
1021}
1022
1023var errorReaderFromTests = []errorReaderFromTest{
1024 {0, 1, io.EOF, nil, nil},
1025 {1, 1, io.EOF, nil, nil},
1026 {0, 1, io.ErrClosedPipe, nil, io.ErrClosedPipe},
1027 {0, 0, io.ErrClosedPipe, io.ErrShortWrite, io.ErrClosedPipe},
1028 {1, 0, nil, io.ErrShortWrite, io.ErrShortWrite},
1029}
1030
1031func TestWriterReadFromErrors(t *testing.T) {
1032 for i, rw := range errorReaderFromTests {
1033 w := NewWriter(rw)
1034 if _, err := w.ReadFrom(rw); err != rw.expected {
1035 t.Errorf("w.ReadFrom(errorReaderFromTests[%d]) = _, %v, want _,%v", i, err, rw.expected)
1036 }
1037 }
1038}
1039
Nigel Taoe55fdff2012-10-19 16:32:00 +11001040// TestWriterReadFromCounts tests that using io.Copy to copy into a
1041// bufio.Writer does not prematurely flush the buffer. For example, when
1042// buffering writes to a network socket, excessive network writes should be
1043// avoided.
1044func TestWriterReadFromCounts(t *testing.T) {
1045 var w0 writeCountingDiscard
1046 b0 := NewWriterSize(&w0, 1234)
1047 b0.WriteString(strings.Repeat("x", 1000))
1048 if w0 != 0 {
1049 t.Fatalf("write 1000 'x's: got %d writes, want 0", w0)
1050 }
1051 b0.WriteString(strings.Repeat("x", 200))
1052 if w0 != 0 {
1053 t.Fatalf("write 1200 'x's: got %d writes, want 0", w0)
1054 }
Nigel Tao0ba5ec52012-10-20 13:02:29 +11001055 io.Copy(b0, onlyReader{strings.NewReader(strings.Repeat("x", 30))})
Nigel Taoe55fdff2012-10-19 16:32:00 +11001056 if w0 != 0 {
1057 t.Fatalf("write 1230 'x's: got %d writes, want 0", w0)
1058 }
Nigel Tao0ba5ec52012-10-20 13:02:29 +11001059 io.Copy(b0, onlyReader{strings.NewReader(strings.Repeat("x", 9))})
Nigel Taoe55fdff2012-10-19 16:32:00 +11001060 if w0 != 1 {
1061 t.Fatalf("write 1239 'x's: got %d writes, want 1", w0)
1062 }
1063
1064 var w1 writeCountingDiscard
1065 b1 := NewWriterSize(&w1, 1234)
1066 b1.WriteString(strings.Repeat("x", 1200))
1067 b1.Flush()
1068 if w1 != 1 {
1069 t.Fatalf("flush 1200 'x's: got %d writes, want 1", w1)
1070 }
1071 b1.WriteString(strings.Repeat("x", 89))
1072 if w1 != 1 {
1073 t.Fatalf("write 1200 + 89 'x's: got %d writes, want 1", w1)
1074 }
Nigel Tao0ba5ec52012-10-20 13:02:29 +11001075 io.Copy(b1, onlyReader{strings.NewReader(strings.Repeat("x", 700))})
Nigel Taoe55fdff2012-10-19 16:32:00 +11001076 if w1 != 1 {
1077 t.Fatalf("write 1200 + 789 'x's: got %d writes, want 1", w1)
1078 }
Nigel Tao0ba5ec52012-10-20 13:02:29 +11001079 io.Copy(b1, onlyReader{strings.NewReader(strings.Repeat("x", 600))})
Nigel Taoe55fdff2012-10-19 16:32:00 +11001080 if w1 != 2 {
1081 t.Fatalf("write 1200 + 1389 'x's: got %d writes, want 2", w1)
1082 }
1083 b1.Flush()
1084 if w1 != 3 {
1085 t.Fatalf("flush 1200 + 1389 'x's: got %d writes, want 3", w1)
1086 }
1087}
1088
1089// A writeCountingDiscard is like ioutil.Discard and counts the number of times
1090// Write is called on it.
1091type writeCountingDiscard int
1092
1093func (w *writeCountingDiscard) Write(p []byte) (int, error) {
1094 *w++
1095 return len(p), nil
1096}
1097
Russ Coxf0d9ccb2012-12-10 17:25:31 -05001098type negativeReader int
1099
1100func (r *negativeReader) Read([]byte) (int, error) { return -1, nil }
1101
1102func TestNegativeRead(t *testing.T) {
1103 // should panic with a description pointing at the reader, not at itself.
1104 // (should NOT panic with slice index error, for example.)
1105 b := NewReader(new(negativeReader))
1106 defer func() {
1107 switch err := recover().(type) {
1108 case nil:
1109 t.Fatal("read did not panic")
1110 case error:
1111 if !strings.Contains(err.Error(), "reader returned negative count from Read") {
Rob Pike55ad7b92013-02-20 12:14:31 -08001112 t.Fatalf("wrong panic: %v", err)
Russ Coxf0d9ccb2012-12-10 17:25:31 -05001113 }
1114 default:
1115 t.Fatalf("unexpected panic value: %T(%v)", err, err)
1116 }
1117 }()
1118 b.Read(make([]byte, 100))
1119}
1120
Brad Fitzpatrickdc71ace2013-03-21 19:59:49 -07001121var errFake = errors.New("fake error")
1122
1123type errorThenGoodReader struct {
1124 didErr bool
1125 nread int
1126}
1127
1128func (r *errorThenGoodReader) Read(p []byte) (int, error) {
1129 r.nread++
1130 if !r.didErr {
1131 r.didErr = true
1132 return 0, errFake
1133 }
1134 return len(p), nil
1135}
1136
1137func TestReaderClearError(t *testing.T) {
1138 r := &errorThenGoodReader{}
1139 b := NewReader(r)
1140 buf := make([]byte, 1)
1141 if _, err := b.Read(nil); err != nil {
1142 t.Fatalf("1st nil Read = %v; want nil", err)
1143 }
1144 if _, err := b.Read(buf); err != errFake {
1145 t.Fatalf("1st Read = %v; want errFake", err)
1146 }
1147 if _, err := b.Read(nil); err != nil {
1148 t.Fatalf("2nd nil Read = %v; want nil", err)
1149 }
1150 if _, err := b.Read(buf); err != nil {
1151 t.Fatalf("3rd Read with buffer = %v; want nil", err)
1152 }
1153 if r.nread != 2 {
1154 t.Errorf("num reads = %d; want 2", r.nread)
1155 }
1156}
1157
Andrew Gerrand93c6d0e2013-07-25 11:29:13 +10001158// Test for golang.org/issue/5947
1159func TestWriterReadFromWhileFull(t *testing.T) {
1160 buf := new(bytes.Buffer)
1161 w := NewWriterSize(buf, 10)
1162
1163 // Fill buffer exactly.
1164 n, err := w.Write([]byte("0123456789"))
1165 if n != 10 || err != nil {
1166 t.Fatalf("Write returned (%v, %v), want (10, nil)", n, err)
1167 }
1168
1169 // Use ReadFrom to read in some data.
1170 n2, err := w.ReadFrom(strings.NewReader("abcdef"))
1171 if n2 != 6 || err != nil {
Rui Ueyamafa445842014-03-22 17:40:17 -07001172 t.Fatalf("ReadFrom returned (%v, %v), want (6, nil)", n2, err)
Andrew Gerrand93c6d0e2013-07-25 11:29:13 +10001173 }
1174}
1175
Rui Ueyama4ffc7992014-03-24 11:48:34 -07001176type emptyThenNonEmptyReader struct {
1177 r io.Reader
1178 n int
1179}
1180
1181func (r *emptyThenNonEmptyReader) Read(p []byte) (int, error) {
1182 if r.n <= 0 {
1183 return r.r.Read(p)
1184 }
1185 r.n--
1186 return 0, nil
1187}
1188
1189// Test for golang.org/issue/7611
1190func TestWriterReadFromUntilEOF(t *testing.T) {
1191 buf := new(bytes.Buffer)
1192 w := NewWriterSize(buf, 5)
1193
1194 // Partially fill buffer
1195 n, err := w.Write([]byte("0123"))
1196 if n != 4 || err != nil {
1197 t.Fatalf("Write returned (%v, %v), want (4, nil)", n, err)
1198 }
1199
1200 // Use ReadFrom to read in some data.
1201 r := &emptyThenNonEmptyReader{r: strings.NewReader("abcd"), n: 3}
1202 n2, err := w.ReadFrom(r)
1203 if n2 != 4 || err != nil {
1204 t.Fatalf("ReadFrom returned (%v, %v), want (4, nil)", n2, err)
1205 }
1206 w.Flush()
1207 if got, want := string(buf.Bytes()), "0123abcd"; got != want {
1208 t.Fatalf("buf.Bytes() returned %q, want %q", got, want)
1209 }
1210}
1211
1212func TestWriterReadFromErrNoProgress(t *testing.T) {
1213 buf := new(bytes.Buffer)
1214 w := NewWriterSize(buf, 5)
1215
1216 // Partially fill buffer
1217 n, err := w.Write([]byte("0123"))
1218 if n != 4 || err != nil {
1219 t.Fatalf("Write returned (%v, %v), want (4, nil)", n, err)
1220 }
1221
1222 // Use ReadFrom to read in some data.
1223 r := &emptyThenNonEmptyReader{r: strings.NewReader("abcd"), n: 100}
1224 n2, err := w.ReadFrom(r)
1225 if n2 != 0 || err != io.ErrNoProgress {
1226 t.Fatalf("buf.Bytes() returned (%v, %v), want (0, io.ErrNoProgress)", n2, err)
1227 }
1228}
1229
Brad Fitzpatrickede9aa92013-08-10 19:22:19 -07001230func TestReaderReset(t *testing.T) {
1231 r := NewReader(strings.NewReader("foo foo"))
1232 buf := make([]byte, 3)
1233 r.Read(buf)
1234 if string(buf) != "foo" {
1235 t.Errorf("buf = %q; want foo", buf)
1236 }
1237 r.Reset(strings.NewReader("bar bar"))
1238 all, err := ioutil.ReadAll(r)
1239 if err != nil {
1240 t.Fatal(err)
1241 }
1242 if string(all) != "bar bar" {
1243 t.Errorf("ReadAll = %q; want bar bar", all)
1244 }
1245}
1246
1247func TestWriterReset(t *testing.T) {
1248 var buf1, buf2 bytes.Buffer
1249 w := NewWriter(&buf1)
1250 w.WriteString("foo")
1251 w.Reset(&buf2) // and not flushed
1252 w.WriteString("bar")
1253 w.Flush()
1254 if buf1.String() != "" {
1255 t.Errorf("buf1 = %q; want empty", buf1.String())
1256 }
1257 if buf2.String() != "bar" {
1258 t.Errorf("buf2 = %q; want bar", buf2.String())
1259 }
1260}
1261
Michael Chatene289a2b2012-09-27 16:31:03 +10001262// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
1263type onlyReader struct {
Brad Fitzpatrickb00e4772014-02-27 10:48:36 -08001264 io.Reader
Michael Chatene289a2b2012-09-27 16:31:03 +10001265}
1266
1267// An onlyWriter only implements io.Writer, no matter what other methods the underlying implementation may have.
1268type onlyWriter struct {
Brad Fitzpatrickb00e4772014-02-27 10:48:36 -08001269 io.Writer
Michael Chatene289a2b2012-09-27 16:31:03 +10001270}
1271
1272func BenchmarkReaderCopyOptimal(b *testing.B) {
1273 // Optimal case is where the underlying reader implements io.WriterTo
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001274 srcBuf := bytes.NewBuffer(make([]byte, 8192))
1275 src := NewReader(srcBuf)
1276 dstBuf := new(bytes.Buffer)
1277 dst := onlyWriter{dstBuf}
Michael Chatene289a2b2012-09-27 16:31:03 +10001278 for i := 0; i < b.N; i++ {
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001279 srcBuf.Reset()
1280 src.Reset(srcBuf)
1281 dstBuf.Reset()
Michael Chatene289a2b2012-09-27 16:31:03 +10001282 io.Copy(dst, src)
1283 }
1284}
1285
1286func BenchmarkReaderCopyUnoptimal(b *testing.B) {
1287 // Unoptimal case is where the underlying reader doesn't implement io.WriterTo
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001288 srcBuf := bytes.NewBuffer(make([]byte, 8192))
1289 src := NewReader(onlyReader{srcBuf})
1290 dstBuf := new(bytes.Buffer)
1291 dst := onlyWriter{dstBuf}
Michael Chatene289a2b2012-09-27 16:31:03 +10001292 for i := 0; i < b.N; i++ {
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001293 srcBuf.Reset()
1294 src.Reset(onlyReader{srcBuf})
1295 dstBuf.Reset()
Michael Chatene289a2b2012-09-27 16:31:03 +10001296 io.Copy(dst, src)
1297 }
1298}
1299
1300func BenchmarkReaderCopyNoWriteTo(b *testing.B) {
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001301 srcBuf := bytes.NewBuffer(make([]byte, 8192))
1302 srcReader := NewReader(srcBuf)
1303 src := onlyReader{srcReader}
1304 dstBuf := new(bytes.Buffer)
1305 dst := onlyWriter{dstBuf}
Michael Chatene289a2b2012-09-27 16:31:03 +10001306 for i := 0; i < b.N; i++ {
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001307 srcBuf.Reset()
1308 srcReader.Reset(srcBuf)
1309 dstBuf.Reset()
Michael Chatene289a2b2012-09-27 16:31:03 +10001310 io.Copy(dst, src)
1311 }
1312}
Michael Chaten2a4818d2012-10-19 11:22:51 +11001313
Brad Fitzpatrickb00e4772014-02-27 10:48:36 -08001314func BenchmarkReaderWriteToOptimal(b *testing.B) {
1315 const bufSize = 16 << 10
1316 buf := make([]byte, bufSize)
1317 r := bytes.NewReader(buf)
1318 srcReader := NewReaderSize(onlyReader{r}, 1<<10)
1319 if _, ok := ioutil.Discard.(io.ReaderFrom); !ok {
1320 b.Fatal("ioutil.Discard doesn't support ReaderFrom")
1321 }
1322 for i := 0; i < b.N; i++ {
1323 r.Seek(0, 0)
1324 srcReader.Reset(onlyReader{r})
1325 n, err := srcReader.WriteTo(ioutil.Discard)
1326 if err != nil {
1327 b.Fatal(err)
1328 }
1329 if n != bufSize {
1330 b.Fatalf("n = %d; want %d", n, bufSize)
1331 }
1332 }
1333}
1334
Michael Chaten2a4818d2012-10-19 11:22:51 +11001335func BenchmarkWriterCopyOptimal(b *testing.B) {
1336 // Optimal case is where the underlying writer implements io.ReaderFrom
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001337 srcBuf := bytes.NewBuffer(make([]byte, 8192))
1338 src := onlyReader{srcBuf}
1339 dstBuf := new(bytes.Buffer)
1340 dst := NewWriter(dstBuf)
Michael Chaten2a4818d2012-10-19 11:22:51 +11001341 for i := 0; i < b.N; i++ {
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001342 srcBuf.Reset()
1343 dstBuf.Reset()
1344 dst.Reset(dstBuf)
Michael Chaten2a4818d2012-10-19 11:22:51 +11001345 io.Copy(dst, src)
1346 }
1347}
1348
1349func BenchmarkWriterCopyUnoptimal(b *testing.B) {
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001350 srcBuf := bytes.NewBuffer(make([]byte, 8192))
1351 src := onlyReader{srcBuf}
1352 dstBuf := new(bytes.Buffer)
1353 dst := NewWriter(onlyWriter{dstBuf})
Michael Chaten2a4818d2012-10-19 11:22:51 +11001354 for i := 0; i < b.N; i++ {
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001355 srcBuf.Reset()
1356 dstBuf.Reset()
1357 dst.Reset(onlyWriter{dstBuf})
Michael Chaten2a4818d2012-10-19 11:22:51 +11001358 io.Copy(dst, src)
1359 }
1360}
1361
1362func BenchmarkWriterCopyNoReadFrom(b *testing.B) {
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001363 srcBuf := bytes.NewBuffer(make([]byte, 8192))
1364 src := onlyReader{srcBuf}
1365 dstBuf := new(bytes.Buffer)
1366 dstWriter := NewWriter(dstBuf)
1367 dst := onlyWriter{dstWriter}
Michael Chaten2a4818d2012-10-19 11:22:51 +11001368 for i := 0; i < b.N; i++ {
Dmitriy Vyukov0ad2cd02014-01-23 15:13:21 -05001369 srcBuf.Reset()
1370 dstBuf.Reset()
1371 dstWriter.Reset(dstBuf)
Michael Chaten2a4818d2012-10-19 11:22:51 +11001372 io.Copy(dst, src)
1373 }
1374}
Brad Fitzpatrickb25a53a2013-05-17 15:16:06 -07001375
1376func BenchmarkReaderEmpty(b *testing.B) {
1377 b.ReportAllocs()
1378 str := strings.Repeat("x", 16<<10)
1379 for i := 0; i < b.N; i++ {
1380 br := NewReader(strings.NewReader(str))
1381 n, err := io.Copy(ioutil.Discard, br)
1382 if err != nil {
1383 b.Fatal(err)
1384 }
1385 if n != int64(len(str)) {
1386 b.Fatal("wrong length")
1387 }
1388 }
1389}
Brad Fitzpatrick99f67222013-05-21 15:51:49 -07001390
1391func BenchmarkWriterEmpty(b *testing.B) {
1392 b.ReportAllocs()
1393 str := strings.Repeat("x", 1<<10)
1394 bs := []byte(str)
1395 for i := 0; i < b.N; i++ {
1396 bw := NewWriter(ioutil.Discard)
1397 bw.Flush()
1398 bw.WriteByte('a')
1399 bw.Flush()
1400 bw.WriteRune('B')
1401 bw.Flush()
1402 bw.Write(bs)
1403 bw.Flush()
1404 bw.WriteString(str)
1405 bw.Flush()
1406 }
1407}
1408
1409func BenchmarkWriterFlush(b *testing.B) {
1410 b.ReportAllocs()
1411 bw := NewWriter(ioutil.Discard)
1412 str := strings.Repeat("x", 50)
1413 for i := 0; i < b.N; i++ {
1414 bw.WriteString(str)
1415 bw.Flush()
1416 }
1417}