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.
19 func TestMultiReader(t
*testing
.T
) {
23 withFooBar
:= func(tests
func()) {
24 r1
:= strings
.NewReader("foo ")
25 r2
:= strings
.NewReader("")
26 r3
:= strings
.NewReader("bar")
27 mr
= MultiReader(r1
, r2
, r3
)
28 buf
= make([]byte, 20)
31 expectRead
:= func(size
int, expected
string, eerr error
) {
33 n
, gerr
:= mr
.Read(buf
[0:size
])
34 if n
!= len(expected
) {
35 t
.Errorf("#%d, expected %d bytes; got %d",
36 nread
, len(expected
), n
)
38 got
:= string(buf
[0:n
])
40 t
.Errorf("#%d, expected %q; got %q",
44 t
.Errorf("#%d, expected error %v; got %v",
50 expectRead(2, "fo", nil)
51 expectRead(5, "o ", nil)
52 expectRead(5, "bar", nil)
53 expectRead(5, "", EOF
)
56 expectRead(4, "foo ", nil)
57 expectRead(1, "b", nil)
58 expectRead(3, "ar", nil)
59 expectRead(1, "", EOF
)
62 expectRead(5, "foo ", nil)
66 func TestMultiWriter(t
*testing
.T
) {
67 sink
:= new(bytes
.Buffer
)
68 // Hide bytes.Buffer's WriteString method:
69 testMultiWriter(t
, struct {
75 func TestMultiWriter_String(t
*testing
.T
) {
76 testMultiWriter(t
, new(bytes
.Buffer
))
79 // Test that a multiWriter.WriteString calls results in at most 1 allocation,
80 // even if multiple targets don't support WriteString.
81 func TestMultiWriter_WriteStringSingleAlloc(t
*testing
.T
) {
82 t
.Skip("skipping on gccgo until we have escape analysis")
83 var sink1
, sink2 bytes
.Buffer
84 type simpleWriter
struct { // hide bytes.Buffer's WriteString
87 mw
:= MultiWriter(simpleWriter
{&sink1
}, simpleWriter
{&sink2
})
88 allocs
:= int(testing
.AllocsPerRun(1000, func() {
89 WriteString(mw
, "foo")
92 t
.Errorf("num allocations = %d; want 1", allocs
)
96 type writeStringChecker
struct{ called
bool }
98 func (c
*writeStringChecker
) WriteString(s
string) (n
int, err error
) {
103 func (c
*writeStringChecker
) Write(p
[]byte) (n
int, err error
) {
107 func TestMultiWriter_StringCheckCall(t
*testing
.T
) {
108 var c writeStringChecker
109 mw
:= MultiWriter(&c
)
110 WriteString(mw
, "foo")
112 t
.Error("did not see WriteString call to writeStringChecker")
116 func testMultiWriter(t
*testing
.T
, sink
interface {
121 mw
:= MultiWriter(sha1
, sink
)
123 sourceString
:= "My input text."
124 source
:= strings
.NewReader(sourceString
)
125 written
, err
:= Copy(mw
, source
)
127 if written
!= int64(len(sourceString
)) {
128 t
.Errorf("short write of %d, not %d", written
, len(sourceString
))
132 t
.Errorf("unexpected error: %v", err
)
135 sha1hex
:= fmt
.Sprintf("%x", sha1
.Sum(nil))
136 if sha1hex
!= "01cb303fa8c30a64123067c5aa6284ba7ec2d31b" {
137 t
.Error("incorrect sha1 value")
140 if sink
.String() != sourceString
{
141 t
.Errorf("expected %q; got %q", sourceString
, sink
.String())
145 // writerFunc is a Writer implemented by the underlying func.
146 type writerFunc
func(p
[]byte) (int, error
)
148 func (f writerFunc
) Write(p
[]byte) (int, error
) {
152 // Test that MultiWriter properly flattens chained multiWriters.
153 func TestMultiWriterSingleChainFlatten(t
*testing
.T
) {
154 pc
:= make([]uintptr, 1000) // 1000 should fit the full stack
155 n
:= runtime
.Callers(0, pc
)
156 var myDepth
= callDepth(pc
[:n
])
157 var writeDepth
int // will contain the depth from which writerFunc.Writer was called
158 var w Writer
= MultiWriter(writerFunc(func(p
[]byte) (int, error
) {
159 n
:= runtime
.Callers(1, pc
)
160 writeDepth
+= callDepth(pc
[:n
])
165 // chain a bunch of multiWriters
166 for i
:= 0; i
< 100; i
++ {
170 mw
= MultiWriter(w
, mw
, w
, mw
)
171 mw
.Write(nil) // don't care about errors, just want to check the call-depth for Write
173 if writeDepth
!= 4*(myDepth
+2) { // 2 should be multiWriter.Write and writerFunc.Write
174 t
.Errorf("multiWriter did not flatten chained multiWriters: expected writeDepth %d, got %d",
175 4*(myDepth
+2), writeDepth
)
179 func TestMultiWriterError(t
*testing
.T
) {
180 f1
:= writerFunc(func(p
[]byte) (int, error
) {
181 return len(p
) / 2, ErrShortWrite
183 f2
:= writerFunc(func(p
[]byte) (int, error
) {
184 t
.Errorf("MultiWriter called f2.Write")
187 w
:= MultiWriter(f1
, f2
)
188 n
, err
:= w
.Write(make([]byte, 100))
189 if n
!= 50 || err
!= ErrShortWrite
{
190 t
.Errorf("Write = %d, %v, want 50, ErrShortWrite", n
, err
)
194 // Test that MultiReader copies the input slice and is insulated from future modification.
195 func TestMultiReaderCopy(t
*testing
.T
) {
196 slice
:= []Reader
{strings
.NewReader("hello world")}
197 r
:= MultiReader(slice
...)
199 data
, err
:= ReadAll(r
)
200 if err
!= nil ||
string(data
) != "hello world" {
201 t
.Errorf("ReadAll() = %q, %v, want %q, nil", data
, err
, "hello world")
205 // Test that MultiWriter copies the input slice and is insulated from future modification.
206 func TestMultiWriterCopy(t
*testing
.T
) {
208 slice
:= []Writer
{&buf
}
209 w
:= MultiWriter(slice
...)
211 n
, err
:= w
.Write([]byte("hello world"))
212 if err
!= nil || n
!= 11 {
213 t
.Errorf("Write(`hello world`) = %d, %v, want 11, nil", n
, err
)
215 if buf
.String() != "hello world" {
216 t
.Errorf("buf.String() = %q, want %q", buf
.String(), "hello world")
220 // readerFunc is a Reader implemented by the underlying func.
221 type readerFunc
func(p
[]byte) (int, error
)
223 func (f readerFunc
) Read(p
[]byte) (int, error
) {
227 // callDepth returns the logical call depth for the given PCs.
228 func callDepth(callers
[]uintptr) (depth
int) {
229 frames
:= runtime
.CallersFrames(callers
)
232 _
, more
= frames
.Next()
238 // Test that MultiReader properly flattens chained multiReaders when Read is called
239 func TestMultiReaderFlatten(t
*testing
.T
) {
240 pc
:= make([]uintptr, 1000) // 1000 should fit the full stack
241 n
:= runtime
.Callers(0, pc
)
242 var myDepth
= callDepth(pc
[:n
])
243 var readDepth
int // will contain the depth from which fakeReader.Read was called
244 var r Reader
= MultiReader(readerFunc(func(p
[]byte) (int, error
) {
245 n
:= runtime
.Callers(1, pc
)
246 readDepth
= callDepth(pc
[:n
])
247 return 0, errors
.New("irrelevant")
250 // chain a bunch of multiReaders
251 for i
:= 0; i
< 100; i
++ {
255 r
.Read(nil) // don't care about errors, just want to check the call-depth for Read
257 if readDepth
!= myDepth
+2 { // 2 should be multiReader.Read and fakeReader.Read
258 t
.Errorf("multiReader did not flatten chained multiReaders: expected readDepth %d, got %d",
259 myDepth
+2, readDepth
)
263 // byteAndEOFReader is a Reader which reads one byte (the underlying
264 // byte) and EOF at once in its Read call.
265 type byteAndEOFReader
byte
267 func (b byteAndEOFReader
) Read(p
[]byte) (n
int, err error
) {
269 // Read(0 bytes) is useless. We expect no such useless
270 // calls in this test.
271 panic("unexpected call")
277 // This used to yield bytes forever; issue 16795.
278 func TestMultiReaderSingleByteWithEOF(t
*testing
.T
) {
279 got
, err
:= ReadAll(LimitReader(MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10))
284 if string(got
) != want
{
285 t
.Errorf("got %q; want %q", got
, want
)
289 // Test that a reader returning (n, EOF) at the end of a MultiReader
290 // chain continues to return EOF on its final read, rather than
291 // yielding a (0, EOF).
292 func TestMultiReaderFinalEOF(t
*testing
.T
) {
293 r
:= MultiReader(bytes
.NewReader(nil), byteAndEOFReader('a'))
294 buf
:= make([]byte, 2)
295 n
, err
:= r
.Read(buf
)
296 if n
!= 1 || err
!= EOF
{
297 t
.Errorf("got %v, %v; want 1, EOF", n
, err
)
301 func TestMultiReaderFreesExhaustedReaders(t
*testing
.T
) {
302 if runtime
.Compiler
== "gccgo" {
303 t
.Skip("skipping finalizer test on gccgo with conservative GC")
307 closed := make(chan struct{})
308 // The closure ensures that we don't have a live reference to buf1
309 // on our stack after MultiReader is inlined (Issue 18819). This
310 // is a work around for a limitation in liveness analysis.
312 buf1
:= bytes
.NewReader([]byte("foo"))
313 buf2
:= bytes
.NewReader([]byte("bar"))
314 mr
= MultiReader(buf1
, buf2
)
315 runtime
.SetFinalizer(buf1
, func(*bytes
.Reader
) {
320 buf
:= make([]byte, 4)
321 if n
, err
:= ReadFull(mr
, buf
); err
!= nil ||
string(buf
) != "foob" {
322 t
.Fatalf(`ReadFull = %d (%q), %v; want 3, "foo", nil`, n
, buf
[:n
], err
)
328 case <-time
.After(5 * time
.Second
):
329 t
.Fatal("timeout waiting for collection of buf1")
332 if n
, err
:= ReadFull(mr
, buf
[:2]); err
!= nil ||
string(buf
[:2]) != "ar" {
333 t
.Fatalf(`ReadFull = %d (%q), %v; want 2, "ar", nil`, n
, buf
[:n
], err
)
337 func TestInterleavedMultiReader(t
*testing
.T
) {
338 r1
:= strings
.NewReader("123")
339 r2
:= strings
.NewReader("45678")
341 mr1
:= MultiReader(r1
, r2
)
342 mr2
:= MultiReader(mr1
)
344 buf
:= make([]byte, 4)
346 // Have mr2 use mr1's []Readers.
347 // Consume r1 (and clear it for GC to handle) and consume part of r2.
348 n
, err
:= ReadFull(mr2
, buf
)
349 if got
:= string(buf
[:n
]); got
!= "1234" || err
!= nil {
350 t
.Errorf(`ReadFull(mr2) = (%q, %v), want ("1234", nil)`, got
, err
)
353 // Consume the rest of r2 via mr1.
354 // This should not panic even though mr2 cleared r1.
355 n
, err
= ReadFull(mr1
, buf
)
356 if got
:= string(buf
[:n
]); got
!= "5678" || err
!= nil {
357 t
.Errorf(`ReadFull(mr1) = (%q, %v), want ("5678", nil)`, got
, err
)