Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Side by Side Diff: common/logdog/frame/reader_test.go

Issue 1253353008: logdog: Add frame read/write library. (Closed) Base URL: https://github.com/luci/luci-go@logdog-review-output
Patch Set: Cleanup :( Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698