github.com/codemac/docker@v1.2.1-0.20150518222241-6a18412d5b9c/pkg/ioutils/readers_test.go (about) 1 package ioutils 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "strings" 9 "testing" 10 ) 11 12 // Implement io.Reader 13 type errorReader struct{} 14 15 func (r *errorReader) Read(p []byte) (int, error) { 16 return 0, fmt.Errorf("Error reader always fail.") 17 } 18 19 func TestReadCloserWrapperClose(t *testing.T) { 20 reader := strings.NewReader("A string reader") 21 wrapper := NewReadCloserWrapper(reader, func() error { 22 return fmt.Errorf("This will be called when closing") 23 }) 24 err := wrapper.Close() 25 if err == nil || !strings.Contains(err.Error(), "This will be called when closing") { 26 t.Fatalf("readCloserWrapper should have call the anonymous func and thus, fail.") 27 } 28 } 29 30 func TestReaderErrWrapperReadOnError(t *testing.T) { 31 called := false 32 reader := &errorReader{} 33 wrapper := NewReaderErrWrapper(reader, func() { 34 called = true 35 }) 36 _, err := wrapper.Read([]byte{}) 37 if err == nil || !strings.Contains(err.Error(), "Error reader always fail.") { 38 t.Fatalf("readErrWrapper should returned an error") 39 } 40 if !called { 41 t.Fatalf("readErrWrapper should have call the anonymous function on failure") 42 } 43 } 44 45 func TestReaderErrWrapperRead(t *testing.T) { 46 called := false 47 reader := strings.NewReader("a string reader.") 48 wrapper := NewReaderErrWrapper(reader, func() { 49 called = true // Should not be called 50 }) 51 // Read 20 byte (should be ok with the string above) 52 num, err := wrapper.Read(make([]byte, 20)) 53 if err != nil { 54 t.Fatal(err) 55 } 56 if num != 16 { 57 t.Fatalf("readerErrWrapper should have read 16 byte, but read %d", num) 58 } 59 } 60 61 func TestNewBufReaderWithDrainbufAndBuffer(t *testing.T) { 62 reader, writer := io.Pipe() 63 64 drainBuffer := make([]byte, 1024) 65 buffer := bytes.Buffer{} 66 bufreader := NewBufReaderWithDrainbufAndBuffer(reader, drainBuffer, &buffer) 67 68 // Write everything down to a Pipe 69 // Usually, a pipe should block but because of the buffered reader, 70 // the writes will go through 71 done := make(chan bool) 72 go func() { 73 writer.Write([]byte("hello world")) 74 writer.Close() 75 done <- true 76 }() 77 78 // Drain the reader *after* everything has been written, just to verify 79 // it is indeed buffering 80 <-done 81 82 output, err := ioutil.ReadAll(bufreader) 83 if err != nil { 84 t.Fatal(err) 85 } 86 if !bytes.Equal(output, []byte("hello world")) { 87 t.Error(string(output)) 88 } 89 } 90 91 func TestBufReader(t *testing.T) { 92 reader, writer := io.Pipe() 93 bufreader := NewBufReader(reader) 94 95 // Write everything down to a Pipe 96 // Usually, a pipe should block but because of the buffered reader, 97 // the writes will go through 98 done := make(chan bool) 99 go func() { 100 writer.Write([]byte("hello world")) 101 writer.Close() 102 done <- true 103 }() 104 105 // Drain the reader *after* everything has been written, just to verify 106 // it is indeed buffering 107 <-done 108 output, err := ioutil.ReadAll(bufreader) 109 if err != nil { 110 t.Fatal(err) 111 } 112 if !bytes.Equal(output, []byte("hello world")) { 113 t.Error(string(output)) 114 } 115 } 116 117 func TestBufReaderCloseWithNonReaderCloser(t *testing.T) { 118 reader := strings.NewReader("buffer") 119 bufreader := NewBufReader(reader) 120 121 if err := bufreader.Close(); err != nil { 122 t.Fatal(err) 123 } 124 125 } 126 127 // implements io.ReadCloser 128 type simpleReaderCloser struct{} 129 130 func (r *simpleReaderCloser) Read(p []byte) (n int, err error) { 131 return 0, nil 132 } 133 134 func (r *simpleReaderCloser) Close() error { 135 return nil 136 } 137 138 func TestBufReaderCloseWithReaderCloser(t *testing.T) { 139 reader := &simpleReaderCloser{} 140 bufreader := NewBufReader(reader) 141 142 err := bufreader.Close() 143 if err != nil { 144 t.Fatal(err) 145 } 146 147 } 148 149 func TestHashData(t *testing.T) { 150 reader := strings.NewReader("hash-me") 151 actual, err := HashData(reader) 152 if err != nil { 153 t.Fatal(err) 154 } 155 expected := "sha256:4d11186aed035cc624d553e10db358492c84a7cd6b9670d92123c144930450aa" 156 if actual != expected { 157 t.Fatalf("Expecting %s, got %s", expected, actual) 158 } 159 } 160 161 type repeatedReader struct { 162 readCount int 163 maxReads int 164 data []byte 165 } 166 167 func newRepeatedReader(max int, data []byte) *repeatedReader { 168 return &repeatedReader{0, max, data} 169 } 170 171 func (r *repeatedReader) Read(p []byte) (int, error) { 172 if r.readCount >= r.maxReads { 173 return 0, io.EOF 174 } 175 r.readCount++ 176 n := copy(p, r.data) 177 return n, nil 178 } 179 180 func testWithData(data []byte, reads int) { 181 reader := newRepeatedReader(reads, data) 182 bufReader := NewBufReader(reader) 183 io.Copy(ioutil.Discard, bufReader) 184 } 185 186 func Benchmark1M10BytesReads(b *testing.B) { 187 reads := 1000000 188 readSize := int64(10) 189 data := make([]byte, readSize) 190 b.SetBytes(readSize * int64(reads)) 191 b.ResetTimer() 192 for i := 0; i < b.N; i++ { 193 testWithData(data, reads) 194 } 195 } 196 197 func Benchmark1M1024BytesReads(b *testing.B) { 198 reads := 1000000 199 readSize := int64(1024) 200 data := make([]byte, readSize) 201 b.SetBytes(readSize * int64(reads)) 202 b.ResetTimer() 203 for i := 0; i < b.N; i++ { 204 testWithData(data, reads) 205 } 206 } 207 208 func Benchmark10k32KBytesReads(b *testing.B) { 209 reads := 10000 210 readSize := int64(32 * 1024) 211 data := make([]byte, readSize) 212 b.SetBytes(readSize * int64(reads)) 213 b.ResetTimer() 214 for i := 0; i < b.N; i++ { 215 testWithData(data, reads) 216 } 217 }