1 // Copyright 2010 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.
20 func TestMultiReader(t
*testing
.T
) {
24 withFooBar
:= func(tests
func()) {
25 r1
:= strings
.NewReader("foo ")
26 r2
:= strings
.NewReader("")
27 r3
:= strings
.NewReader("bar")
28 mr
= MultiReader(r1
, r2
, r3
)
29 buf
= make([]byte, 20)
32 expectRead
:= func(size
int, expected
string, eerr error
) {
34 n
, gerr
:= mr
.Read(buf
[0:size
])
35 if n
!= len(expected
) {
36 t
.Errorf("#%d, expected %d bytes; got %d",
37 nread
, len(expected
), n
)
39 got
:= string(buf
[0:n
])
41 t
.Errorf("#%d, expected %q; got %q",
45 t
.Errorf("#%d, expected error %v; got %v",
51 expectRead(2, "fo", nil)
52 expectRead(5, "o ", nil)
53 expectRead(5, "bar", nil)
54 expectRead(5, "", EOF
)
57 expectRead(4, "foo ", nil)
58 expectRead(1, "b", nil)
59 expectRead(3, "ar", nil)
60 expectRead(1, "", EOF
)
63 expectRead(5, "foo ", nil)
67 func TestMultiWriter(t
*testing
.T
) {
68 sink
:= new(bytes
.Buffer
)
69 // Hide bytes.Buffer's WriteString method:
70 testMultiWriter(t
, struct {
76 func TestMultiWriter_String(t
*testing
.T
) {
77 testMultiWriter(t
, new(bytes
.Buffer
))
80 // test that a multiWriter.WriteString calls results in at most 1 allocation,
81 // even if multiple targets don't support WriteString.
82 func TestMultiWriter_WriteStringSingleAlloc(t
*testing
.T
) {
83 t
.Skip("skipping on gccgo until we have escape analysis")
84 var sink1
, sink2 bytes
.Buffer
85 type simpleWriter
struct { // hide bytes.Buffer's WriteString
88 mw
:= MultiWriter(simpleWriter
{&sink1
}, simpleWriter
{&sink2
})
89 allocs
:= int(testing
.AllocsPerRun(1000, func() {
90 WriteString(mw
, "foo")
93 t
.Errorf("num allocations = %d; want 1", allocs
)
97 type writeStringChecker
struct{ called
bool }
99 func (c
*writeStringChecker
) WriteString(s
string) (n
int, err error
) {
104 func (c
*writeStringChecker
) Write(p
[]byte) (n
int, err error
) {
108 func TestMultiWriter_StringCheckCall(t
*testing
.T
) {
109 var c writeStringChecker
110 mw
:= MultiWriter(&c
)
111 WriteString(mw
, "foo")
113 t
.Error("did not see WriteString call to writeStringChecker")
117 func testMultiWriter(t
*testing
.T
, sink
interface {
122 mw
:= MultiWriter(sha1
, sink
)
124 sourceString
:= "My input text."
125 source
:= strings
.NewReader(sourceString
)
126 written
, err
:= Copy(mw
, source
)
128 if written
!= int64(len(sourceString
)) {
129 t
.Errorf("short write of %d, not %d", written
, len(sourceString
))
133 t
.Errorf("unexpected error: %v", err
)
136 sha1hex
:= fmt
.Sprintf("%x", sha1
.Sum(nil))
137 if sha1hex
!= "01cb303fa8c30a64123067c5aa6284ba7ec2d31b" {
138 t
.Error("incorrect sha1 value")
141 if sink
.String() != sourceString
{
142 t
.Errorf("expected %q; got %q", sourceString
, sink
.String())
146 // writerFunc is an io.Writer implemented by the underlying func.
147 type writerFunc
func(p
[]byte) (int, error
)
149 func (f writerFunc
) Write(p
[]byte) (int, error
) {
153 // Test that MultiWriter properly flattens chained multiWriters,
154 func TestMultiWriterSingleChainFlatten(t
*testing
.T
) {
155 pc
:= make([]uintptr, 1000) // 1000 should fit the full stack
156 n
:= runtime
.Callers(0, pc
)
157 var myDepth
= callDepth(pc
[:n
])
158 var writeDepth
int // will contain the depth from which writerFunc.Writer was called
159 var w Writer
= MultiWriter(writerFunc(func(p
[]byte) (int, error
) {
160 n
:= runtime
.Callers(1, pc
)
161 writeDepth
+= callDepth(pc
[:n
])
166 // chain a bunch of multiWriters
167 for i
:= 0; i
< 100; i
++ {
171 mw
= MultiWriter(w
, mw
, w
, mw
)
172 mw
.Write(nil) // don't care about errors, just want to check the call-depth for Write
174 if writeDepth
!= 4*(myDepth
+2) { // 2 should be multiWriter.Write and writerFunc.Write
175 t
.Errorf("multiWriter did not flatten chained multiWriters: expected writeDepth %d, got %d",
176 4*(myDepth
+2), writeDepth
)
180 func TestMultiWriterError(t
*testing
.T
) {
181 f1
:= writerFunc(func(p
[]byte) (int, error
) {
182 return len(p
) / 2, ErrShortWrite
184 f2
:= writerFunc(func(p
[]byte) (int, error
) {
185 t
.Errorf("MultiWriter called f2.Write")
188 w
:= MultiWriter(f1
, f2
)
189 n
, err
:= w
.Write(make([]byte, 100))
190 if n
!= 50 || err
!= ErrShortWrite
{
191 t
.Errorf("Write = %d, %v, want 50, ErrShortWrite", n
, err
)
195 // Test that MultiReader copies the input slice and is insulated from future modification.
196 func TestMultiReaderCopy(t
*testing
.T
) {
197 slice
:= []Reader
{strings
.NewReader("hello world")}
198 r
:= MultiReader(slice
...)
200 data
, err
:= ioutil
.ReadAll(r
)
201 if err
!= nil ||
string(data
) != "hello world" {
202 t
.Errorf("ReadAll() = %q, %v, want %q, nil", data
, err
, "hello world")
206 // Test that MultiWriter copies the input slice and is insulated from future modification.
207 func TestMultiWriterCopy(t
*testing
.T
) {
209 slice
:= []Writer
{&buf
}
210 w
:= MultiWriter(slice
...)
212 n
, err
:= w
.Write([]byte("hello world"))
213 if err
!= nil || n
!= 11 {
214 t
.Errorf("Write(`hello world`) = %d, %v, want 11, nil", n
, err
)
216 if buf
.String() != "hello world" {
217 t
.Errorf("buf.String() = %q, want %q", buf
.String(), "hello world")
221 // readerFunc is an io.Reader implemented by the underlying func.
222 type readerFunc
func(p
[]byte) (int, error
)
224 func (f readerFunc
) Read(p
[]byte) (int, error
) {
228 // callDepth returns the logical call depth for the given PCs.
229 func callDepth(callers
[]uintptr) (depth
int) {
230 frames
:= runtime
.CallersFrames(callers
)
233 _
, more
= frames
.Next()
239 // Test that MultiReader properly flattens chained multiReaders when Read is called
240 func TestMultiReaderFlatten(t
*testing
.T
) {
241 pc
:= make([]uintptr, 1000) // 1000 should fit the full stack
242 n
:= runtime
.Callers(0, pc
)
243 var myDepth
= callDepth(pc
[:n
])
244 var readDepth
int // will contain the depth from which fakeReader.Read was called
245 var r Reader
= MultiReader(readerFunc(func(p
[]byte) (int, error
) {
246 n
:= runtime
.Callers(1, pc
)
247 readDepth
= callDepth(pc
[:n
])
248 return 0, errors
.New("irrelevant")
251 // chain a bunch of multiReaders
252 for i
:= 0; i
< 100; i
++ {
256 r
.Read(nil) // don't care about errors, just want to check the call-depth for Read
258 if readDepth
!= myDepth
+2 { // 2 should be multiReader.Read and fakeReader.Read
259 t
.Errorf("multiReader did not flatten chained multiReaders: expected readDepth %d, got %d",
260 myDepth
+2, readDepth
)
264 // byteAndEOFReader is a Reader which reads one byte (the underlying
265 // byte) and io.EOF at once in its Read call.
266 type byteAndEOFReader
byte
268 func (b byteAndEOFReader
) Read(p
[]byte) (n
int, err error
) {
270 // Read(0 bytes) is useless. We expect no such useless
271 // calls in this test.
272 panic("unexpected call")
278 // This used to yield bytes forever; issue 16795.
279 func TestMultiReaderSingleByteWithEOF(t
*testing
.T
) {
280 got
, err
:= ioutil
.ReadAll(LimitReader(MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10))
285 if string(got
) != want
{
286 t
.Errorf("got %q; want %q", got
, want
)
290 // Test that a reader returning (n, EOF) at the end of an MultiReader
291 // chain continues to return EOF on its final read, rather than
292 // yielding a (0, EOF).
293 func TestMultiReaderFinalEOF(t
*testing
.T
) {
294 r
:= MultiReader(bytes
.NewReader(nil), byteAndEOFReader('a'))
295 buf
:= make([]byte, 2)
296 n
, err
:= r
.Read(buf
)
297 if n
!= 1 || err
!= EOF
{
298 t
.Errorf("got %v, %v; want 1, EOF", n
, err
)
302 func TestMultiReaderFreesExhaustedReaders(t
*testing
.T
) {
303 if runtime
.Compiler
== "gccgo" {
304 t
.Skip("skipping finalizer test on gccgo with conservative GC")
308 closed := make(chan struct{})
309 // The closure ensures that we don't have a live reference to buf1
310 // on our stack after MultiReader is inlined (Issue 18819). This
311 // is a work around for a limitation in liveness analysis.
313 buf1
:= bytes
.NewReader([]byte("foo"))
314 buf2
:= bytes
.NewReader([]byte("bar"))
315 mr
= MultiReader(buf1
, buf2
)
316 runtime
.SetFinalizer(buf1
, func(*bytes
.Reader
) {
321 buf
:= make([]byte, 4)
322 if n
, err
:= ReadFull(mr
, buf
); err
!= nil ||
string(buf
) != "foob" {
323 t
.Fatalf(`ReadFull = %d (%q), %v; want 3, "foo", nil`, n
, buf
[:n
], err
)
329 case <-time
.After(5 * time
.Second
):
330 t
.Fatal("timeout waiting for collection of buf1")
333 if n
, err
:= ReadFull(mr
, buf
[:2]); err
!= nil ||
string(buf
[:2]) != "ar" {
334 t
.Fatalf(`ReadFull = %d (%q), %v; want 2, "ar", nil`, n
, buf
[:n
], err
)
338 func TestInterleavedMultiReader(t
*testing
.T
) {
339 r1
:= strings
.NewReader("123")
340 r2
:= strings
.NewReader("45678")
342 mr1
:= MultiReader(r1
, r2
)
343 mr2
:= MultiReader(mr1
)
345 buf
:= make([]byte, 4)
347 // Have mr2 use mr1's []Readers.
348 // Consume r1 (and clear it for GC to handle) and consume part of r2.
349 n
, err
:= ReadFull(mr2
, buf
)
350 if got
:= string(buf
[:n
]); got
!= "1234" || err
!= nil {
351 t
.Errorf(`ReadFull(mr2) = (%q, %v), want ("1234", nil)`, got
, err
)
354 // Consume the rest of r2 via mr1.
355 // This should not panic even though mr2 cleared r1.
356 n
, err
= ReadFull(mr1
, buf
)
357 if got
:= string(buf
[:n
]); got
!= "5678" || err
!= nil {
358 t
.Errorf(`ReadFull(mr1) = (%q, %v), want ("5678", nil)`, got
, err
)