| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package recordio |
| 6 |
| 7 import ( |
| 8 "bytes" |
| 9 "encoding/binary" |
| 10 "errors" |
| 11 "io" |
| 12 "io/ioutil" |
| 13 "testing" |
| 14 |
| 15 . "github.com/smartystreets/goconvey/convey" |
| 16 ) |
| 17 |
| 18 // plainReader implements the io.Reader interface on top of a bytes.Buffer; |
| 19 // however, it does not also implement io.ByteReader. |
| 20 type plainReader struct { |
| 21 buf bytes.Buffer |
| 22 err error |
| 23 } |
| 24 |
| 25 func (r *plainReader) loadFrames(chunks ...[]byte) { |
| 26 for _, chunk := range chunks { |
| 27 _, err := WriteFrame(&r.buf, chunk) |
| 28 if err != nil { |
| 29 panic(err) |
| 30 } |
| 31 } |
| 32 } |
| 33 |
| 34 func (r *plainReader) Read(data []byte) (int, error) { |
| 35 if r.err != nil { |
| 36 return 0, r.err |
| 37 } |
| 38 return r.buf.Read(data) |
| 39 } |
| 40 |
| 41 type testByteReader struct { |
| 42 plainReader |
| 43 |
| 44 readByteErr error |
| 45 readBytes int |
| 46 byteBuf [1]byte |
| 47 } |
| 48 |
| 49 func (r *testByteReader) ReadByte() (b byte, err error) { |
| 50 if r.readByteErr != nil { |
| 51 return 0, r.readByteErr |
| 52 } |
| 53 |
| 54 b, err = r.buf.ReadByte() |
| 55 if err == nil { |
| 56 r.readBytes++ |
| 57 } |
| 58 return |
| 59 } |
| 60 |
| 61 // TestReader tests the default Reader implementation, "reader". |
| 62 func TestReader(t *testing.T) { |
| 63 t.Parallel() |
| 64 |
| 65 Convey(`A frame reader with max size 1MB using a plain io.Reader`, t, fu
nc() { |
| 66 maxSize := int64(1024 * 1024) |
| 67 tr := plainReader{} |
| 68 r := NewReader(&tr, maxSize) |
| 69 |
| 70 Convey(`Will return io.EOF with an empty reader.`, func() { |
| 71 _, err := r.ReadFrameAll() |
| 72 So(err, ShouldEqual, io.EOF) |
| 73 }) |
| 74 |
| 75 Convey(`Can successfully read a frame.`, func() { |
| 76 data := []byte{0x13, 0x37, 0xd0, 0x65} |
| 77 tr.loadFrames(data) |
| 78 |
| 79 f, err := r.ReadFrameAll() |
| 80 So(err, ShouldBeNil) |
| 81 So(f, ShouldResemble, data) |
| 82 }) |
| 83 |
| 84 Convey(`Can successfully read two frames.`, func() { |
| 85 data := [][]byte{ |
| 86 {0x13, 0x37, 0xd0, 0x65}, |
| 87 {0xd0, 0x06, 0xea, 0x15, 0xf0, 0x0d}, |
| 88 } |
| 89 tr.loadFrames(data...) |
| 90 |
| 91 c, fr, err := r.ReadFrame() |
| 92 So(err, ShouldBeNil) |
| 93 So(c, ShouldEqual, 4) |
| 94 |
| 95 d, err := ioutil.ReadAll(fr) |
| 96 So(err, ShouldBeNil) |
| 97 So(d, ShouldResemble, data[0]) |
| 98 |
| 99 c, fr, err = r.ReadFrame() |
| 100 So(err, ShouldBeNil) |
| 101 So(c, ShouldEqual, 6) |
| 102 |
| 103 d, err = ioutil.ReadAll(fr) |
| 104 So(err, ShouldBeNil) |
| 105 So(d, ShouldResemble, data[1]) |
| 106 }) |
| 107 |
| 108 Convey(`When reading a frame, will return EOF if the frame is ex
ceeded.`, func() { |
| 109 data := []byte{0x13, 0x37, 0xd0, 0x65} |
| 110 tr.loadFrames(data) |
| 111 |
| 112 count, fr, err := r.ReadFrame() |
| 113 So(err, ShouldBeNil) |
| 114 So(count, ShouldEqual, 4) |
| 115 |
| 116 buf := make([]byte, 5) |
| 117 c, err := fr.Read(make([]byte, 5)) |
| 118 So(c, ShouldEqual, 4) |
| 119 So(err, ShouldBeNil) |
| 120 |
| 121 buf = buf[count:] |
| 122 _, err = fr.Read(buf) |
| 123 So(err, ShouldEqual, io.EOF) |
| 124 }) |
| 125 |
| 126 Convey(`Will fail if the underlying frame exceeds the maximum si
ze.`, func() { |
| 127 var sizeBuf [binary.MaxVarintLen64]byte |
| 128 tr.buf.Write(sizeBuf[:binary.PutUvarint(sizeBuf[:], uint
64(maxSize+1))]) |
| 129 |
| 130 _, err := r.ReadFrameAll() |
| 131 So(err, ShouldEqual, ErrFrameTooLarge) |
| 132 }) |
| 133 |
| 134 Convey(`Will fail if the frame contains an invalid size header.`
, func() { |
| 135 tr.buf.Write([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) |
| 136 _, err := r.ReadFrameAll() |
| 137 So(err, ShouldNotBeNil) |
| 138 }) |
| 139 |
| 140 Convey(`Can read conscutive frames, then io.EOF.`, func() { |
| 141 data := [][]byte{} |
| 142 for _, size := range []int{ |
| 143 0, |
| 144 14, |
| 145 1024 * 1024, |
| 146 0, |
| 147 511, |
| 148 } { |
| 149 data = append(data, bytes.Repeat([]byte{0x5A}, s
ize)) |
| 150 tr.loadFrames(data[len(data)-1]) |
| 151 } |
| 152 |
| 153 for _, expected := range data { |
| 154 f, err := r.ReadFrameAll() |
| 155 So(err, ShouldBeNil) |
| 156 |
| 157 if len(expected) == 0 { |
| 158 expected = nil |
| 159 } |
| 160 So(f, ShouldResemble, expected) |
| 161 } |
| 162 |
| 163 _, err := r.ReadFrameAll() |
| 164 So(err, ShouldEqual, io.EOF) |
| 165 }) |
| 166 }) |
| 167 |
| 168 Convey(`A frame reader with max size 1MB using an io.Reader+io.ByteReade
r`, t, func() { |
| 169 tr := testByteReader{} |
| 170 r := NewReader(&tr, 1024*1024) |
| 171 |
| 172 Convey(`Will return io.EOF with an empty reader.`, func() { |
| 173 _, err := r.ReadFrameAll() |
| 174 So(err, ShouldEqual, io.EOF) |
| 175 }) |
| 176 |
| 177 Convey(`Will use io.ByteReader to read the frame header.`, func(
) { |
| 178 data := []byte{0x13, 0x37, 0xd0, 0x65} |
| 179 tr.loadFrames(data) |
| 180 |
| 181 f, err := r.ReadFrameAll() |
| 182 So(err, ShouldBeNil) |
| 183 So(f, ShouldResemble, data) |
| 184 So(tr.readBytes, ShouldEqual, 1) |
| 185 }) |
| 186 |
| 187 Convey(`Will fail if the underlying io.Reader returns an error.`
, func() { |
| 188 tr.loadFrames([]byte{}) |
| 189 tr.err = errors.New("test: test-induced error") |
| 190 tr.readByteErr = tr.err |
| 191 _, err := r.ReadFrameAll() |
| 192 So(err, ShouldEqual, tr.err) |
| 193 }) |
| 194 |
| 195 Convey(`Will fail if an error is returned while reading frame's
data.`, func() { |
| 196 data := []byte{0x13, 0x37, 0xd0, 0x65} |
| 197 tr.loadFrames(data) |
| 198 |
| 199 // Have "ReadByte()" calls ignore the configured error.
This will cause |
| 200 // the frame size to be read without incident, but the f
rame data to still |
| 201 // return an error. |
| 202 tr.err = errors.New("test: test-induced error") |
| 203 data, err := r.ReadFrameAll() |
| 204 So(err, ShouldEqual, tr.err) |
| 205 }) |
| 206 }) |
| 207 } |
| OLD | NEW |