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.
16 // An version of bytes.Buffer without ReadFrom and WriteTo
19 ReaderFrom
// conflicts with and hides bytes.Buffer's ReaderFrom.
20 WriterTo
// conflicts with and hides bytes.Buffer's WriterTo.
23 // Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy, CopyBuffer and CopyN.
25 func TestCopy(t
*testing
.T
) {
28 rb
.WriteString("hello, world.")
30 if wb
.String() != "hello, world." {
31 t
.Errorf("Copy did not work properly")
35 func TestCopyBuffer(t
*testing
.T
) {
38 rb
.WriteString("hello, world.")
39 CopyBuffer(wb
, rb
, make([]byte, 1)) // Tiny buffer to keep it honest.
40 if wb
.String() != "hello, world." {
41 t
.Errorf("CopyBuffer did not work properly")
45 func TestCopyBufferNil(t
*testing
.T
) {
48 rb
.WriteString("hello, world.")
49 CopyBuffer(wb
, rb
, nil) // Should allocate a buffer.
50 if wb
.String() != "hello, world." {
51 t
.Errorf("CopyBuffer did not work properly")
55 func TestCopyReadFrom(t
*testing
.T
) {
57 wb
:= new(bytes
.Buffer
) // implements ReadFrom.
58 rb
.WriteString("hello, world.")
60 if wb
.String() != "hello, world." {
61 t
.Errorf("Copy did not work properly")
65 func TestCopyWriteTo(t
*testing
.T
) {
66 rb
:= new(bytes
.Buffer
) // implements WriteTo.
68 rb
.WriteString("hello, world.")
70 if wb
.String() != "hello, world." {
71 t
.Errorf("Copy did not work properly")
75 // Version of bytes.Buffer that checks whether WriteTo was called or not
76 type writeToChecker
struct {
81 func (wt
*writeToChecker
) WriteTo(w Writer
) (int64, error
) {
82 wt
.writeToCalled
= true
83 return wt
.Buffer
.WriteTo(w
)
86 // It's preferable to choose WriterTo over ReaderFrom, since a WriterTo can issue one large write,
87 // while the ReaderFrom must read until EOF, potentially allocating when running out of buffer.
88 // Make sure that we choose WriterTo when both are implemented.
89 func TestCopyPriority(t
*testing
.T
) {
90 rb
:= new(writeToChecker
)
91 wb
:= new(bytes
.Buffer
)
92 rb
.WriteString("hello, world.")
94 if wb
.String() != "hello, world." {
95 t
.Errorf("Copy did not work properly")
96 } else if !rb
.writeToCalled
{
97 t
.Errorf("WriteTo was not prioritized over ReadFrom")
101 type zeroErrReader
struct {
105 func (r zeroErrReader
) Read(p
[]byte) (int, error
) {
106 return copy(p
, []byte{0}), r
.err
109 type errWriter
struct {
113 func (w errWriter
) Write([]byte) (int, error
) {
117 // In case a Read results in an error with non-zero bytes read, and
118 // the subsequent Write also results in an error, the error from Write
119 // is returned, as it is the one that prevented progressing further.
120 func TestCopyReadErrWriteErr(t
*testing
.T
) {
121 er
, ew
:= errors
.New("readError"), errors
.New("writeError")
122 r
, w
:= zeroErrReader
{err
: er
}, errWriter
{err
: ew
}
124 if n
!= 0 || err
!= ew
{
125 t
.Errorf("Copy(zeroErrReader, errWriter) = %d, %v; want 0, writeError", n
, err
)
129 func TestCopyN(t
*testing
.T
) {
132 rb
.WriteString("hello, world.")
134 if wb
.String() != "hello" {
135 t
.Errorf("CopyN did not work properly")
139 func TestCopyNReadFrom(t
*testing
.T
) {
141 wb
:= new(bytes
.Buffer
) // implements ReadFrom.
142 rb
.WriteString("hello")
144 if wb
.String() != "hello" {
145 t
.Errorf("CopyN did not work properly")
149 func TestCopyNWriteTo(t
*testing
.T
) {
150 rb
:= new(bytes
.Buffer
) // implements WriteTo.
152 rb
.WriteString("hello, world.")
154 if wb
.String() != "hello" {
155 t
.Errorf("CopyN did not work properly")
159 type noReadFrom
struct {
163 func (w
*noReadFrom
) Write(p
[]byte) (n
int, err error
) {
167 type wantedAndErrReader
struct{}
169 func (wantedAndErrReader
) Read(p
[]byte) (int, error
) {
170 return len(p
), errors
.New("wantedAndErrReader error")
173 func TestCopyNEOF(t
*testing
.T
) {
174 // Test that EOF behavior is the same regardless of whether
175 // argument to CopyN has ReadFrom.
177 b
:= new(bytes
.Buffer
)
179 n
, err
:= CopyN(&noReadFrom
{b
}, strings
.NewReader("foo"), 3)
180 if n
!= 3 || err
!= nil {
181 t
.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n
, err
)
184 n
, err
= CopyN(&noReadFrom
{b
}, strings
.NewReader("foo"), 4)
185 if n
!= 3 || err
!= EOF
{
186 t
.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n
, err
)
189 n
, err
= CopyN(b
, strings
.NewReader("foo"), 3) // b has read from
190 if n
!= 3 || err
!= nil {
191 t
.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n
, err
)
194 n
, err
= CopyN(b
, strings
.NewReader("foo"), 4) // b has read from
195 if n
!= 3 || err
!= EOF
{
196 t
.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n
, err
)
199 n
, err
= CopyN(b
, wantedAndErrReader
{}, 5)
200 if n
!= 5 || err
!= nil {
201 t
.Errorf("CopyN(bytes.Buffer, wantedAndErrReader, 5) = %d, %v; want 5, nil", n
, err
)
204 n
, err
= CopyN(&noReadFrom
{b
}, wantedAndErrReader
{}, 5)
205 if n
!= 5 || err
!= nil {
206 t
.Errorf("CopyN(noReadFrom, wantedAndErrReader, 5) = %d, %v; want 5, nil", n
, err
)
210 func TestReadAtLeast(t
*testing
.T
) {
212 testReadAtLeast(t
, &rb
)
215 // A version of bytes.Buffer that returns n > 0, err on Read
216 // when the input is exhausted.
217 type dataAndErrorBuffer
struct {
222 func (r
*dataAndErrorBuffer
) Read(p
[]byte) (n
int, err error
) {
223 n
, err
= r
.Buffer
.Read(p
)
224 if n
> 0 && r
.Buffer
.Len() == 0 && err
== nil {
230 func TestReadAtLeastWithDataAndEOF(t
*testing
.T
) {
231 var rb dataAndErrorBuffer
233 testReadAtLeast(t
, &rb
)
236 func TestReadAtLeastWithDataAndError(t
*testing
.T
) {
237 var rb dataAndErrorBuffer
238 rb
.err
= fmt
.Errorf("fake error")
239 testReadAtLeast(t
, &rb
)
242 func testReadAtLeast(t
*testing
.T
, rb ReadWriter
) {
243 rb
.Write([]byte("0123"))
244 buf
:= make([]byte, 2)
245 n
, err
:= ReadAtLeast(rb
, buf
, 2)
249 n
, err
= ReadAtLeast(rb
, buf
, 4)
250 if err
!= ErrShortBuffer
{
251 t
.Errorf("expected ErrShortBuffer got %v", err
)
254 t
.Errorf("expected to have read 0 bytes, got %v", n
)
256 n
, err
= ReadAtLeast(rb
, buf
, 1)
261 t
.Errorf("expected to have read 2 bytes, got %v", n
)
263 n
, err
= ReadAtLeast(rb
, buf
, 2)
265 t
.Errorf("expected EOF, got %v", err
)
268 t
.Errorf("expected to have read 0 bytes, got %v", n
)
270 rb
.Write([]byte("4"))
271 n
, err
= ReadAtLeast(rb
, buf
, 2)
272 want
:= ErrUnexpectedEOF
273 if rb
, ok
:= rb
.(*dataAndErrorBuffer
); ok
&& rb
.err
!= EOF
{
277 t
.Errorf("expected %v, got %v", want
, err
)
280 t
.Errorf("expected to have read 1 bytes, got %v", n
)
284 func TestTeeReader(t
*testing
.T
) {
285 src
:= []byte("hello, world")
286 dst
:= make([]byte, len(src
))
287 rb
:= bytes
.NewBuffer(src
)
288 wb
:= new(bytes
.Buffer
)
289 r
:= TeeReader(rb
, wb
)
290 if n
, err
:= ReadFull(r
, dst
); err
!= nil || n
!= len(src
) {
291 t
.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n
, err
, len(src
))
293 if !bytes
.Equal(dst
, src
) {
294 t
.Errorf("bytes read = %q want %q", dst
, src
)
296 if !bytes
.Equal(wb
.Bytes(), src
) {
297 t
.Errorf("bytes written = %q want %q", wb
.Bytes(), src
)
299 if n
, err
:= r
.Read(dst
); n
!= 0 || err
!= EOF
{
300 t
.Errorf("r.Read at EOF = %d, %v want 0, EOF", n
, err
)
302 rb
= bytes
.NewBuffer(src
)
305 r
= TeeReader(rb
, pw
)
306 if n
, err
:= ReadFull(r
, dst
); n
!= 0 || err
!= ErrClosedPipe
{
307 t
.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n
, err
)
311 func TestSectionReader_ReadAt(t
*testing
.T
) {
312 dat
:= "a long sample data, 1234567890"
322 {data
: "", off
: 0, n
: 10, bufLen
: 2, at
: 0, exp
: "", err
: EOF
},
323 {data
: dat
, off
: 0, n
: len(dat
), bufLen
: 0, at
: 0, exp
: "", err
: nil},
324 {data
: dat
, off
: len(dat
), n
: 1, bufLen
: 1, at
: 0, exp
: "", err
: EOF
},
325 {data
: dat
, off
: 0, n
: len(dat
) + 2, bufLen
: len(dat
), at
: 0, exp
: dat
, err
: nil},
326 {data
: dat
, off
: 0, n
: len(dat
), bufLen
: len(dat
) / 2, at
: 0, exp
: dat
[:len(dat
)/2], err
: nil},
327 {data
: dat
, off
: 0, n
: len(dat
), bufLen
: len(dat
), at
: 0, exp
: dat
, err
: nil},
328 {data
: dat
, off
: 0, n
: len(dat
), bufLen
: len(dat
) / 2, at
: 2, exp
: dat
[2 : 2+len(dat
)/2], err
: nil},
329 {data
: dat
, off
: 3, n
: len(dat
), bufLen
: len(dat
) / 2, at
: 2, exp
: dat
[5 : 5+len(dat
)/2], err
: nil},
330 {data
: dat
, off
: 3, n
: len(dat
) / 2, bufLen
: len(dat
)/2 - 2, at
: 2, exp
: dat
[5 : 5+len(dat
)/2-2], err
: nil},
331 {data
: dat
, off
: 3, n
: len(dat
) / 2, bufLen
: len(dat
)/2 + 2, at
: 2, exp
: dat
[5 : 5+len(dat
)/2-2], err
: EOF
},
332 {data
: dat
, off
: 0, n
: 0, bufLen
: 0, at
: -1, exp
: "", err
: EOF
},
333 {data
: dat
, off
: 0, n
: 0, bufLen
: 0, at
: 1, exp
: "", err
: EOF
},
335 for i
, tt
:= range tests
{
336 r
:= strings
.NewReader(tt
.data
)
337 s
:= NewSectionReader(r
, int64(tt
.off
), int64(tt
.n
))
338 buf
:= make([]byte, tt
.bufLen
)
339 if n
, err
:= s
.ReadAt(buf
, int64(tt
.at
)); n
!= len(tt
.exp
) ||
string(buf
[:n
]) != tt
.exp || err
!= tt
.err
{
340 t
.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i
, tt
.at
, buf
[:n
], err
, tt
.exp
, tt
.err
)
345 func TestSectionReader_Seek(t
*testing
.T
) {
346 // Verifies that NewSectionReader's Seeker behaves like bytes.NewReader (which is like strings.NewReader)
347 br
:= bytes
.NewReader([]byte("foo"))
348 sr
:= NewSectionReader(br
, 0, int64(len("foo")))
350 for _
, whence
:= range []int{SeekStart
, SeekCurrent
, SeekEnd
} {
351 for offset
:= int64(-3); offset
<= 4; offset
++ {
352 brOff
, brErr
:= br
.Seek(offset
, whence
)
353 srOff
, srErr
:= sr
.Seek(offset
, whence
)
354 if (brErr
!= nil) != (srErr
!= nil) || brOff
!= srOff
{
355 t
.Errorf("For whence %d, offset %d: bytes.Reader.Seek = (%v, %v) != SectionReader.Seek = (%v, %v)",
356 whence
, offset
, brOff
, brErr
, srErr
, srOff
)
361 // And verify we can just seek past the end and get an EOF
362 got
, err
:= sr
.Seek(100, SeekStart
)
363 if err
!= nil || got
!= 100 {
364 t
.Errorf("Seek = %v, %v; want 100, nil", got
, err
)
367 n
, err
:= sr
.Read(make([]byte, 10))
368 if n
!= 0 || err
!= EOF
{
369 t
.Errorf("Read = %v, %v; want 0, EOF", n
, err
)
373 func TestSectionReader_Size(t
*testing
.T
) {
378 {"a long sample data, 1234567890", 30},
382 for _
, tt
:= range tests
{
383 r
:= strings
.NewReader(tt
.data
)
384 sr
:= NewSectionReader(r
, 0, int64(len(tt
.data
)))
385 if got
:= sr
.Size(); got
!= tt
.want
{
386 t
.Errorf("Size = %v; want %v", got
, tt
.want
)