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