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