github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/io/multi_test.go (about) 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. 4 5 package io_test 6 7 import ( 8 "bytes" 9 "crypto/sha1" 10 "fmt" 11 . "io" 12 "io/ioutil" 13 "strings" 14 "testing" 15 ) 16 17 func TestMultiReader(t *testing.T) { 18 var mr Reader 19 var buf []byte 20 nread := 0 21 withFooBar := func(tests func()) { 22 r1 := strings.NewReader("foo ") 23 r2 := strings.NewReader("") 24 r3 := strings.NewReader("bar") 25 mr = MultiReader(r1, r2, r3) 26 buf = make([]byte, 20) 27 tests() 28 } 29 expectRead := func(size int, expected string, eerr error) { 30 nread++ 31 n, gerr := mr.Read(buf[0:size]) 32 if n != len(expected) { 33 t.Errorf("#%d, expected %d bytes; got %d", 34 nread, len(expected), n) 35 } 36 got := string(buf[0:n]) 37 if got != expected { 38 t.Errorf("#%d, expected %q; got %q", 39 nread, expected, got) 40 } 41 if gerr != eerr { 42 t.Errorf("#%d, expected error %v; got %v", 43 nread, eerr, gerr) 44 } 45 buf = buf[n:] 46 } 47 withFooBar(func() { 48 expectRead(2, "fo", nil) 49 expectRead(5, "o ", nil) 50 expectRead(5, "bar", nil) 51 expectRead(5, "", EOF) 52 }) 53 withFooBar(func() { 54 expectRead(4, "foo ", nil) 55 expectRead(1, "b", nil) 56 expectRead(3, "ar", nil) 57 expectRead(1, "", EOF) 58 }) 59 withFooBar(func() { 60 expectRead(5, "foo ", nil) 61 }) 62 } 63 64 func TestMultiWriter(t *testing.T) { 65 sink := new(bytes.Buffer) 66 // Hide bytes.Buffer's WriteString method: 67 testMultiWriter(t, struct { 68 Writer 69 fmt.Stringer 70 }{sink, sink}) 71 } 72 73 func TestMultiWriter_String(t *testing.T) { 74 testMultiWriter(t, new(bytes.Buffer)) 75 } 76 77 // test that a multiWriter.WriteString calls results in at most 1 allocation, 78 // even if multiple targets don't support WriteString. 79 func TestMultiWriter_WriteStringSingleAlloc(t *testing.T) { 80 var sink1, sink2 bytes.Buffer 81 type simpleWriter struct { // hide bytes.Buffer's WriteString 82 Writer 83 } 84 mw := MultiWriter(simpleWriter{&sink1}, simpleWriter{&sink2}) 85 allocs := int(testing.AllocsPerRun(1000, func() { 86 WriteString(mw, "foo") 87 })) 88 if allocs != 1 { 89 t.Errorf("num allocations = %d; want 1", allocs) 90 } 91 } 92 93 type writeStringChecker struct{ called bool } 94 95 func (c *writeStringChecker) WriteString(s string) (n int, err error) { 96 c.called = true 97 return len(s), nil 98 } 99 100 func (c *writeStringChecker) Write(p []byte) (n int, err error) { 101 return len(p), nil 102 } 103 104 func TestMultiWriter_StringCheckCall(t *testing.T) { 105 var c writeStringChecker 106 mw := MultiWriter(&c) 107 WriteString(mw, "foo") 108 if !c.called { 109 t.Error("did not see WriteString call to writeStringChecker") 110 } 111 } 112 113 func testMultiWriter(t *testing.T, sink interface { 114 Writer 115 fmt.Stringer 116 }) { 117 sha1 := sha1.New() 118 mw := MultiWriter(sha1, sink) 119 120 sourceString := "My input text." 121 source := strings.NewReader(sourceString) 122 written, err := Copy(mw, source) 123 124 if written != int64(len(sourceString)) { 125 t.Errorf("short write of %d, not %d", written, len(sourceString)) 126 } 127 128 if err != nil { 129 t.Errorf("unexpected error: %v", err) 130 } 131 132 sha1hex := fmt.Sprintf("%x", sha1.Sum(nil)) 133 if sha1hex != "01cb303fa8c30a64123067c5aa6284ba7ec2d31b" { 134 t.Error("incorrect sha1 value") 135 } 136 137 if sink.String() != sourceString { 138 t.Errorf("expected %q; got %q", sourceString, sink.String()) 139 } 140 } 141 142 // Test that MultiReader copies the input slice and is insulated from future modification. 143 func TestMultiReaderCopy(t *testing.T) { 144 slice := []Reader{strings.NewReader("hello world")} 145 r := MultiReader(slice...) 146 slice[0] = nil 147 data, err := ioutil.ReadAll(r) 148 if err != nil || string(data) != "hello world" { 149 t.Errorf("ReadAll() = %q, %v, want %q, nil", data, err, "hello world") 150 } 151 } 152 153 // Test that MultiWriter copies the input slice and is insulated from future modification. 154 func TestMultiWriterCopy(t *testing.T) { 155 var buf bytes.Buffer 156 slice := []Writer{&buf} 157 w := MultiWriter(slice...) 158 slice[0] = nil 159 n, err := w.Write([]byte("hello world")) 160 if err != nil || n != 11 { 161 t.Errorf("Write(`hello world`) = %d, %v, want 11, nil", n, err) 162 } 163 if buf.String() != "hello world" { 164 t.Errorf("buf.String() = %q, want %q", buf.String(), "hello world") 165 } 166 }