blob: c24fb04543f84b28ffd218233159f84bebc24bdf [file] [log] [blame]
Joe Tsaifa02f4e2018-09-12 16:20:37 -07001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package impl
6
7import (
Joe Tsai91e14662018-09-13 13:24:35 -07008 "fmt"
9 "math"
10 "strings"
Joe Tsaifa02f4e2018-09-12 16:20:37 -070011 "testing"
12
13 "github.com/google/go-cmp/cmp"
Joe Tsai91e14662018-09-13 13:24:35 -070014 "github.com/google/go-cmp/cmp/cmpopts"
Joe Tsaifa02f4e2018-09-12 16:20:37 -070015
Joe Tsai01ab2962018-09-21 17:44:00 -070016 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
17 ptype "github.com/golang/protobuf/v2/reflect/prototype"
Joe Tsaifa02f4e2018-09-12 16:20:37 -070018)
19
Joe Tsaic6b75612018-09-13 14:24:37 -070020func mustMakeMessageDesc(t ptype.StandaloneMessage) pref.MessageDescriptor {
21 md, err := ptype.NewMessage(&t)
22 if err != nil {
23 panic(err)
24 }
25 return md
26}
27
Joe Tsai91e14662018-09-13 13:24:35 -070028var V = pref.ValueOf
29
Joe Tsaifa02f4e2018-09-12 16:20:37 -070030type (
31 MyBool bool
32 MyInt32 int32
33 MyInt64 int64
34 MyUint32 uint32
35 MyUint64 uint64
36 MyFloat32 float32
37 MyFloat64 float64
38 MyString string
39 MyBytes []byte
Joe Tsai91e14662018-09-13 13:24:35 -070040
41 NamedStrings []MyString
42 NamedBytes []MyBytes
Joe Tsaifa02f4e2018-09-12 16:20:37 -070043)
44
Joe Tsai91e14662018-09-13 13:24:35 -070045// List of test operations to perform on messages, vectors, or maps.
46type (
47 messageOp interface{} // equalMessage | hasFields | getFields | setFields | clearFields | vectorFields | mapFields
48 messageOps []messageOp
Joe Tsaifa02f4e2018-09-12 16:20:37 -070049
Joe Tsai91e14662018-09-13 13:24:35 -070050 vectorOp interface{} // equalVector | lenVector | getVector | setVector | appendVector | truncVector
51 vectorOps []vectorOp
52
53 mapOp interface{} // TODO
54 mapOps []mapOp // TODO
55)
56
57// Test operations performed on a message.
58type (
59 equalMessage pref.Message
60 hasFields map[pref.FieldNumber]bool
61 getFields map[pref.FieldNumber]pref.Value
62 setFields map[pref.FieldNumber]pref.Value
63 clearFields map[pref.FieldNumber]bool
64 vectorFields map[pref.FieldNumber]vectorOps
65 mapFields map[pref.FieldNumber]mapOps
66 messageFields map[pref.FieldNumber]messageOps
67 // TODO: Mutable, Range, ExtensionTypes
68)
69
70// Test operations performed on a vector.
71type (
72 equalVector pref.Vector
73 lenVector int
74 getVector map[int]pref.Value
75 setVector map[int]pref.Value
76 appendVector []pref.Value
77 truncVector int
78 // TODO: Mutable, MutableAppend
79)
80
81func TestScalarProto2(t *testing.T) {
82 type ScalarProto2 struct {
83 Bool *bool `protobuf:"1"`
84 Int32 *int32 `protobuf:"2"`
85 Int64 *int64 `protobuf:"3"`
86 Uint32 *uint32 `protobuf:"4"`
87 Uint64 *uint64 `protobuf:"5"`
88 Float32 *float32 `protobuf:"6"`
89 Float64 *float64 `protobuf:"7"`
90 String *string `protobuf:"8"`
91 StringA []byte `protobuf:"9"`
92 Bytes []byte `protobuf:"10"`
93 BytesA *string `protobuf:"11"`
94
95 MyBool *MyBool `protobuf:"12"`
96 MyInt32 *MyInt32 `protobuf:"13"`
97 MyInt64 *MyInt64 `protobuf:"14"`
98 MyUint32 *MyUint32 `protobuf:"15"`
99 MyUint64 *MyUint64 `protobuf:"16"`
100 MyFloat32 *MyFloat32 `protobuf:"17"`
101 MyFloat64 *MyFloat64 `protobuf:"18"`
102 MyString *MyString `protobuf:"19"`
103 MyStringA MyBytes `protobuf:"20"`
104 MyBytes MyBytes `protobuf:"21"`
105 MyBytesA *MyString `protobuf:"22"`
106 }
107
108 mi := MessageType{Desc: mustMakeMessageDesc(ptype.StandaloneMessage{
109 Syntax: pref.Proto2,
110 FullName: "ScalarProto2",
111 Fields: []ptype.Field{
112 {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: V(bool(true))},
113 {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: V(int32(2))},
114 {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: V(int64(3))},
115 {Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: V(uint32(4))},
116 {Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: V(uint64(5))},
117 {Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: V(float32(6))},
118 {Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: V(float64(7))},
119 {Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("8"))},
120 {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("9"))},
121 {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("10"))},
122 {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("11"))},
123
124 {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: V(bool(true))},
125 {Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: V(int32(13))},
126 {Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: V(int64(14))},
127 {Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: V(uint32(15))},
128 {Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: V(uint64(16))},
129 {Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: V(float32(17))},
130 {Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: V(float64(18))},
131 {Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("19"))},
132 {Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("20"))},
133 {Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("21"))},
134 {Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("22"))},
135 },
136 })}
137
138 testMessage(t, nil, mi.MessageOf(&ScalarProto2{}), messageOps{
139 hasFields{
140 1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false,
141 12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false,
142 },
143 getFields{
144 1: V(bool(true)), 2: V(int32(2)), 3: V(int64(3)), 4: V(uint32(4)), 5: V(uint64(5)), 6: V(float32(6)), 7: V(float64(7)), 8: V(string("8")), 9: V(string("9")), 10: V([]byte("10")), 11: V([]byte("11")),
145 12: V(bool(true)), 13: V(int32(13)), 14: V(int64(14)), 15: V(uint32(15)), 16: V(uint64(16)), 17: V(float32(17)), 18: V(float64(18)), 19: V(string("19")), 20: V(string("20")), 21: V([]byte("21")), 22: V([]byte("22")),
146 },
147 setFields{
148 1: V(bool(false)), 2: V(int32(0)), 3: V(int64(0)), 4: V(uint32(0)), 5: V(uint64(0)), 6: V(float32(0)), 7: V(float64(0)), 8: V(string("")), 9: V(string("")), 10: V([]byte(nil)), 11: V([]byte(nil)),
149 12: V(bool(false)), 13: V(int32(0)), 14: V(int64(0)), 15: V(uint32(0)), 16: V(uint64(0)), 17: V(float32(0)), 18: V(float64(0)), 19: V(string("")), 20: V(string("")), 21: V([]byte(nil)), 22: V([]byte(nil)),
150 },
151 hasFields{
152 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
153 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
154 },
155 equalMessage(mi.MessageOf(&ScalarProto2{
156 new(bool), new(int32), new(int64), new(uint32), new(uint64), new(float32), new(float64), new(string), []byte{}, []byte{}, new(string),
157 new(MyBool), new(MyInt32), new(MyInt64), new(MyUint32), new(MyUint64), new(MyFloat32), new(MyFloat64), new(MyString), MyBytes{}, MyBytes{}, new(MyString),
158 })),
159 clearFields{
160 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
161 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
162 },
163 equalMessage(mi.MessageOf(&ScalarProto2{})),
164 })
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700165}
166
Joe Tsai91e14662018-09-13 13:24:35 -0700167func TestScalarProto3(t *testing.T) {
168 type ScalarProto3 struct {
169 Bool bool `protobuf:"1"`
170 Int32 int32 `protobuf:"2"`
171 Int64 int64 `protobuf:"3"`
172 Uint32 uint32 `protobuf:"4"`
173 Uint64 uint64 `protobuf:"5"`
174 Float32 float32 `protobuf:"6"`
175 Float64 float64 `protobuf:"7"`
176 String string `protobuf:"8"`
177 StringA []byte `protobuf:"9"`
178 Bytes []byte `protobuf:"10"`
179 BytesA string `protobuf:"11"`
Joe Tsaic6b75612018-09-13 14:24:37 -0700180
Joe Tsai91e14662018-09-13 13:24:35 -0700181 MyBool MyBool `protobuf:"12"`
182 MyInt32 MyInt32 `protobuf:"13"`
183 MyInt64 MyInt64 `protobuf:"14"`
184 MyUint32 MyUint32 `protobuf:"15"`
185 MyUint64 MyUint64 `protobuf:"16"`
186 MyFloat32 MyFloat32 `protobuf:"17"`
187 MyFloat64 MyFloat64 `protobuf:"18"`
188 MyString MyString `protobuf:"19"`
189 MyStringA MyBytes `protobuf:"20"`
190 MyBytes MyBytes `protobuf:"21"`
191 MyBytesA MyString `protobuf:"22"`
192 }
Joe Tsaic6b75612018-09-13 14:24:37 -0700193
Joe Tsai91e14662018-09-13 13:24:35 -0700194 mi := MessageType{Desc: mustMakeMessageDesc(ptype.StandaloneMessage{
195 Syntax: pref.Proto3,
196 FullName: "ScalarProto3",
197 Fields: []ptype.Field{
198 {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind},
199 {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind},
200 {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind},
201 {Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
202 {Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
203 {Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind},
204 {Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind},
205 {Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind},
206 {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind},
207 {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind},
208 {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind},
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700209
Joe Tsai91e14662018-09-13 13:24:35 -0700210 {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind},
211 {Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind},
212 {Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind},
213 {Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
214 {Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
215 {Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind},
216 {Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind},
217 {Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind},
218 {Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind},
219 {Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind},
220 {Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind},
221 },
222 })}
223
224 testMessage(t, nil, mi.MessageOf(&ScalarProto3{}), messageOps{
225 hasFields{
226 1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false,
227 12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false,
228 },
229 getFields{
230 1: V(bool(false)), 2: V(int32(0)), 3: V(int64(0)), 4: V(uint32(0)), 5: V(uint64(0)), 6: V(float32(0)), 7: V(float64(0)), 8: V(string("")), 9: V(string("")), 10: V([]byte(nil)), 11: V([]byte(nil)),
231 12: V(bool(false)), 13: V(int32(0)), 14: V(int64(0)), 15: V(uint32(0)), 16: V(uint64(0)), 17: V(float32(0)), 18: V(float64(0)), 19: V(string("")), 20: V(string("")), 21: V([]byte(nil)), 22: V([]byte(nil)),
232 },
233 setFields{
234 1: V(bool(false)), 2: V(int32(0)), 3: V(int64(0)), 4: V(uint32(0)), 5: V(uint64(0)), 6: V(float32(0)), 7: V(float64(0)), 8: V(string("")), 9: V(string("")), 10: V([]byte(nil)), 11: V([]byte(nil)),
235 12: V(bool(false)), 13: V(int32(0)), 14: V(int64(0)), 15: V(uint32(0)), 16: V(uint64(0)), 17: V(float32(0)), 18: V(float64(0)), 19: V(string("")), 20: V(string("")), 21: V([]byte(nil)), 22: V([]byte(nil)),
236 },
237 hasFields{
238 1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false,
239 12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false,
240 },
241 equalMessage(mi.MessageOf(&ScalarProto3{})),
242 setFields{
243 1: V(bool(true)), 2: V(int32(2)), 3: V(int64(3)), 4: V(uint32(4)), 5: V(uint64(5)), 6: V(float32(6)), 7: V(float64(7)), 8: V(string("8")), 9: V(string("9")), 10: V([]byte("10")), 11: V([]byte("11")),
244 12: V(bool(true)), 13: V(int32(13)), 14: V(int64(14)), 15: V(uint32(15)), 16: V(uint64(16)), 17: V(float32(17)), 18: V(float64(18)), 19: V(string("19")), 20: V(string("20")), 21: V([]byte("21")), 22: V([]byte("22")),
245 },
246 hasFields{
247 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
248 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
249 },
250 equalMessage(mi.MessageOf(&ScalarProto3{
251 true, 2, 3, 4, 5, 6, 7, "8", []byte("9"), []byte("10"), "11",
252 true, 13, 14, 15, 16, 17, 18, "19", []byte("20"), []byte("21"), "22",
253 })),
254 clearFields{
255 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
256 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
257 },
258 equalMessage(mi.MessageOf(&ScalarProto3{})),
259 })
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700260}
261
Joe Tsai91e14662018-09-13 13:24:35 -0700262func TestRepeatedScalars(t *testing.T) {
263 type RepeatedScalars struct {
264 Bools []bool `protobuf:"1"`
265 Int32s []int32 `protobuf:"2"`
266 Int64s []int64 `protobuf:"3"`
267 Uint32s []uint32 `protobuf:"4"`
268 Uint64s []uint64 `protobuf:"5"`
269 Float32s []float32 `protobuf:"6"`
270 Float64s []float64 `protobuf:"7"`
271 Strings []string `protobuf:"8"`
272 StringsA [][]byte `protobuf:"9"`
273 Bytes [][]byte `protobuf:"10"`
274 BytesA []string `protobuf:"11"`
Joe Tsaic6b75612018-09-13 14:24:37 -0700275
Joe Tsai91e14662018-09-13 13:24:35 -0700276 MyStrings1 []MyString `protobuf:"12"`
277 MyStrings2 []MyBytes `protobuf:"13"`
278 MyBytes1 []MyBytes `protobuf:"14"`
279 MyBytes2 []MyString `protobuf:"15"`
Joe Tsaic6b75612018-09-13 14:24:37 -0700280
Joe Tsai91e14662018-09-13 13:24:35 -0700281 MyStrings3 NamedStrings `protobuf:"16"`
282 MyStrings4 NamedBytes `protobuf:"17"`
283 MyBytes3 NamedBytes `protobuf:"18"`
284 MyBytes4 NamedStrings `protobuf:"19"`
285 }
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700286
Joe Tsai91e14662018-09-13 13:24:35 -0700287 mi := MessageType{Desc: mustMakeMessageDesc(ptype.StandaloneMessage{
288 Syntax: pref.Proto2,
289 FullName: "RepeatedScalars",
290 Fields: []ptype.Field{
291 {Name: "f1", Number: 1, Cardinality: pref.Repeated, Kind: pref.BoolKind},
292 {Name: "f2", Number: 2, Cardinality: pref.Repeated, Kind: pref.Int32Kind},
293 {Name: "f3", Number: 3, Cardinality: pref.Repeated, Kind: pref.Int64Kind},
294 {Name: "f4", Number: 4, Cardinality: pref.Repeated, Kind: pref.Uint32Kind},
295 {Name: "f5", Number: 5, Cardinality: pref.Repeated, Kind: pref.Uint64Kind},
296 {Name: "f6", Number: 6, Cardinality: pref.Repeated, Kind: pref.FloatKind},
297 {Name: "f7", Number: 7, Cardinality: pref.Repeated, Kind: pref.DoubleKind},
298 {Name: "f8", Number: 8, Cardinality: pref.Repeated, Kind: pref.StringKind},
299 {Name: "f9", Number: 9, Cardinality: pref.Repeated, Kind: pref.StringKind},
300 {Name: "f10", Number: 10, Cardinality: pref.Repeated, Kind: pref.BytesKind},
301 {Name: "f11", Number: 11, Cardinality: pref.Repeated, Kind: pref.BytesKind},
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700302
Joe Tsai91e14662018-09-13 13:24:35 -0700303 {Name: "f12", Number: 12, Cardinality: pref.Repeated, Kind: pref.StringKind},
304 {Name: "f13", Number: 13, Cardinality: pref.Repeated, Kind: pref.StringKind},
305 {Name: "f14", Number: 14, Cardinality: pref.Repeated, Kind: pref.BytesKind},
306 {Name: "f15", Number: 15, Cardinality: pref.Repeated, Kind: pref.BytesKind},
307
308 {Name: "f16", Number: 16, Cardinality: pref.Repeated, Kind: pref.StringKind},
309 {Name: "f17", Number: 17, Cardinality: pref.Repeated, Kind: pref.StringKind},
310 {Name: "f18", Number: 18, Cardinality: pref.Repeated, Kind: pref.BytesKind},
311 {Name: "f19", Number: 19, Cardinality: pref.Repeated, Kind: pref.BytesKind},
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700312 },
Joe Tsai91e14662018-09-13 13:24:35 -0700313 })}
314
315 empty := mi.MessageOf(&RepeatedScalars{})
316 emptyFS := empty.KnownFields()
317
318 want := mi.MessageOf(&RepeatedScalars{
319 Bools: []bool{true, false, true},
320 Int32s: []int32{2, math.MinInt32, math.MaxInt32},
321 Int64s: []int64{3, math.MinInt64, math.MaxInt64},
322 Uint32s: []uint32{4, math.MaxUint32 / 2, math.MaxUint32},
323 Uint64s: []uint64{5, math.MaxUint64 / 2, math.MaxUint64},
324 Float32s: []float32{6, math.SmallestNonzeroFloat32, float32(math.NaN()), math.MaxFloat32},
325 Float64s: []float64{7, math.SmallestNonzeroFloat64, float64(math.NaN()), math.MaxFloat64},
326 Strings: []string{"8", "", "eight"},
327 StringsA: [][]byte{[]byte("9"), nil, []byte("nine")},
328 Bytes: [][]byte{[]byte("10"), nil, []byte("ten")},
329 BytesA: []string{"11", "", "eleven"},
330
331 MyStrings1: []MyString{"12", "", "twelve"},
332 MyStrings2: []MyBytes{[]byte("13"), nil, []byte("thirteen")},
333 MyBytes1: []MyBytes{[]byte("14"), nil, []byte("fourteen")},
334 MyBytes2: []MyString{"15", "", "fifteen"},
335
336 MyStrings3: NamedStrings{"16", "", "sixteen"},
337 MyStrings4: NamedBytes{[]byte("17"), nil, []byte("seventeen")},
338 MyBytes3: NamedBytes{[]byte("18"), nil, []byte("eighteen")},
339 MyBytes4: NamedStrings{"19", "", "nineteen"},
340 })
341 wantFS := want.KnownFields()
342
343 testMessage(t, nil, mi.MessageOf(&RepeatedScalars{}), messageOps{
344 hasFields{1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false, 12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false},
345 getFields{1: emptyFS.Get(1), 3: emptyFS.Get(3), 5: emptyFS.Get(5), 7: emptyFS.Get(7), 9: emptyFS.Get(9), 11: emptyFS.Get(11), 13: emptyFS.Get(13), 15: emptyFS.Get(15), 17: emptyFS.Get(17), 19: emptyFS.Get(19)},
346 setFields{1: wantFS.Get(1), 3: wantFS.Get(3), 5: wantFS.Get(5), 7: wantFS.Get(7), 9: wantFS.Get(9), 11: wantFS.Get(11), 13: wantFS.Get(13), 15: wantFS.Get(15), 17: wantFS.Get(17), 19: wantFS.Get(19)},
347 vectorFields{
348 2: {
349 lenVector(0),
350 appendVector{V(int32(2)), V(int32(math.MinInt32)), V(int32(math.MaxInt32))},
351 getVector{0: V(int32(2)), 1: V(int32(math.MinInt32)), 2: V(int32(math.MaxInt32))},
352 equalVector(wantFS.Get(2).Vector()),
353 },
354 4: {
355 appendVector{V(uint32(0)), V(uint32(0)), V(uint32(0))},
356 setVector{0: V(uint32(4)), 1: V(uint32(math.MaxUint32 / 2)), 2: V(uint32(math.MaxUint32))},
357 lenVector(3),
358 },
359 6: {
360 appendVector{V(float32(6)), V(float32(math.SmallestNonzeroFloat32)), V(float32(math.NaN())), V(float32(math.MaxFloat32))},
361 equalVector(wantFS.Get(6).Vector()),
362 },
363 8: {
364 appendVector{V(""), V(""), V(""), V(""), V(""), V("")},
365 lenVector(6),
366 setVector{0: V("8"), 2: V("eight")},
367 truncVector(3),
368 equalVector(wantFS.Get(8).Vector()),
369 },
370 10: {
371 appendVector{V([]byte(nil)), V([]byte(nil))},
372 setVector{0: V([]byte("10"))},
373 appendVector{V([]byte("wrong"))},
374 setVector{2: V([]byte("ten"))},
375 equalVector(wantFS.Get(10).Vector()),
376 },
377 12: {
378 appendVector{V("12"), V("wrong"), V("twelve")},
379 setVector{1: V("")},
380 equalVector(wantFS.Get(12).Vector()),
381 },
382 14: {
383 appendVector{V([]byte("14")), V([]byte(nil)), V([]byte("fourteen"))},
384 equalVector(wantFS.Get(14).Vector()),
385 },
386 16: {
387 appendVector{V("16"), V(""), V("sixteen"), V("extra")},
388 truncVector(3),
389 equalVector(wantFS.Get(16).Vector()),
390 },
391 18: {
392 appendVector{V([]byte("18")), V([]byte(nil)), V([]byte("eighteen"))},
393 equalVector(wantFS.Get(18).Vector()),
394 },
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700395 },
Joe Tsai91e14662018-09-13 13:24:35 -0700396 hasFields{1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true, 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true},
397 equalMessage(want),
398 clearFields{1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true, 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true},
399 equalMessage(mi.MessageOf(&RepeatedScalars{})),
400 })
401}
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700402
Joe Tsai91e14662018-09-13 13:24:35 -0700403// TODO: Need to test singular and repeated messages
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700404
Joe Tsai91e14662018-09-13 13:24:35 -0700405var cmpOpts = cmp.Options{
406 cmp.Transformer("UnwrapValue", func(v pref.Value) interface{} {
407 return v.Interface()
408 }),
409 cmp.Transformer("UnwrapMessage", func(m pref.Message) interface{} {
410 v := m.Interface()
411 if v, ok := v.(interface{ Unwrap() interface{} }); ok {
412 return v.Unwrap()
413 }
414 return v
415 }),
416 cmp.Transformer("UnwrapVector", func(v pref.Vector) interface{} {
417 return v.(interface{ Unwrap() interface{} }).Unwrap()
418 }),
419 cmp.Transformer("UnwrapMap", func(m pref.Map) interface{} {
420 return m.(interface{ Unwrap() interface{} }).Unwrap()
421 }),
422 cmpopts.EquateNaNs(),
423}
424
425func testMessage(t *testing.T, p path, m pref.Message, tt messageOps) {
426 fs := m.KnownFields()
427 for i, op := range tt {
428 p.Push(i)
429 switch op := op.(type) {
430 case equalMessage:
431 if diff := cmp.Diff(op, m, cmpOpts); diff != "" {
432 t.Errorf("operation %v, message mismatch (-want, +got):\n%s", p, diff)
433 }
434 case hasFields:
435 got := map[pref.FieldNumber]bool{}
436 want := map[pref.FieldNumber]bool(op)
437 for n := range want {
438 got[n] = fs.Has(n)
439 }
440 if diff := cmp.Diff(want, got); diff != "" {
441 t.Errorf("operation %v, KnownFields.Has mismatch (-want, +got):\n%s", p, diff)
442 }
443 case getFields:
444 got := map[pref.FieldNumber]pref.Value{}
445 want := map[pref.FieldNumber]pref.Value(op)
446 for n := range want {
447 got[n] = fs.Get(n)
448 }
449 if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
450 t.Errorf("operation %v, KnownFields.Get mismatch (-want, +got):\n%s", p, diff)
451 }
452 case setFields:
453 for n, v := range op {
454 fs.Set(n, v)
455 }
456 case clearFields:
457 for n, ok := range op {
458 if ok {
459 fs.Clear(n)
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700460 }
461 }
Joe Tsai91e14662018-09-13 13:24:35 -0700462 case vectorFields:
463 for n, tt := range op {
464 p.Push(int(n))
465 testVectors(t, p, fs.Mutable(n).(pref.Vector), tt)
466 p.Pop()
467 }
468 default:
469 t.Fatalf("operation %v, invalid operation: %T", p, op)
470 }
471 p.Pop()
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700472 }
473}
Joe Tsai91e14662018-09-13 13:24:35 -0700474
475func testVectors(t *testing.T, p path, v pref.Vector, tt vectorOps) {
476 for i, op := range tt {
477 p.Push(i)
478 switch op := op.(type) {
479 case equalVector:
480 if diff := cmp.Diff(op, v, cmpOpts); diff != "" {
481 t.Errorf("operation %v, vector mismatch (-want, +got):\n%s", p, diff)
482 }
483 case lenVector:
484 if got, want := v.Len(), int(op); got != want {
485 t.Errorf("operation %v, Vector.Len = %d, want %d", p, got, want)
486 }
487 case getVector:
488 got := map[int]pref.Value{}
489 want := map[int]pref.Value(op)
490 for n := range want {
491 got[n] = v.Get(n)
492 }
493 if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
494 t.Errorf("operation %v, Vector.Get mismatch (-want, +got):\n%s", p, diff)
495 }
496 case setVector:
497 for n, e := range op {
498 v.Set(n, e)
499 }
500 case appendVector:
501 for _, e := range op {
502 v.Append(e)
503 }
504 case truncVector:
505 v.Truncate(int(op))
506 default:
507 t.Fatalf("operation %v, invalid operation: %T", p, op)
508 }
509 p.Pop()
510 }
511}
512
513type path []int
514
515func (p *path) Push(i int) { *p = append(*p, i) }
516func (p *path) Pop() { *p = (*p)[:len(*p)-1] }
517func (p path) String() string {
518 var ss []string
519 for _, i := range p {
520 ss = append(ss, fmt.Sprint(i))
521 }
522 return strings.Join(ss, ".")
523}