Chromium Code Reviews| 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 frame | |
| 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(data ...[]byte) { | |
| 26 for _, d := range data { | |
|
iannucci
2015/08/04 17:13:50
s/d/chunk
maybe?
dnj
2015/08/04 17:51:42
Done.
| |
| 27 _, err := WriteFrame(&r.buf, d) | |
| 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 readBytes int | |
| 44 nativeReadByte bool | |
|
iannucci
2015/08/04 17:13:51
why not just have 2 struct types (e.g. testByteRea
dnj
2015/08/04 17:51:41
Opted to just have a separate error field for Read
| |
| 45 byteBuf [1]byte | |
| 46 } | |
| 47 | |
| 48 func (r *testByteReader) ReadByte() (b byte, err error) { | |
| 49 if r.nativeReadByte { | |
| 50 b, err = r.buf.ReadByte() | |
| 51 } else { | |
| 52 _, err = r.Read(r.byteBuf[:]) | |
| 53 b = r.byteBuf[0] | |
| 54 } | |
| 55 | |
| 56 if err == nil { | |
| 57 r.readBytes++ | |
| 58 } | |
| 59 return | |
| 60 } | |
| 61 | |
| 62 // TestReader tests the default Reader implementation, "reader". | |
| 63 func TestReader(t *testing.T) { | |
| 64 t.Parallel() | |
| 65 | |
| 66 Convey(`A frame reader with max size 1MB using a plain io.Reader`, t, fu nc() { | |
| 67 maxSize := int64(1024 * 1024) | |
| 68 tr := plainReader{} | |
| 69 r := NewReader(&tr, maxSize) | |
| 70 | |
| 71 Convey(`Will return io.EOF with an empty reader.`, func() { | |
| 72 _, err := r.ReadFrameAll() | |
| 73 So(err, ShouldEqual, io.EOF) | |
| 74 }) | |
| 75 | |
| 76 Convey(`Can successfully read a frame.`, func() { | |
| 77 data := []byte{0x13, 0x37, 0xd0, 0x65} | |
| 78 tr.loadFrames(data) | |
| 79 | |
| 80 f, err := r.ReadFrameAll() | |
| 81 So(err, ShouldBeNil) | |
| 82 So(f, ShouldResemble, data) | |
| 83 }) | |
| 84 | |
| 85 Convey(`Can successfully read two frames.`, func() { | |
| 86 data := [][]byte{ | |
| 87 {0x13, 0x37, 0xd0, 0x65}, | |
| 88 {0xd0, 0x06, 0xea, 0x15, 0xf0, 0x0d}, | |
| 89 } | |
| 90 tr.loadFrames(data...) | |
| 91 | |
| 92 c, fr, err := r.ReadFrame() | |
| 93 So(err, ShouldBeNil) | |
| 94 So(c, ShouldEqual, 4) | |
| 95 | |
| 96 d, err := ioutil.ReadAll(fr) | |
| 97 So(err, ShouldBeNil) | |
| 98 So(d, ShouldResemble, data[0]) | |
| 99 | |
| 100 c, fr, err = r.ReadFrame() | |
| 101 So(err, ShouldBeNil) | |
| 102 So(c, ShouldEqual, 6) | |
| 103 | |
| 104 d, err = ioutil.ReadAll(fr) | |
| 105 So(err, ShouldBeNil) | |
| 106 So(d, ShouldResemble, data[1]) | |
| 107 }) | |
| 108 | |
| 109 Convey(`When reading a frame, will return EOF if the frame is ex ceeded.`, func() { | |
| 110 data := []byte{0x13, 0x37, 0xd0, 0x65} | |
| 111 tr.loadFrames(data) | |
| 112 | |
| 113 count, fr, err := r.ReadFrame() | |
| 114 So(err, ShouldBeNil) | |
| 115 So(count, ShouldEqual, 4) | |
| 116 | |
| 117 buf := make([]byte, 5) | |
| 118 c, err := fr.Read(make([]byte, 5)) | |
| 119 So(c, ShouldEqual, 4) | |
| 120 So(err, ShouldBeNil) | |
| 121 | |
| 122 buf = buf[count:] | |
| 123 _, err = fr.Read(buf) | |
| 124 So(err, ShouldEqual, io.EOF) | |
| 125 }) | |
| 126 | |
| 127 Convey(`Will fail if the underlying frame exceeds the maximum si ze.`, func() { | |
| 128 var sizeBuf [binary.MaxVarintLen64]byte | |
| 129 tr.buf.Write(sizeBuf[:binary.PutUvarint(sizeBuf[:], uint 64(maxSize+1))]) | |
| 130 | |
| 131 _, err := r.ReadFrameAll() | |
| 132 So(err, ShouldEqual, ErrFrameTooLarge) | |
| 133 }) | |
| 134 | |
| 135 Convey(`Will fail if the frame contains an invalid size header.` , func() { | |
| 136 tr.buf.Write([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) | |
| 137 _, err := r.ReadFrameAll() | |
| 138 So(err, ShouldNotBeNil) | |
| 139 }) | |
| 140 | |
| 141 Convey(`Can read conscutive frames, then io.EOF.`, func() { | |
| 142 data := [][]byte{} | |
| 143 for _, size := range []int{ | |
| 144 0, | |
| 145 14, | |
| 146 1024 * 1024, | |
| 147 0, | |
| 148 511, | |
| 149 } { | |
| 150 data = append(data, bytes.Repeat([]byte{0x5A}, s ize)) | |
| 151 tr.loadFrames(data[len(data)-1]) | |
| 152 } | |
| 153 | |
| 154 for _, expected := range data { | |
| 155 f, err := r.ReadFrameAll() | |
| 156 So(err, ShouldBeNil) | |
| 157 | |
| 158 if len(expected) == 0 { | |
| 159 expected = nil | |
| 160 } | |
| 161 So(f, ShouldResemble, expected) | |
| 162 } | |
| 163 | |
| 164 _, err := r.ReadFrameAll() | |
| 165 So(err, ShouldEqual, io.EOF) | |
| 166 }) | |
| 167 }) | |
| 168 | |
| 169 Convey(`A frame reader with max size 1MB using an io.Reader+io.ByteReade r`, t, func() { | |
| 170 tr := testByteReader{} | |
| 171 r := NewReader(&tr, 1024*1024) | |
| 172 | |
| 173 Convey(`Will return io.EOF with an empty reader.`, func() { | |
| 174 _, err := r.ReadFrameAll() | |
| 175 So(err, ShouldEqual, io.EOF) | |
| 176 }) | |
| 177 | |
| 178 Convey(`Will use io.ByteReader to read the frame header.`, func( ) { | |
| 179 data := []byte{0x13, 0x37, 0xd0, 0x65} | |
| 180 tr.loadFrames(data) | |
| 181 | |
| 182 f, err := r.ReadFrameAll() | |
| 183 So(err, ShouldBeNil) | |
| 184 So(f, ShouldResemble, data) | |
| 185 So(tr.readBytes, ShouldEqual, 1) | |
| 186 }) | |
| 187 | |
| 188 Convey(`Will fail if the underlying io.Reader returns an error.` , func() { | |
| 189 tr.loadFrames([]byte{}) | |
| 190 tr.err = errors.New("test: test-induced error") | |
| 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 tr.nativeReadByte = true | |
| 204 data, err := r.ReadFrameAll() | |
| 205 So(err, ShouldEqual, tr.err) | |
| 206 }) | |
| 207 }) | |
| 208 } | |
| OLD | NEW |