1
2
3
4
5 package protowire
6
7 import (
8 "bytes"
9 "encoding/hex"
10 "io"
11 "math"
12 "strings"
13 "testing"
14 )
15
16 type (
17 testOps struct {
18
19
20 appendOps []appendOp
21
22
23 wantRaw []byte
24
25
26
27
28 consumeOps []consumeOp
29 }
30
31
32 appendOp = interface{}
33 appendTag struct {
34 inNum Number
35 inType Type
36 }
37 appendVarint struct {
38 inVal uint64
39 }
40 appendFixed32 struct {
41 inVal uint32
42 }
43 appendFixed64 struct {
44 inVal uint64
45 }
46 appendBytes struct {
47 inVal []byte
48 }
49 appendGroup struct {
50 inNum Number
51 inVal []byte
52 }
53 appendRaw []byte
54
55
56 consumeOp = interface{}
57 consumeField struct {
58 wantNum Number
59 wantType Type
60 wantCnt int
61 wantErr error
62 }
63 consumeFieldValue struct {
64 inNum Number
65 inType Type
66 wantCnt int
67 wantErr error
68 }
69 consumeTag struct {
70 wantNum Number
71 wantType Type
72 wantCnt int
73 wantErr error
74 }
75 consumeVarint struct {
76 wantVal uint64
77 wantCnt int
78 wantErr error
79 }
80 consumeFixed32 struct {
81 wantVal uint32
82 wantCnt int
83 wantErr error
84 }
85 consumeFixed64 struct {
86 wantVal uint64
87 wantCnt int
88 wantErr error
89 }
90 consumeBytes struct {
91 wantVal []byte
92 wantCnt int
93 wantErr error
94 }
95 consumeGroup struct {
96 inNum Number
97 wantVal []byte
98 wantCnt int
99 wantErr error
100 }
101
102 ops []interface{}
103 )
104
105
106 func dhex(s string) []byte {
107 b, err := hex.DecodeString(s)
108 if err != nil {
109 panic(err)
110 }
111 return b
112 }
113
114 func TestTag(t *testing.T) {
115 runTests(t, []testOps{{
116 appendOps: ops{appendRaw(dhex(""))},
117 consumeOps: ops{consumeTag{wantErr: io.ErrUnexpectedEOF}},
118 }, {
119 appendOps: ops{appendTag{inNum: 0, inType: Fixed32Type}},
120 wantRaw: dhex("05"),
121 consumeOps: ops{consumeTag{wantErr: errFieldNumber}},
122 }, {
123 appendOps: ops{appendTag{inNum: 1, inType: Fixed32Type}},
124 wantRaw: dhex("0d"),
125 consumeOps: ops{consumeTag{wantNum: 1, wantType: Fixed32Type, wantCnt: 1}},
126 }, {
127 appendOps: ops{appendTag{inNum: FirstReservedNumber, inType: BytesType}},
128 wantRaw: dhex("c2a309"),
129 consumeOps: ops{consumeTag{wantNum: FirstReservedNumber, wantType: BytesType, wantCnt: 3}},
130 }, {
131 appendOps: ops{appendTag{inNum: LastReservedNumber, inType: StartGroupType}},
132 wantRaw: dhex("fbe109"),
133 consumeOps: ops{consumeTag{wantNum: LastReservedNumber, wantType: StartGroupType, wantCnt: 3}},
134 }, {
135 appendOps: ops{appendTag{inNum: MaxValidNumber, inType: VarintType}},
136 wantRaw: dhex("f8ffffff0f"),
137 consumeOps: ops{consumeTag{wantNum: MaxValidNumber, wantType: VarintType, wantCnt: 5}},
138 }, {
139 appendOps: ops{appendVarint{inVal: ((math.MaxInt32+1)<<3 | uint64(VarintType))}},
140 wantRaw: dhex("8080808040"),
141 consumeOps: ops{consumeTag{wantErr: errFieldNumber}},
142 }})
143 }
144
145 func TestVarint(t *testing.T) {
146 runTests(t, []testOps{{
147 appendOps: ops{appendRaw(dhex(""))},
148 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
149 }, {
150 appendOps: ops{appendRaw(dhex("80"))},
151 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
152 }, {
153 appendOps: ops{appendRaw(dhex("8080"))},
154 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
155 }, {
156 appendOps: ops{appendRaw(dhex("808080"))},
157 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
158 }, {
159 appendOps: ops{appendRaw(dhex("80808080"))},
160 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
161 }, {
162 appendOps: ops{appendRaw(dhex("8080808080"))},
163 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
164 }, {
165 appendOps: ops{appendRaw(dhex("808080808080"))},
166 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
167 }, {
168 appendOps: ops{appendRaw(dhex("80808080808080"))},
169 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
170 }, {
171 appendOps: ops{appendRaw(dhex("8080808080808080"))},
172 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
173 }, {
174 appendOps: ops{appendRaw(dhex("808080808080808080"))},
175 consumeOps: ops{consumeVarint{wantErr: io.ErrUnexpectedEOF}},
176 }, {
177 appendOps: ops{appendRaw(dhex("80808080808080808080"))},
178 consumeOps: ops{consumeVarint{wantErr: errOverflow}},
179 }, {
180
181 appendOps: ops{appendVarint{inVal: 0x0}},
182 wantRaw: dhex("00"),
183 consumeOps: ops{consumeVarint{wantVal: 0, wantCnt: 1}},
184 }, {
185 appendOps: ops{appendVarint{inVal: 0x1}},
186 wantRaw: dhex("01"),
187 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 1}},
188 }, {
189 appendOps: ops{appendVarint{inVal: 0x7f}},
190 wantRaw: dhex("7f"),
191 consumeOps: ops{consumeVarint{wantVal: 0x7f, wantCnt: 1}},
192 }, {
193 appendOps: ops{appendVarint{inVal: 0x7f + 1}},
194 wantRaw: dhex("8001"),
195 consumeOps: ops{consumeVarint{wantVal: 0x7f + 1, wantCnt: 2}},
196 }, {
197 appendOps: ops{appendVarint{inVal: 0x3fff}},
198 wantRaw: dhex("ff7f"),
199 consumeOps: ops{consumeVarint{wantVal: 0x3fff, wantCnt: 2}},
200 }, {
201 appendOps: ops{appendVarint{inVal: 0x3fff + 1}},
202 wantRaw: dhex("808001"),
203 consumeOps: ops{consumeVarint{wantVal: 0x3fff + 1, wantCnt: 3}},
204 }, {
205 appendOps: ops{appendVarint{inVal: 0x1fffff}},
206 wantRaw: dhex("ffff7f"),
207 consumeOps: ops{consumeVarint{wantVal: 0x1fffff, wantCnt: 3}},
208 }, {
209 appendOps: ops{appendVarint{inVal: 0x1fffff + 1}},
210 wantRaw: dhex("80808001"),
211 consumeOps: ops{consumeVarint{wantVal: 0x1fffff + 1, wantCnt: 4}},
212 }, {
213 appendOps: ops{appendVarint{inVal: 0xfffffff}},
214 wantRaw: dhex("ffffff7f"),
215 consumeOps: ops{consumeVarint{wantVal: 0xfffffff, wantCnt: 4}},
216 }, {
217 appendOps: ops{appendVarint{inVal: 0xfffffff + 1}},
218 wantRaw: dhex("8080808001"),
219 consumeOps: ops{consumeVarint{wantVal: 0xfffffff + 1, wantCnt: 5}},
220 }, {
221 appendOps: ops{appendVarint{inVal: 0x7ffffffff}},
222 wantRaw: dhex("ffffffff7f"),
223 consumeOps: ops{consumeVarint{wantVal: 0x7ffffffff, wantCnt: 5}},
224 }, {
225 appendOps: ops{appendVarint{inVal: 0x7ffffffff + 1}},
226 wantRaw: dhex("808080808001"),
227 consumeOps: ops{consumeVarint{wantVal: 0x7ffffffff + 1, wantCnt: 6}},
228 }, {
229 appendOps: ops{appendVarint{inVal: 0x3ffffffffff}},
230 wantRaw: dhex("ffffffffff7f"),
231 consumeOps: ops{consumeVarint{wantVal: 0x3ffffffffff, wantCnt: 6}},
232 }, {
233 appendOps: ops{appendVarint{inVal: 0x3ffffffffff + 1}},
234 wantRaw: dhex("80808080808001"),
235 consumeOps: ops{consumeVarint{wantVal: 0x3ffffffffff + 1, wantCnt: 7}},
236 }, {
237 appendOps: ops{appendVarint{inVal: 0x1ffffffffffff}},
238 wantRaw: dhex("ffffffffffff7f"),
239 consumeOps: ops{consumeVarint{wantVal: 0x1ffffffffffff, wantCnt: 7}},
240 }, {
241 appendOps: ops{appendVarint{inVal: 0x1ffffffffffff + 1}},
242 wantRaw: dhex("8080808080808001"),
243 consumeOps: ops{consumeVarint{wantVal: 0x1ffffffffffff + 1, wantCnt: 8}},
244 }, {
245 appendOps: ops{appendVarint{inVal: 0xffffffffffffff}},
246 wantRaw: dhex("ffffffffffffff7f"),
247 consumeOps: ops{consumeVarint{wantVal: 0xffffffffffffff, wantCnt: 8}},
248 }, {
249 appendOps: ops{appendVarint{inVal: 0xffffffffffffff + 1}},
250 wantRaw: dhex("808080808080808001"),
251 consumeOps: ops{consumeVarint{wantVal: 0xffffffffffffff + 1, wantCnt: 9}},
252 }, {
253 appendOps: ops{appendVarint{inVal: 0x7fffffffffffffff}},
254 wantRaw: dhex("ffffffffffffffff7f"),
255 consumeOps: ops{consumeVarint{wantVal: 0x7fffffffffffffff, wantCnt: 9}},
256 }, {
257 appendOps: ops{appendVarint{inVal: 0x7fffffffffffffff + 1}},
258 wantRaw: dhex("80808080808080808001"),
259 consumeOps: ops{consumeVarint{wantVal: 0x7fffffffffffffff + 1, wantCnt: 10}},
260 }, {
261 appendOps: ops{appendVarint{inVal: math.MaxUint64}},
262 wantRaw: dhex("ffffffffffffffffff01"),
263 consumeOps: ops{consumeVarint{wantVal: math.MaxUint64, wantCnt: 10}},
264 }, {
265 appendOps: ops{appendRaw(dhex("ffffffffffffffffff02"))},
266 consumeOps: ops{consumeVarint{wantErr: errOverflow}},
267 }, {
268
269
270 appendOps: ops{appendRaw(dhex("01"))},
271 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 1}},
272 }, {
273 appendOps: ops{appendRaw(dhex("8100"))},
274 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 2}},
275 }, {
276 appendOps: ops{appendRaw(dhex("818000"))},
277 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 3}},
278 }, {
279 appendOps: ops{appendRaw(dhex("81808000"))},
280 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 4}},
281 }, {
282 appendOps: ops{appendRaw(dhex("8180808000"))},
283 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 5}},
284 }, {
285 appendOps: ops{appendRaw(dhex("818080808000"))},
286 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 6}},
287 }, {
288 appendOps: ops{appendRaw(dhex("81808080808000"))},
289 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 7}},
290 }, {
291 appendOps: ops{appendRaw(dhex("8180808080808000"))},
292 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 8}},
293 }, {
294 appendOps: ops{appendRaw(dhex("818080808080808000"))},
295 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 9}},
296 }, {
297 appendOps: ops{appendRaw(dhex("81808080808080808000"))},
298 consumeOps: ops{consumeVarint{wantVal: 1, wantCnt: 10}},
299 }, {
300 appendOps: ops{appendRaw(dhex("8180808080808080808000"))},
301 consumeOps: ops{consumeVarint{wantErr: errOverflow}},
302 }})
303 }
304
305 func TestFixed32(t *testing.T) {
306 runTests(t, []testOps{{
307 appendOps: ops{appendRaw(dhex(""))},
308 consumeOps: ops{consumeFixed32{wantErr: io.ErrUnexpectedEOF}},
309 }, {
310 appendOps: ops{appendRaw(dhex("000000"))},
311 consumeOps: ops{consumeFixed32{wantErr: io.ErrUnexpectedEOF}},
312 }, {
313 appendOps: ops{appendFixed32{0}},
314 wantRaw: dhex("00000000"),
315 consumeOps: ops{consumeFixed32{wantVal: 0, wantCnt: 4}},
316 }, {
317 appendOps: ops{appendFixed32{math.MaxUint32}},
318 wantRaw: dhex("ffffffff"),
319 consumeOps: ops{consumeFixed32{wantVal: math.MaxUint32, wantCnt: 4}},
320 }, {
321 appendOps: ops{appendFixed32{0xf0e1d2c3}},
322 wantRaw: dhex("c3d2e1f0"),
323 consumeOps: ops{consumeFixed32{wantVal: 0xf0e1d2c3, wantCnt: 4}},
324 }})
325 }
326
327 func TestFixed64(t *testing.T) {
328 runTests(t, []testOps{{
329 appendOps: ops{appendRaw(dhex(""))},
330 consumeOps: ops{consumeFixed64{wantErr: io.ErrUnexpectedEOF}},
331 }, {
332 appendOps: ops{appendRaw(dhex("00000000000000"))},
333 consumeOps: ops{consumeFixed64{wantErr: io.ErrUnexpectedEOF}},
334 }, {
335 appendOps: ops{appendFixed64{0}},
336 wantRaw: dhex("0000000000000000"),
337 consumeOps: ops{consumeFixed64{wantVal: 0, wantCnt: 8}},
338 }, {
339 appendOps: ops{appendFixed64{math.MaxUint64}},
340 wantRaw: dhex("ffffffffffffffff"),
341 consumeOps: ops{consumeFixed64{wantVal: math.MaxUint64, wantCnt: 8}},
342 }, {
343 appendOps: ops{appendFixed64{0xf0e1d2c3b4a59687}},
344 wantRaw: dhex("8796a5b4c3d2e1f0"),
345 consumeOps: ops{consumeFixed64{wantVal: 0xf0e1d2c3b4a59687, wantCnt: 8}},
346 }})
347 }
348
349 func TestBytes(t *testing.T) {
350 runTests(t, []testOps{{
351 appendOps: ops{appendRaw(dhex(""))},
352 consumeOps: ops{consumeBytes{wantErr: io.ErrUnexpectedEOF}},
353 }, {
354 appendOps: ops{appendRaw(dhex("01"))},
355 consumeOps: ops{consumeBytes{wantErr: io.ErrUnexpectedEOF}},
356 }, {
357 appendOps: ops{appendVarint{0}, appendRaw("")},
358 wantRaw: dhex("00"),
359 consumeOps: ops{consumeBytes{wantVal: dhex(""), wantCnt: 1}},
360 }, {
361 appendOps: ops{appendBytes{[]byte("hello")}},
362 wantRaw: []byte("\x05hello"),
363 consumeOps: ops{consumeBytes{wantVal: []byte("hello"), wantCnt: 6}},
364 }, {
365 appendOps: ops{appendBytes{[]byte(strings.Repeat("hello", 50))}},
366 wantRaw: []byte("\xfa\x01" + strings.Repeat("hello", 50)),
367 consumeOps: ops{consumeBytes{wantVal: []byte(strings.Repeat("hello", 50)), wantCnt: 252}},
368 }, {
369 appendOps: ops{appendRaw("\x85\x80\x00hello")},
370 consumeOps: ops{consumeBytes{wantVal: []byte("hello"), wantCnt: 8}},
371 }, {
372 appendOps: ops{appendRaw("\x85\x80\x00hell")},
373 consumeOps: ops{consumeBytes{wantErr: io.ErrUnexpectedEOF}},
374 }})
375 }
376
377 func TestGroup(t *testing.T) {
378 runTests(t, []testOps{{
379 appendOps: ops{appendRaw(dhex(""))},
380 consumeOps: ops{consumeGroup{wantErr: io.ErrUnexpectedEOF}},
381 }, {
382 appendOps: ops{appendTag{inNum: 0, inType: StartGroupType}},
383 consumeOps: ops{consumeGroup{inNum: 1, wantErr: errFieldNumber}},
384 }, {
385 appendOps: ops{appendTag{inNum: 2, inType: EndGroupType}},
386 consumeOps: ops{consumeGroup{inNum: 1, wantErr: errEndGroup}},
387 }, {
388 appendOps: ops{appendTag{inNum: 1, inType: EndGroupType}},
389 consumeOps: ops{consumeGroup{inNum: 1, wantCnt: 1}},
390 }, {
391 appendOps: ops{
392 appendTag{inNum: 5, inType: Fixed32Type},
393 appendFixed32{0xf0e1d2c3},
394 appendTag{inNum: 5, inType: EndGroupType},
395 },
396 wantRaw: dhex("2dc3d2e1f02c"),
397 consumeOps: ops{consumeGroup{inNum: 5, wantVal: dhex("2dc3d2e1f0"), wantCnt: 6}},
398 }, {
399 appendOps: ops{
400 appendTag{inNum: 5, inType: Fixed32Type},
401 appendFixed32{0xf0e1d2c3},
402 appendRaw(dhex("ac808000")),
403 },
404 consumeOps: ops{consumeGroup{inNum: 5, wantVal: dhex("2dc3d2e1f0"), wantCnt: 9}},
405 }})
406 }
407
408 func TestField(t *testing.T) {
409 runTests(t, []testOps{{
410 appendOps: ops{appendRaw(dhex(""))},
411 consumeOps: ops{consumeField{wantErr: io.ErrUnexpectedEOF}},
412 }, {
413 appendOps: ops{
414 appendTag{inNum: 5000, inType: StartGroupType},
415 appendTag{inNum: 1, inType: VarintType},
416 appendVarint{123456789},
417 appendTag{inNum: 12, inType: Fixed32Type},
418 appendFixed32{123456789},
419 appendTag{inNum: 123, inType: Fixed64Type},
420 appendFixed64{123456789},
421 appendTag{inNum: 1234, inType: BytesType},
422 appendBytes{[]byte("hello")},
423 appendTag{inNum: 12345, inType: StartGroupType},
424 appendTag{inNum: 11, inType: VarintType},
425 appendVarint{123456789},
426 appendTag{inNum: 1212, inType: Fixed32Type},
427 appendFixed32{123456789},
428 appendTag{inNum: 123123, inType: Fixed64Type},
429 appendFixed64{123456789},
430 appendTag{inNum: 12341234, inType: BytesType},
431 appendBytes{[]byte("goodbye")},
432 appendTag{inNum: 12345, inType: EndGroupType},
433 appendTag{inNum: 5000, inType: EndGroupType},
434 },
435 wantRaw: dhex("c3b80208959aef3a6515cd5b07d90715cd5b0700000000924d0568656c6c6fcb830658959aef3ae54b15cd5b07998f3c15cd5b070000000092ff892f07676f6f64627965cc8306c4b802"),
436 consumeOps: ops{
437 consumeTag{wantNum: 5000, wantType: StartGroupType, wantCnt: 3},
438 consumeTag{wantNum: 1, wantType: VarintType, wantCnt: 1},
439 consumeVarint{wantVal: 123456789, wantCnt: 4},
440 consumeTag{wantNum: 12, wantType: Fixed32Type, wantCnt: 1},
441 consumeFixed32{wantVal: 123456789, wantCnt: 4},
442 consumeTag{wantNum: 123, wantType: Fixed64Type, wantCnt: 2},
443 consumeFixed64{wantVal: 123456789, wantCnt: 8},
444 consumeTag{wantNum: 1234, wantType: BytesType, wantCnt: 2},
445 consumeBytes{wantVal: []byte("hello"), wantCnt: 6},
446 consumeTag{wantNum: 12345, wantType: StartGroupType, wantCnt: 3},
447 consumeTag{wantNum: 11, wantType: VarintType, wantCnt: 1},
448 consumeVarint{wantVal: 123456789, wantCnt: 4},
449 consumeTag{wantNum: 1212, wantType: Fixed32Type, wantCnt: 2},
450 consumeFixed32{wantVal: 123456789, wantCnt: 4},
451 consumeTag{wantNum: 123123, wantType: Fixed64Type, wantCnt: 3},
452 consumeFixed64{wantVal: 123456789, wantCnt: 8},
453 consumeTag{wantNum: 12341234, wantType: BytesType, wantCnt: 4},
454 consumeBytes{wantVal: []byte("goodbye"), wantCnt: 8},
455 consumeTag{wantNum: 12345, wantType: EndGroupType, wantCnt: 3},
456 consumeTag{wantNum: 5000, wantType: EndGroupType, wantCnt: 3},
457 },
458 }, {
459 appendOps: ops{appendRaw(dhex("c3b80208959aef3a6515cd5b07d90715cd5b0700000000924d0568656c6c6fcb830658959aef3ae54b15cd5b07998f3c15cd5b070000000092ff892f07676f6f64627965cc8306c4b802"))},
460 consumeOps: ops{consumeField{wantNum: 5000, wantType: StartGroupType, wantCnt: 74}},
461 }, {
462 appendOps: ops{appendTag{inNum: 5, inType: EndGroupType}},
463 wantRaw: dhex("2c"),
464 consumeOps: ops{consumeField{wantErr: errEndGroup}},
465 }, {
466 appendOps: ops{
467 appendTag{inNum: 1, inType: StartGroupType},
468 appendTag{inNum: 22, inType: StartGroupType},
469 appendTag{inNum: 333, inType: StartGroupType},
470 appendTag{inNum: 4444, inType: StartGroupType},
471 appendTag{inNum: 4444, inType: EndGroupType},
472 appendTag{inNum: 333, inType: EndGroupType},
473 appendTag{inNum: 22, inType: EndGroupType},
474 appendTag{inNum: 1, inType: EndGroupType},
475 },
476 wantRaw: dhex("0bb301eb14e39502e49502ec14b4010c"),
477 consumeOps: ops{consumeField{wantNum: 1, wantType: StartGroupType, wantCnt: 16}},
478 }, {
479 appendOps: ops{
480 appendTag{inNum: 1, inType: StartGroupType},
481 appendGroup{inNum: 1, inVal: dhex("b301eb14e39502e49502ec14b401")},
482 },
483 wantRaw: dhex("0b" + "b301eb14e39502e49502ec14b401" + "0c"),
484 consumeOps: ops{consumeField{wantNum: 1, wantType: StartGroupType, wantCnt: 16}},
485 }, {
486 appendOps: ops{
487 appendTag{inNum: 1, inType: StartGroupType},
488 appendTag{inNum: 22, inType: StartGroupType},
489 appendTag{inNum: 333, inType: StartGroupType},
490 appendTag{inNum: 4444, inType: StartGroupType},
491 appendTag{inNum: 333, inType: EndGroupType},
492 appendTag{inNum: 22, inType: EndGroupType},
493 appendTag{inNum: 1, inType: EndGroupType},
494 },
495 consumeOps: ops{consumeField{wantErr: errEndGroup}},
496 }, {
497 appendOps: ops{
498 appendTag{inNum: 1, inType: StartGroupType},
499 appendTag{inNum: 22, inType: StartGroupType},
500 appendTag{inNum: 333, inType: StartGroupType},
501 appendTag{inNum: 4444, inType: StartGroupType},
502 appendTag{inNum: 4444, inType: EndGroupType},
503 appendTag{inNum: 333, inType: EndGroupType},
504 appendTag{inNum: 22, inType: EndGroupType},
505 },
506 consumeOps: ops{consumeField{wantErr: io.ErrUnexpectedEOF}},
507 }, {
508 appendOps: ops{
509 appendTag{inNum: 1, inType: StartGroupType},
510 appendTag{inNum: 22, inType: StartGroupType},
511 appendTag{inNum: 333, inType: StartGroupType},
512 appendTag{inNum: 4444, inType: StartGroupType},
513 appendTag{inNum: 0, inType: VarintType},
514 appendTag{inNum: 4444, inType: EndGroupType},
515 appendTag{inNum: 333, inType: EndGroupType},
516 appendTag{inNum: 22, inType: EndGroupType},
517 appendTag{inNum: 1, inType: EndGroupType},
518 },
519 consumeOps: ops{consumeField{wantErr: errFieldNumber}},
520 }, {
521 appendOps: ops{
522 appendTag{inNum: 1, inType: StartGroupType},
523 appendTag{inNum: 22, inType: StartGroupType},
524 appendTag{inNum: 333, inType: StartGroupType},
525 appendTag{inNum: 4444, inType: StartGroupType},
526 appendTag{inNum: 1, inType: 6},
527 appendTag{inNum: 4444, inType: EndGroupType},
528 appendTag{inNum: 333, inType: EndGroupType},
529 appendTag{inNum: 22, inType: EndGroupType},
530 appendTag{inNum: 1, inType: EndGroupType},
531 },
532 consumeOps: ops{consumeField{wantErr: errReserved}},
533 }})
534 }
535
536 func runTests(t *testing.T, tests []testOps) {
537 for _, tt := range tests {
538 t.Run("", func(t *testing.T) {
539 var b []byte
540 for _, op := range tt.appendOps {
541 b0 := b
542 switch op := op.(type) {
543 case appendTag:
544 b = AppendTag(b, op.inNum, op.inType)
545 case appendVarint:
546 b = AppendVarint(b, op.inVal)
547 case appendFixed32:
548 b = AppendFixed32(b, op.inVal)
549 case appendFixed64:
550 b = AppendFixed64(b, op.inVal)
551 case appendBytes:
552 b = AppendBytes(b, op.inVal)
553 case appendGroup:
554 b = AppendGroup(b, op.inNum, op.inVal)
555 case appendRaw:
556 b = append(b, op...)
557 }
558
559 check := func(label string, want int) {
560 t.Helper()
561 if got := len(b) - len(b0); got != want {
562 t.Errorf("len(Append%v) and Size%v mismatch: got %v, want %v", label, label, got, want)
563 }
564 }
565 switch op := op.(type) {
566 case appendTag:
567 check("Tag", SizeTag(op.inNum))
568 case appendVarint:
569 check("Varint", SizeVarint(op.inVal))
570 case appendFixed32:
571 check("Fixed32", SizeFixed32())
572 case appendFixed64:
573 check("Fixed64", SizeFixed64())
574 case appendBytes:
575 check("Bytes", SizeBytes(len(op.inVal)))
576 case appendGroup:
577 check("Group", SizeGroup(op.inNum, len(op.inVal)))
578 }
579 }
580
581 if tt.wantRaw != nil && !bytes.Equal(b, tt.wantRaw) {
582 t.Errorf("raw output mismatch:\ngot %x\nwant %x", b, tt.wantRaw)
583 }
584
585 for _, op := range tt.consumeOps {
586 check := func(label string, gotCnt, wantCnt int, wantErr error) {
587 t.Helper()
588 gotErr := ParseError(gotCnt)
589 if gotCnt < 0 {
590 gotCnt = 0
591 }
592 if gotCnt != wantCnt {
593 t.Errorf("Consume%v(): consumed %d bytes, want %d bytes consumed", label, gotCnt, wantCnt)
594 }
595 if gotErr != wantErr {
596 t.Errorf("Consume%v(): got %v error, want %v error", label, gotErr, wantErr)
597 }
598 b = b[gotCnt:]
599 }
600 switch op := op.(type) {
601 case consumeField:
602 gotNum, gotType, n := ConsumeField(b)
603 if gotNum != op.wantNum || gotType != op.wantType {
604 t.Errorf("ConsumeField() = (%d, %v), want (%d, %v)", gotNum, gotType, op.wantNum, op.wantType)
605 }
606 check("Field", n, op.wantCnt, op.wantErr)
607 case consumeFieldValue:
608 n := ConsumeFieldValue(op.inNum, op.inType, b)
609 check("FieldValue", n, op.wantCnt, op.wantErr)
610 case consumeTag:
611 gotNum, gotType, n := ConsumeTag(b)
612 if gotNum != op.wantNum || gotType != op.wantType {
613 t.Errorf("ConsumeTag() = (%d, %v), want (%d, %v)", gotNum, gotType, op.wantNum, op.wantType)
614 }
615 check("Tag", n, op.wantCnt, op.wantErr)
616 case consumeVarint:
617 gotVal, n := ConsumeVarint(b)
618 if gotVal != op.wantVal {
619 t.Errorf("ConsumeVarint() = %d, want %d", gotVal, op.wantVal)
620 }
621 check("Varint", n, op.wantCnt, op.wantErr)
622 case consumeFixed32:
623 gotVal, n := ConsumeFixed32(b)
624 if gotVal != op.wantVal {
625 t.Errorf("ConsumeFixed32() = %d, want %d", gotVal, op.wantVal)
626 }
627 check("Fixed32", n, op.wantCnt, op.wantErr)
628 case consumeFixed64:
629 gotVal, n := ConsumeFixed64(b)
630 if gotVal != op.wantVal {
631 t.Errorf("ConsumeFixed64() = %d, want %d", gotVal, op.wantVal)
632 }
633 check("Fixed64", n, op.wantCnt, op.wantErr)
634 case consumeBytes:
635 gotVal, n := ConsumeBytes(b)
636 if !bytes.Equal(gotVal, op.wantVal) {
637 t.Errorf("ConsumeBytes() = %x, want %x", gotVal, op.wantVal)
638 }
639 check("Bytes", n, op.wantCnt, op.wantErr)
640 case consumeGroup:
641 gotVal, n := ConsumeGroup(op.inNum, b)
642 if !bytes.Equal(gotVal, op.wantVal) {
643 t.Errorf("ConsumeGroup() = %x, want %x", gotVal, op.wantVal)
644 }
645 check("Group", n, op.wantCnt, op.wantErr)
646 }
647 }
648 })
649 }
650 }
651
652 func TestZigZag(t *testing.T) {
653 tests := []struct {
654 dec int64
655 enc uint64
656 }{
657 {math.MinInt64 + 0, math.MaxUint64 - 0},
658 {math.MinInt64 + 1, math.MaxUint64 - 2},
659 {math.MinInt64 + 2, math.MaxUint64 - 4},
660 {-3, 5},
661 {-2, 3},
662 {-1, 1},
663 {0, 0},
664 {+1, 2},
665 {+2, 4},
666 {+3, 6},
667 {math.MaxInt64 - 2, math.MaxUint64 - 5},
668 {math.MaxInt64 - 1, math.MaxUint64 - 3},
669 {math.MaxInt64 - 0, math.MaxUint64 - 1},
670 }
671
672 for _, tt := range tests {
673 if enc := EncodeZigZag(tt.dec); enc != tt.enc {
674 t.Errorf("EncodeZigZag(%d) = %d, want %d", tt.dec, enc, tt.enc)
675 }
676 if dec := DecodeZigZag(tt.enc); dec != tt.dec {
677 t.Errorf("DecodeZigZag(%d) = %d, want %d", tt.enc, dec, tt.dec)
678 }
679 }
680 }
681
View as plain text