Chromium Code Reviews

Side by Side Diff: go/src/infra/libs/funnybase/funnybase_test.go

Issue 1153883002: go: infra/libs/* now live in luci-go. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: move the rest too Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
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 funnybase
6
7 import (
8 "bytes"
9 "flag"
10 "fmt"
11 "io"
12 "math"
13 "math/rand"
14 "sort"
15 "testing"
16 "time"
17
18 . "github.com/smartystreets/goconvey/convey"
19 )
20
21 type testCase struct {
22 expect []byte
23 val int64
24 }
25
26 type testCaseSlice []testCase
27
28 func (t testCaseSlice) Len() int { return len(t) }
29 func (t testCaseSlice) Less(i, j int) bool { return t[i].val < t[j].val }
30 func (t testCaseSlice) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
31
32 var cases = testCaseSlice{
33 {[]byte{b01000000, b01111111, b11111111, b11111111, b11111111, 0xff, 0xf f, 0xff, b11111111}, -math.MaxInt64 - 1},
34 {[]byte{b01000001, b00000000, b00000000, b00000000, b00000000, 0, 0, 0, b00000001}, -math.MaxInt64},
35 {[]byte{b01000001, b00000000, b00000000, b00000000, b00000000, 0, 0, 0, b00000011}, -math.MaxInt64 + 1},
36 {[]byte{b01100000, b01111111, b11111111, b11111111, b11111111}, -math.Ma xInt32 - 1},
37 {[]byte{b01100001, b00000000, b00000000, b00000000, b00000001}, -math.Ma xInt32},
38 {[]byte{b01100001, b00000000, b00000000, b00000000, b00000011}, -math.Ma xInt32 + 1},
39 {[]byte{b01110000, b01111111, b11111111}, -math.MaxInt16 - 1},
40 {[]byte{b01111000, b01111110}, -129},
41 {[]byte{b01111000, b01111111}, -128},
42 {[]byte{b01111001, b00000001}, -127},
43 {[]byte{b01111001, b01111101}, -65},
44 {[]byte{b01111001, b01111111}, -64},
45 {[]byte{b01111010, b00000011}, -63},
46 {[]byte{b01111101, b01011111}, -5},
47 {[]byte{b01111110, b00111111}, -3},
48 {[]byte{b01111111, b01111111}, -1},
49 {[]byte{b10000000, b00000000}, 0},
50 {[]byte{b10000010, b10100000}, 5},
51 {[]byte{b10000100, b10001000}, 17},
52 {[]byte{b10000101, b11111100}, 63},
53 {[]byte{b10000110, b10000000}, 64},
54 {[]byte{b10000110, b10000010}, 65},
55 {[]byte{b10000111, b10000000}, 128},
56 {[]byte{b10011110, b11111111, 0xff, 0xff, b11111110}, math.MaxInt32},
57 {[]byte{b10011111, b10000000, 0, 0, 0}, math.MaxInt32 + 1},
58 {[]byte{b10111110, b11111111, 0xff, 0xff, b11111111, 0xff, 0xff, 0xff, b 11111110}, math.MaxInt64},
59 }
60
61 var seed = flag.Int64("funnybase.seed", 0, "Random seed to use for randomized fu nnybase tests")
62
63 func init() {
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 {
74 c := c
75 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() {
83 buf := &bytes.Buffer{}
84 err := Write(buf, c.val)
85 So(err, ShouldBeNil)
86 So(buf.Bytes(), ShouldResemble, c.expect )
87 })
88
89 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() {
97 buf := &bytes.Buffer{}
98 err := WriteUint(buf, uint64(c.v al))
99 So(err, ShouldBeNil)
100 So(buf.Bytes(), ShouldResemble, c.expect)
101 })
102 }
103 })
104 }
105 })
106 }
107
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) {
128 Convey("Read", t, func() {
129 for _, c := range cases {
130 c := c
131 Convey(fmt.Sprintf("% x -> %d", c.expect, c.val), func() {
132 buf := bytes.NewBuffer(c.expect)
133 v, err := Read(buf)
134 So(err, ShouldBeNil)
135 So(v, ShouldEqual, c.val)
136
137 if c.val >= 0 {
138 buf := bytes.NewBuffer(c.expect)
139 v, err := ReadUint(buf)
140 So(err, ShouldBeNil)
141 So(v, ShouldEqual, c.val)
142 }
143 })
144 }
145 })
146 }
147
148 func TestSort(t *testing.T) {
149 num := 20000000
150 if testing.Short() {
151 num = 100000
152 }
153 num += len(cases)
154 randomCases := make(testCaseSlice, num)
155
156 rcSub := randomCases[copy(randomCases, cases):]
157 r := rand.New(rand.NewSource(*seed))
158 for i := range rcSub {
159 v := int64(uint64(r.Uint32())<<32 | uint64(r.Uint32()))
160 rcSub[i].val = v
161 buf := make([]byte, MaxFunnyBaseLen64)
162 rcSub[i].expect = buf[:Put(buf, v)]
163 }
164
165 sort.Sort(randomCases)
166
167 shouldBeLessThanOrEqual := func(actual interface{}, expected ...interfac e{}) string {
168 a, b := actual.([]byte), expected[0].([]byte)
169 if bytes.Compare(a, b) <= 0 {
170 return fmt.Sprintf("Expected A <= B (but it wasn't)!\nA: [% x]\nB: [% x]", a, b)
171 }
172 return ""
173 }
174
175 Convey("TestSort", t, func() {
176 prev := randomCases[0]
177 for _, c := range randomCases[1:] {
178 // Actually asserting with the So for every entry in the sorted array will
179 // produce 100000 green checkmarks on a sucessful test, which is a bit
180 // much :).
181 if bytes.Compare(c.expect, prev.expect) < 0 {
182 So(c.expect, shouldBeLessThanOrEqual, prev.expec t)
183 break
184 }
185 prev = c
186 }
187
188 // This silly assertion is done so that this test has a green ch eck next to
189 // it in the event that it passes. Otherwise convey thinks we sk ipped the
190 // test, which isn't correct.
191 So(true, ShouldBeTrue)
192 })
193 }
194
195 type fakeWriter struct{ count int }
196
197 func (f *fakeWriter) WriteByte(byte) error {
198 if f.count == 0 {
199 return fmt.Errorf("nope")
200 }
201 f.count--
202 return nil
203 }
204
205 func TestErrors(t *testing.T) {
206 smallerInt64 := []byte{b01000000, b01111111, b11111111, b11111111, b1111 1111, 0xff, 0xff, 0xff, b11111110}
207
208 prettyBigUint64 := []byte{b10111111, b10000000, 0, 0, 0, 0, 0, 0, 0}
209 prettyBigUint64Val := uint64(math.MaxInt64 + 1)
210
211 reallyBigUint64 := []byte{b10111111, b11111111, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
212 reallyBigUint64Val := uint64(math.MaxUint64)
213 tests := []struct {
214 name string
215 buf []byte
216
217 v int64
218 n int
219 err error
220
221 uv uint64
222 un int
223 uerr error
224 }{
225 {
226 name: "Too big!!",
227 buf: []byte{b11000000}, // 65 bits!?
228 n: -1,
229 un: -1,
230 err: ErrOverflow,
231 uerr: ErrOverflow,
232 }, {
233 name: "Nil buffer",
234 err: io.EOF,
235 uerr: io.EOF,
236 }, {
237 name: "Empty buffer",
238 buf: []byte{},
239 err: io.EOF,
240 uerr: io.EOF,
241 }, {
242 name: "Small buffer",
243 buf: cases[len(cases)-1].expect[:4],
244 err: io.EOF,
245 uerr: io.EOF,
246 }, {
247 name: "Reading a negative number with *Uint",
248 buf: cases[0].expect,
249 v: cases[0].val,
250 n: len(cases[0].expect),
251
252 un: -2,
253 uerr: ErrUnderflow,
254 }, {
255 name: "Reading a number smaller than min int64",
256 buf: smallerInt64,
257 n: -2,
258 err: ErrUnderflow,
259
260 un: -2,
261 uerr: ErrUnderflow,
262 }, {
263 name: "Reading a number bigger than int64",
264 buf: prettyBigUint64,
265 n: -1,
266 err: ErrOverflow,
267
268 uv: prettyBigUint64Val,
269 un: len(prettyBigUint64),
270 }, {
271 name: "Reading MaxUint64",
272 buf: reallyBigUint64,
273 n: -1,
274 err: ErrOverflow,
275
276 uv: reallyBigUint64Val,
277 un: len(reallyBigUint64),
278 },
279 }
280
281 Convey("Error conditions", t, func() {
282 for _, t := range tests {
283 Convey(t.name, func() {
284 Convey("Get", func() {
285 v, n := Get(t.buf)
286 So(v, ShouldEqual, t.v)
287 So(n, ShouldEqual, t.n)
288 })
289 Convey("GetUint", func() {
290 uv, un := GetUint(t.buf)
291 So(uv, ShouldEqual, t.uv)
292 So(un, ShouldEqual, t.un)
293 })
294 Convey("Read", func() {
295 v, err := Read(bytes.NewBuffer(t.buf))
296 So(err, ShouldEqual, t.err)
297 So(v, ShouldEqual, t.v)
298 })
299 Convey("ReadUint", func() {
300 uv, err := ReadUint(bytes.NewBuffer(t.bu f))
301 So(err, ShouldEqual, t.uerr)
302 So(uv, ShouldEqual, t.uv)
303 })
304 })
305 }
306 Convey("Panics", func() {
307 Convey("Put", func() {
308 buf := make([]byte, MaxFunnyBaseLen64)
309 buf = buf[:4] // enough capacity, but not enough length!
310 So(func() { Put(buf, cases[0].val) }, ShouldPani c)
311 })
312 Convey("PutUint", func() {
313 buf := make([]byte, MaxFunnyBaseLen64)
314 buf = buf[:4] // enough capacity, but not enough length!
315 So(func() { PutUint(buf, reallyBigUint64Val) }, ShouldPanic)
316 })
317 })
318 Convey("Write Errors", func() {
319 // Test each error return location in writeSignMag
320 for count := 0; count < 3; count++ {
321 fw := &fakeWriter{count}
322 err := Write(fw, -10000)
323 So(err.Error(), ShouldContainSubstring, "nope")
324 So(fw.count, ShouldEqual, 0)
325 }
326 })
327 })
328 }
OLDNEW
« no previous file with comments | « go/src/infra/libs/funnybase/funnybase.goconvey ('k') | go/src/infra/libs/logging/gaelogger/gaelogger.go » ('j') | no next file with comments »

Powered by Google App Engine