OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package funnybase | 5 package cmpbin |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "flag" | |
10 "fmt" | 9 "fmt" |
11 "io" | 10 "io" |
12 "math" | 11 "math" |
13 "math/rand" | 12 "math/rand" |
14 "sort" | 13 "sort" |
15 "testing" | 14 "testing" |
16 "time" | |
17 | 15 |
18 . "github.com/smartystreets/goconvey/convey" | 16 . "github.com/smartystreets/goconvey/convey" |
19 ) | 17 ) |
20 | 18 |
21 type testCase struct { | 19 type testCase struct { |
22 expect []byte | 20 expect []byte |
23 val int64 | 21 val int64 |
24 } | 22 } |
25 | 23 |
26 type testCaseSlice []testCase | 24 type testCaseSlice []testCase |
(...skipping 24 matching lines...) Expand all Loading... |
51 {[]byte{b10000100, b10001000}, 17}, | 49 {[]byte{b10000100, b10001000}, 17}, |
52 {[]byte{b10000101, b11111100}, 63}, | 50 {[]byte{b10000101, b11111100}, 63}, |
53 {[]byte{b10000110, b10000000}, 64}, | 51 {[]byte{b10000110, b10000000}, 64}, |
54 {[]byte{b10000110, b10000010}, 65}, | 52 {[]byte{b10000110, b10000010}, 65}, |
55 {[]byte{b10000111, b10000000}, 128}, | 53 {[]byte{b10000111, b10000000}, 128}, |
56 {[]byte{b10011110, b11111111, 0xff, 0xff, b11111110}, math.MaxInt32}, | 54 {[]byte{b10011110, b11111111, 0xff, 0xff, b11111110}, math.MaxInt32}, |
57 {[]byte{b10011111, b10000000, 0, 0, 0}, math.MaxInt32 + 1}, | 55 {[]byte{b10011111, b10000000, 0, 0, 0}, math.MaxInt32 + 1}, |
58 {[]byte{b10111110, b11111111, 0xff, 0xff, b11111111, 0xff, 0xff, 0xff, b
11111110}, math.MaxInt64}, | 56 {[]byte{b10111110, b11111111, 0xff, 0xff, b11111111, 0xff, 0xff, 0xff, b
11111110}, math.MaxInt64}, |
59 } | 57 } |
60 | 58 |
61 var seed = flag.Int64("funnybase.seed", 0, "Random seed to use for randomized fu
nnybase tests") | 59 func TestWrite(t *testing.T) { |
62 | 60 » t.Parallel() |
63 func init() { | 61 » Convey("WriteFuncs", t, func() { |
64 » flag.Parse() | |
65 » if *seed == 0 { | |
66 » » *seed = time.Now().UnixNano() | |
67 » } | |
68 » fmt.Println("funnybase.seed =", *seed) | |
69 } | |
70 | |
71 func TestPut(t *testing.T) { | |
72 » Convey("Put", t, func() { | |
73 for _, c := range cases { | 62 for _, c := range cases { |
74 c := c | 63 c := c |
75 Convey(fmt.Sprintf("%d -> % x", c.val, c.expect), func()
{ | 64 Convey(fmt.Sprintf("%d -> % x", c.val, c.expect), func()
{ |
76 Convey("Put", func() { | |
77 buf := make([]byte, MaxFunnyBaseLen64) | |
78 n := Put(buf, c.val) | |
79 So(n, ShouldEqual, len(c.expect)) | |
80 So(buf[:n], ShouldResemble, c.expect) | |
81 }) | |
82 Convey("Write", func() { | 65 Convey("Write", func() { |
83 buf := &bytes.Buffer{} | 66 buf := &bytes.Buffer{} |
84 » » » » » err := Write(buf, c.val) | 67 » » » » » n, err := WriteInt(buf, c.val) |
85 So(err, ShouldBeNil) | 68 So(err, ShouldBeNil) |
| 69 So(n, ShouldEqual, len(c.expect)) |
86 So(buf.Bytes(), ShouldResemble, c.expect
) | 70 So(buf.Bytes(), ShouldResemble, c.expect
) |
87 }) | 71 }) |
88 | 72 |
89 if c.val >= 0 { | 73 if c.val >= 0 { |
90 Convey("PutUint", func() { | |
91 buf := make([]byte, MaxFunnyBase
Len64) | |
92 n := PutUint(buf, uint64(c.val)) | |
93 So(n, ShouldEqual, len(c.expect)
) | |
94 So(buf[:n], ShouldResemble, c.ex
pect) | |
95 }) | |
96 Convey("WriteUint", func() { | 74 Convey("WriteUint", func() { |
97 buf := &bytes.Buffer{} | 75 buf := &bytes.Buffer{} |
98 » » » » » » err := WriteUint(buf, uint64(c.v
al)) | 76 » » » » » » n, err := WriteUint(buf, uint64(
c.val)) |
99 So(err, ShouldBeNil) | 77 So(err, ShouldBeNil) |
| 78 So(n, ShouldEqual, len(c.expect)
) |
100 So(buf.Bytes(), ShouldResemble,
c.expect) | 79 So(buf.Bytes(), ShouldResemble,
c.expect) |
101 }) | 80 }) |
102 } | 81 } |
103 }) | 82 }) |
104 } | 83 } |
105 }) | 84 }) |
106 } | 85 } |
107 | 86 |
108 func TestGet(t *testing.T) { | |
109 Convey("Get", t, func() { | |
110 for _, c := range cases { | |
111 c := c | |
112 Convey(fmt.Sprintf("% x -> %d", c.expect, c.val), func()
{ | |
113 v, n := Get(c.expect) | |
114 So(n, ShouldEqual, len(c.expect)) | |
115 So(v, ShouldEqual, c.val) | |
116 | |
117 if c.val >= 0 { | |
118 v, n := GetUint(c.expect) | |
119 So(n, ShouldEqual, len(c.expect)) | |
120 So(v, ShouldEqual, c.val) | |
121 } | |
122 }) | |
123 } | |
124 }) | |
125 } | |
126 | |
127 func TestRead(t *testing.T) { | 87 func TestRead(t *testing.T) { |
128 Convey("Read", t, func() { | 88 Convey("Read", t, func() { |
129 for _, c := range cases { | 89 for _, c := range cases { |
130 c := c | 90 c := c |
131 Convey(fmt.Sprintf("% x -> %d", c.expect, c.val), func()
{ | 91 Convey(fmt.Sprintf("% x -> %d", c.expect, c.val), func()
{ |
132 buf := bytes.NewBuffer(c.expect) | 92 buf := bytes.NewBuffer(c.expect) |
133 » » » » v, err := Read(buf) | 93 » » » » v, n, err := ReadInt(buf) |
134 So(err, ShouldBeNil) | 94 So(err, ShouldBeNil) |
| 95 So(n, ShouldEqual, len(c.expect)) |
135 So(v, ShouldEqual, c.val) | 96 So(v, ShouldEqual, c.val) |
136 | 97 |
137 if c.val >= 0 { | 98 if c.val >= 0 { |
138 buf := bytes.NewBuffer(c.expect) | 99 buf := bytes.NewBuffer(c.expect) |
139 » » » » » v, err := ReadUint(buf) | 100 » » » » » v, n, err := ReadUint(buf) |
140 So(err, ShouldBeNil) | 101 So(err, ShouldBeNil) |
| 102 So(n, ShouldEqual, len(c.expect)) |
141 So(v, ShouldEqual, c.val) | 103 So(v, ShouldEqual, c.val) |
142 } | 104 } |
143 }) | 105 }) |
144 } | 106 } |
145 }) | 107 }) |
146 } | 108 } |
147 | 109 |
148 func TestSort(t *testing.T) { | 110 func TestSort(t *testing.T) { |
149 » // TODO(iannucci): Enable full test with num = 20000000. | 111 » num := randomTestSize |
150 » num := 100000 | |
151 num += len(cases) | 112 num += len(cases) |
152 randomCases := make(testCaseSlice, num) | 113 randomCases := make(testCaseSlice, num) |
153 | 114 |
154 rcSub := randomCases[copy(randomCases, cases):] | 115 rcSub := randomCases[copy(randomCases, cases):] |
155 r := rand.New(rand.NewSource(*seed)) | 116 r := rand.New(rand.NewSource(*seed)) |
| 117 buf := &bytes.Buffer{} |
156 for i := range rcSub { | 118 for i := range rcSub { |
157 v := int64(uint64(r.Uint32())<<32 | uint64(r.Uint32())) | 119 v := int64(uint64(r.Uint32())<<32 | uint64(r.Uint32())) |
158 rcSub[i].val = v | 120 rcSub[i].val = v |
159 » » buf := make([]byte, MaxFunnyBaseLen64) | 121 » » buf.Reset() |
160 » » rcSub[i].expect = buf[:Put(buf, v)] | 122 » » if _, err := WriteInt(buf, v); err != nil { |
| 123 » » » panic(err) |
| 124 » » } |
| 125 » » rcSub[i].expect = make([]byte, buf.Len()) |
| 126 » » copy(rcSub[i].expect, buf.Bytes()) |
161 } | 127 } |
162 | 128 |
163 sort.Sort(randomCases) | 129 sort.Sort(randomCases) |
164 | 130 |
165 shouldBeLessThanOrEqual := func(actual interface{}, expected ...interfac
e{}) string { | 131 shouldBeLessThanOrEqual := func(actual interface{}, expected ...interfac
e{}) string { |
166 a, b := actual.([]byte), expected[0].([]byte) | 132 a, b := actual.([]byte), expected[0].([]byte) |
167 if bytes.Compare(a, b) <= 0 { | 133 if bytes.Compare(a, b) <= 0 { |
168 return fmt.Sprintf("Expected A <= B (but it wasn't)!\nA:
[% x]\nB: [% x]", a, b) | 134 return fmt.Sprintf("Expected A <= B (but it wasn't)!\nA:
[% x]\nB: [% x]", a, b) |
169 } | 135 } |
170 return "" | 136 return "" |
171 } | 137 } |
172 | 138 |
173 Convey("TestSort", t, func() { | 139 Convey("TestSort", t, func() { |
174 prev := randomCases[0] | 140 prev := randomCases[0] |
175 for _, c := range randomCases[1:] { | 141 for _, c := range randomCases[1:] { |
176 // Actually asserting with the So for every entry in the
sorted array will | 142 // Actually asserting with the So for every entry in the
sorted array will |
177 » » » // produce 100000 green checkmarks on a sucessful test,
which is a bit | 143 » » » // produce 100 green checkmarks on a sucessful test, whi
ch is a bit |
178 // much :). | 144 // much :). |
179 if bytes.Compare(c.expect, prev.expect) < 0 { | 145 if bytes.Compare(c.expect, prev.expect) < 0 { |
180 So(c.expect, shouldBeLessThanOrEqual, prev.expec
t) | 146 So(c.expect, shouldBeLessThanOrEqual, prev.expec
t) |
181 break | 147 break |
182 } | 148 } |
183 prev = c | 149 prev = c |
184 } | 150 } |
185 | 151 |
186 // This silly assertion is done so that this test has a green ch
eck next to | 152 // This silly assertion is done so that this test has a green ch
eck next to |
187 // it in the event that it passes. Otherwise convey thinks we sk
ipped the | 153 // it in the event that it passes. Otherwise convey thinks we sk
ipped the |
188 // test, which isn't correct. | 154 // test, which isn't correct. |
189 So(true, ShouldBeTrue) | 155 So(true, ShouldBeTrue) |
190 }) | 156 }) |
191 } | 157 } |
192 | 158 |
193 type fakeWriter struct{ count int } | |
194 | |
195 func (f *fakeWriter) WriteByte(byte) error { | |
196 if f.count == 0 { | |
197 return fmt.Errorf("nope") | |
198 } | |
199 f.count-- | |
200 return nil | |
201 } | |
202 | |
203 func TestErrors(t *testing.T) { | 159 func TestErrors(t *testing.T) { |
204 smallerInt64 := []byte{b01000000, b01111111, b11111111, b11111111, b1111
1111, 0xff, 0xff, 0xff, b11111110} | 160 smallerInt64 := []byte{b01000000, b01111111, b11111111, b11111111, b1111
1111, 0xff, 0xff, 0xff, b11111110} |
205 | 161 |
206 prettyBigUint64 := []byte{b10111111, b10000000, 0, 0, 0, 0, 0, 0, 0} | 162 prettyBigUint64 := []byte{b10111111, b10000000, 0, 0, 0, 0, 0, 0, 0} |
207 prettyBigUint64Val := uint64(math.MaxInt64 + 1) | 163 prettyBigUint64Val := uint64(math.MaxInt64 + 1) |
208 | 164 |
209 reallyBigUint64 := []byte{b10111111, b11111111, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff} | 165 reallyBigUint64 := []byte{b10111111, b11111111, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff} |
210 reallyBigUint64Val := uint64(math.MaxUint64) | 166 reallyBigUint64Val := uint64(math.MaxUint64) |
211 tests := []struct { | 167 tests := []struct { |
212 name string | 168 name string |
213 buf []byte | 169 buf []byte |
214 | 170 |
215 v int64 | 171 v int64 |
216 n int | 172 n int |
217 err error | 173 err error |
218 | 174 |
219 uv uint64 | 175 uv uint64 |
220 un int | 176 un int |
221 uerr error | 177 uerr error |
222 }{ | 178 }{ |
223 { | 179 { |
224 name: "Too big!!", | 180 name: "Too big!!", |
225 buf: []byte{b11000000}, // 65 bits!? | 181 buf: []byte{b11000000}, // 65 bits!? |
226 n: -1, | |
227 un: -1, | |
228 err: ErrOverflow, | 182 err: ErrOverflow, |
229 uerr: ErrOverflow, | 183 uerr: ErrOverflow, |
230 }, { | 184 }, { |
231 name: "Nil buffer", | 185 name: "Nil buffer", |
232 err: io.EOF, | 186 err: io.EOF, |
233 uerr: io.EOF, | 187 uerr: io.EOF, |
234 }, { | 188 }, { |
235 name: "Empty buffer", | 189 name: "Empty buffer", |
236 buf: []byte{}, | 190 buf: []byte{}, |
237 err: io.EOF, | 191 err: io.EOF, |
238 uerr: io.EOF, | 192 uerr: io.EOF, |
239 }, { | 193 }, { |
240 name: "Small buffer", | 194 name: "Small buffer", |
241 buf: cases[len(cases)-1].expect[:4], | 195 buf: cases[len(cases)-1].expect[:4], |
242 err: io.EOF, | 196 err: io.EOF, |
243 uerr: io.EOF, | 197 uerr: io.EOF, |
244 }, { | 198 }, { |
245 name: "Reading a negative number with *Uint", | 199 name: "Reading a negative number with *Uint", |
246 buf: cases[0].expect, | 200 buf: cases[0].expect, |
247 v: cases[0].val, | 201 v: cases[0].val, |
248 n: len(cases[0].expect), | 202 n: len(cases[0].expect), |
249 | 203 |
250 un: -2, | |
251 uerr: ErrUnderflow, | 204 uerr: ErrUnderflow, |
252 }, { | 205 }, { |
253 name: "Reading a number smaller than min int64", | 206 name: "Reading a number smaller than min int64", |
254 buf: smallerInt64, | 207 buf: smallerInt64, |
255 n: -2, | |
256 err: ErrUnderflow, | 208 err: ErrUnderflow, |
257 | |
258 un: -2, | |
259 uerr: ErrUnderflow, | 209 uerr: ErrUnderflow, |
260 }, { | 210 }, { |
261 name: "Reading a number bigger than int64", | 211 name: "Reading a number bigger than int64", |
262 buf: prettyBigUint64, | 212 buf: prettyBigUint64, |
263 n: -1, | |
264 err: ErrOverflow, | 213 err: ErrOverflow, |
265 | 214 |
266 uv: prettyBigUint64Val, | 215 uv: prettyBigUint64Val, |
267 un: len(prettyBigUint64), | 216 un: len(prettyBigUint64), |
268 }, { | 217 }, { |
269 name: "Reading MaxUint64", | 218 name: "Reading MaxUint64", |
270 buf: reallyBigUint64, | 219 buf: reallyBigUint64, |
271 n: -1, | |
272 err: ErrOverflow, | 220 err: ErrOverflow, |
273 | 221 |
274 uv: reallyBigUint64Val, | 222 uv: reallyBigUint64Val, |
275 un: len(reallyBigUint64), | 223 un: len(reallyBigUint64), |
276 }, | 224 }, |
277 } | 225 } |
278 | 226 |
279 Convey("Error conditions", t, func() { | 227 Convey("Error conditions", t, func() { |
280 for _, t := range tests { | 228 for _, t := range tests { |
281 Convey(t.name, func() { | 229 Convey(t.name, func() { |
282 Convey("Get", func() { | |
283 v, n := Get(t.buf) | |
284 So(v, ShouldEqual, t.v) | |
285 So(n, ShouldEqual, t.n) | |
286 }) | |
287 Convey("GetUint", func() { | |
288 uv, un := GetUint(t.buf) | |
289 So(uv, ShouldEqual, t.uv) | |
290 So(un, ShouldEqual, t.un) | |
291 }) | |
292 Convey("Read", func() { | 230 Convey("Read", func() { |
293 » » » » » v, err := Read(bytes.NewBuffer(t.buf)) | 231 » » » » » v, _, err := ReadInt(bytes.NewBuffer(t.b
uf)) |
294 So(err, ShouldEqual, t.err) | 232 So(err, ShouldEqual, t.err) |
295 » » » » » So(v, ShouldEqual, t.v) | 233 » » » » » if t.err == nil { |
| 234 » » » » » » So(v, ShouldEqual, t.v) |
| 235 » » » » » } |
296 }) | 236 }) |
297 Convey("ReadUint", func() { | 237 Convey("ReadUint", func() { |
298 » » » » » uv, err := ReadUint(bytes.NewBuffer(t.bu
f)) | 238 » » » » » uv, _, err := ReadUint(bytes.NewBuffer(t
.buf)) |
299 So(err, ShouldEqual, t.uerr) | 239 So(err, ShouldEqual, t.uerr) |
300 » » » » » So(uv, ShouldEqual, t.uv) | 240 » » » » » if t.uerr == nil { |
| 241 » » » » » » So(uv, ShouldEqual, t.uv) |
| 242 » » » » » } |
301 }) | 243 }) |
302 }) | 244 }) |
303 } | 245 } |
304 Convey("Panics", func() { | |
305 Convey("Put", func() { | |
306 buf := make([]byte, MaxFunnyBaseLen64) | |
307 buf = buf[:4] // enough capacity, but not enough
length! | |
308 So(func() { Put(buf, cases[0].val) }, ShouldPani
c) | |
309 }) | |
310 Convey("PutUint", func() { | |
311 buf := make([]byte, MaxFunnyBaseLen64) | |
312 buf = buf[:4] // enough capacity, but not enough
length! | |
313 So(func() { PutUint(buf, reallyBigUint64Val) },
ShouldPanic) | |
314 }) | |
315 }) | |
316 Convey("Write Errors", func() { | 246 Convey("Write Errors", func() { |
317 // Test each error return location in writeSignMag | 247 // Test each error return location in writeSignMag |
318 for count := 0; count < 3; count++ { | 248 for count := 0; count < 3; count++ { |
319 fw := &fakeWriter{count} | 249 fw := &fakeWriter{count} |
320 » » » » err := Write(fw, -10000) | 250 » » » » _, err := WriteInt(fw, -10000) |
321 So(err.Error(), ShouldContainSubstring, "nope") | 251 So(err.Error(), ShouldContainSubstring, "nope") |
322 So(fw.count, ShouldEqual, 0) | 252 So(fw.count, ShouldEqual, 0) |
323 } | 253 } |
324 }) | 254 }) |
325 }) | 255 }) |
326 } | 256 } |
OLD | NEW |