blob: a789247dc7aedc945f334f45ef951da83caf8367 [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 Tsaibbfaeb72018-10-17 00:27:21 +000043
44 MapStrings map[MyString]MyString
45 MapBytes map[MyString]MyBytes
Joe Tsaifa02f4e2018-09-12 16:20:37 -070046)
47
Joe Tsai91e14662018-09-13 13:24:35 -070048// List of test operations to perform on messages, vectors, or maps.
49type (
50 messageOp interface{} // equalMessage | hasFields | getFields | setFields | clearFields | vectorFields | mapFields
51 messageOps []messageOp
Joe Tsaifa02f4e2018-09-12 16:20:37 -070052
Joe Tsai91e14662018-09-13 13:24:35 -070053 vectorOp interface{} // equalVector | lenVector | getVector | setVector | appendVector | truncVector
54 vectorOps []vectorOp
55
Joe Tsaibbfaeb72018-10-17 00:27:21 +000056 mapOp interface{} // equalMap | lenMap | hasMap | getMap | setMap | clearMap | rangeMap
57 mapOps []mapOp
Joe Tsai91e14662018-09-13 13:24:35 -070058)
59
60// Test operations performed on a message.
61type (
62 equalMessage pref.Message
63 hasFields map[pref.FieldNumber]bool
64 getFields map[pref.FieldNumber]pref.Value
65 setFields map[pref.FieldNumber]pref.Value
66 clearFields map[pref.FieldNumber]bool
67 vectorFields map[pref.FieldNumber]vectorOps
68 mapFields map[pref.FieldNumber]mapOps
69 messageFields map[pref.FieldNumber]messageOps
70 // TODO: Mutable, Range, ExtensionTypes
71)
72
73// Test operations performed on a vector.
74type (
75 equalVector pref.Vector
76 lenVector int
77 getVector map[int]pref.Value
78 setVector map[int]pref.Value
79 appendVector []pref.Value
80 truncVector int
81 // TODO: Mutable, MutableAppend
82)
83
Joe Tsaibbfaeb72018-10-17 00:27:21 +000084// Test operations performed on a map.
85type (
86 equalMap pref.Map
87 lenMap int
88 hasMap map[interface{}]bool
89 getMap map[interface{}]pref.Value
90 setMap map[interface{}]pref.Value
91 clearMap map[interface{}]bool
92 rangeMap map[interface{}]pref.Value
93 // TODO: List, Mutable
94)
95
Joe Tsai91e14662018-09-13 13:24:35 -070096func TestScalarProto2(t *testing.T) {
97 type ScalarProto2 struct {
98 Bool *bool `protobuf:"1"`
99 Int32 *int32 `protobuf:"2"`
100 Int64 *int64 `protobuf:"3"`
101 Uint32 *uint32 `protobuf:"4"`
102 Uint64 *uint64 `protobuf:"5"`
103 Float32 *float32 `protobuf:"6"`
104 Float64 *float64 `protobuf:"7"`
105 String *string `protobuf:"8"`
106 StringA []byte `protobuf:"9"`
107 Bytes []byte `protobuf:"10"`
108 BytesA *string `protobuf:"11"`
109
110 MyBool *MyBool `protobuf:"12"`
111 MyInt32 *MyInt32 `protobuf:"13"`
112 MyInt64 *MyInt64 `protobuf:"14"`
113 MyUint32 *MyUint32 `protobuf:"15"`
114 MyUint64 *MyUint64 `protobuf:"16"`
115 MyFloat32 *MyFloat32 `protobuf:"17"`
116 MyFloat64 *MyFloat64 `protobuf:"18"`
117 MyString *MyString `protobuf:"19"`
118 MyStringA MyBytes `protobuf:"20"`
119 MyBytes MyBytes `protobuf:"21"`
120 MyBytesA *MyString `protobuf:"22"`
121 }
122
123 mi := MessageType{Desc: mustMakeMessageDesc(ptype.StandaloneMessage{
124 Syntax: pref.Proto2,
125 FullName: "ScalarProto2",
126 Fields: []ptype.Field{
127 {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: V(bool(true))},
128 {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: V(int32(2))},
129 {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: V(int64(3))},
130 {Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: V(uint32(4))},
131 {Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: V(uint64(5))},
132 {Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: V(float32(6))},
133 {Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: V(float64(7))},
134 {Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("8"))},
135 {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("9"))},
136 {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("10"))},
137 {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("11"))},
138
139 {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: V(bool(true))},
140 {Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: V(int32(13))},
141 {Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: V(int64(14))},
142 {Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: V(uint32(15))},
143 {Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: V(uint64(16))},
144 {Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: V(float32(17))},
145 {Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: V(float64(18))},
146 {Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("19"))},
147 {Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind, Default: V(string("20"))},
148 {Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("21"))},
149 {Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: V([]byte("22"))},
150 },
151 })}
152
153 testMessage(t, nil, mi.MessageOf(&ScalarProto2{}), messageOps{
154 hasFields{
155 1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false,
156 12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false,
157 },
158 getFields{
159 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")),
160 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")),
161 },
162 setFields{
163 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)),
164 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)),
165 },
166 hasFields{
167 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
168 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
169 },
170 equalMessage(mi.MessageOf(&ScalarProto2{
171 new(bool), new(int32), new(int64), new(uint32), new(uint64), new(float32), new(float64), new(string), []byte{}, []byte{}, new(string),
172 new(MyBool), new(MyInt32), new(MyInt64), new(MyUint32), new(MyUint64), new(MyFloat32), new(MyFloat64), new(MyString), MyBytes{}, MyBytes{}, new(MyString),
173 })),
174 clearFields{
175 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
176 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
177 },
178 equalMessage(mi.MessageOf(&ScalarProto2{})),
179 })
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700180}
181
Joe Tsai91e14662018-09-13 13:24:35 -0700182func TestScalarProto3(t *testing.T) {
183 type ScalarProto3 struct {
184 Bool bool `protobuf:"1"`
185 Int32 int32 `protobuf:"2"`
186 Int64 int64 `protobuf:"3"`
187 Uint32 uint32 `protobuf:"4"`
188 Uint64 uint64 `protobuf:"5"`
189 Float32 float32 `protobuf:"6"`
190 Float64 float64 `protobuf:"7"`
191 String string `protobuf:"8"`
192 StringA []byte `protobuf:"9"`
193 Bytes []byte `protobuf:"10"`
194 BytesA string `protobuf:"11"`
Joe Tsaic6b75612018-09-13 14:24:37 -0700195
Joe Tsai91e14662018-09-13 13:24:35 -0700196 MyBool MyBool `protobuf:"12"`
197 MyInt32 MyInt32 `protobuf:"13"`
198 MyInt64 MyInt64 `protobuf:"14"`
199 MyUint32 MyUint32 `protobuf:"15"`
200 MyUint64 MyUint64 `protobuf:"16"`
201 MyFloat32 MyFloat32 `protobuf:"17"`
202 MyFloat64 MyFloat64 `protobuf:"18"`
203 MyString MyString `protobuf:"19"`
204 MyStringA MyBytes `protobuf:"20"`
205 MyBytes MyBytes `protobuf:"21"`
206 MyBytesA MyString `protobuf:"22"`
207 }
Joe Tsaic6b75612018-09-13 14:24:37 -0700208
Joe Tsai91e14662018-09-13 13:24:35 -0700209 mi := MessageType{Desc: mustMakeMessageDesc(ptype.StandaloneMessage{
210 Syntax: pref.Proto3,
211 FullName: "ScalarProto3",
212 Fields: []ptype.Field{
213 {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind},
214 {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind},
215 {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind},
216 {Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
217 {Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
218 {Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind},
219 {Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind},
220 {Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind},
221 {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind},
222 {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind},
223 {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind},
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700224
Joe Tsai91e14662018-09-13 13:24:35 -0700225 {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind},
226 {Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind},
227 {Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind},
228 {Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
229 {Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
230 {Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind},
231 {Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind},
232 {Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind},
233 {Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind},
234 {Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind},
235 {Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind},
236 },
237 })}
238
239 testMessage(t, nil, mi.MessageOf(&ScalarProto3{}), messageOps{
240 hasFields{
241 1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false,
242 12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false,
243 },
244 getFields{
245 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)),
246 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)),
247 },
248 setFields{
249 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)),
250 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)),
251 },
252 hasFields{
253 1: false, 2: false, 3: false, 4: false, 5: false, 6: false, 7: false, 8: false, 9: false, 10: false, 11: false,
254 12: false, 13: false, 14: false, 15: false, 16: false, 17: false, 18: false, 19: false, 20: false, 21: false, 22: false,
255 },
256 equalMessage(mi.MessageOf(&ScalarProto3{})),
257 setFields{
258 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")),
259 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")),
260 },
261 hasFields{
262 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
263 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
264 },
265 equalMessage(mi.MessageOf(&ScalarProto3{
266 true, 2, 3, 4, 5, 6, 7, "8", []byte("9"), []byte("10"), "11",
267 true, 13, 14, 15, 16, 17, 18, "19", []byte("20"), []byte("21"), "22",
268 })),
269 clearFields{
270 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true, 11: true,
271 12: true, 13: true, 14: true, 15: true, 16: true, 17: true, 18: true, 19: true, 20: true, 21: true, 22: true,
272 },
273 equalMessage(mi.MessageOf(&ScalarProto3{})),
274 })
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700275}
276
Joe Tsai91e14662018-09-13 13:24:35 -0700277func TestRepeatedScalars(t *testing.T) {
278 type RepeatedScalars struct {
279 Bools []bool `protobuf:"1"`
280 Int32s []int32 `protobuf:"2"`
281 Int64s []int64 `protobuf:"3"`
282 Uint32s []uint32 `protobuf:"4"`
283 Uint64s []uint64 `protobuf:"5"`
284 Float32s []float32 `protobuf:"6"`
285 Float64s []float64 `protobuf:"7"`
286 Strings []string `protobuf:"8"`
287 StringsA [][]byte `protobuf:"9"`
288 Bytes [][]byte `protobuf:"10"`
289 BytesA []string `protobuf:"11"`
Joe Tsaic6b75612018-09-13 14:24:37 -0700290
Joe Tsai91e14662018-09-13 13:24:35 -0700291 MyStrings1 []MyString `protobuf:"12"`
292 MyStrings2 []MyBytes `protobuf:"13"`
293 MyBytes1 []MyBytes `protobuf:"14"`
294 MyBytes2 []MyString `protobuf:"15"`
Joe Tsaic6b75612018-09-13 14:24:37 -0700295
Joe Tsai91e14662018-09-13 13:24:35 -0700296 MyStrings3 NamedStrings `protobuf:"16"`
297 MyStrings4 NamedBytes `protobuf:"17"`
298 MyBytes3 NamedBytes `protobuf:"18"`
299 MyBytes4 NamedStrings `protobuf:"19"`
300 }
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700301
Joe Tsai91e14662018-09-13 13:24:35 -0700302 mi := MessageType{Desc: mustMakeMessageDesc(ptype.StandaloneMessage{
303 Syntax: pref.Proto2,
304 FullName: "RepeatedScalars",
305 Fields: []ptype.Field{
306 {Name: "f1", Number: 1, Cardinality: pref.Repeated, Kind: pref.BoolKind},
307 {Name: "f2", Number: 2, Cardinality: pref.Repeated, Kind: pref.Int32Kind},
308 {Name: "f3", Number: 3, Cardinality: pref.Repeated, Kind: pref.Int64Kind},
309 {Name: "f4", Number: 4, Cardinality: pref.Repeated, Kind: pref.Uint32Kind},
310 {Name: "f5", Number: 5, Cardinality: pref.Repeated, Kind: pref.Uint64Kind},
311 {Name: "f6", Number: 6, Cardinality: pref.Repeated, Kind: pref.FloatKind},
312 {Name: "f7", Number: 7, Cardinality: pref.Repeated, Kind: pref.DoubleKind},
313 {Name: "f8", Number: 8, Cardinality: pref.Repeated, Kind: pref.StringKind},
314 {Name: "f9", Number: 9, Cardinality: pref.Repeated, Kind: pref.StringKind},
315 {Name: "f10", Number: 10, Cardinality: pref.Repeated, Kind: pref.BytesKind},
316 {Name: "f11", Number: 11, Cardinality: pref.Repeated, Kind: pref.BytesKind},
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700317
Joe Tsai91e14662018-09-13 13:24:35 -0700318 {Name: "f12", Number: 12, Cardinality: pref.Repeated, Kind: pref.StringKind},
319 {Name: "f13", Number: 13, Cardinality: pref.Repeated, Kind: pref.StringKind},
320 {Name: "f14", Number: 14, Cardinality: pref.Repeated, Kind: pref.BytesKind},
321 {Name: "f15", Number: 15, Cardinality: pref.Repeated, Kind: pref.BytesKind},
322
323 {Name: "f16", Number: 16, Cardinality: pref.Repeated, Kind: pref.StringKind},
324 {Name: "f17", Number: 17, Cardinality: pref.Repeated, Kind: pref.StringKind},
325 {Name: "f18", Number: 18, Cardinality: pref.Repeated, Kind: pref.BytesKind},
326 {Name: "f19", Number: 19, Cardinality: pref.Repeated, Kind: pref.BytesKind},
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700327 },
Joe Tsai91e14662018-09-13 13:24:35 -0700328 })}
329
330 empty := mi.MessageOf(&RepeatedScalars{})
331 emptyFS := empty.KnownFields()
332
333 want := mi.MessageOf(&RepeatedScalars{
334 Bools: []bool{true, false, true},
335 Int32s: []int32{2, math.MinInt32, math.MaxInt32},
336 Int64s: []int64{3, math.MinInt64, math.MaxInt64},
337 Uint32s: []uint32{4, math.MaxUint32 / 2, math.MaxUint32},
338 Uint64s: []uint64{5, math.MaxUint64 / 2, math.MaxUint64},
339 Float32s: []float32{6, math.SmallestNonzeroFloat32, float32(math.NaN()), math.MaxFloat32},
340 Float64s: []float64{7, math.SmallestNonzeroFloat64, float64(math.NaN()), math.MaxFloat64},
341 Strings: []string{"8", "", "eight"},
342 StringsA: [][]byte{[]byte("9"), nil, []byte("nine")},
343 Bytes: [][]byte{[]byte("10"), nil, []byte("ten")},
344 BytesA: []string{"11", "", "eleven"},
345
346 MyStrings1: []MyString{"12", "", "twelve"},
347 MyStrings2: []MyBytes{[]byte("13"), nil, []byte("thirteen")},
348 MyBytes1: []MyBytes{[]byte("14"), nil, []byte("fourteen")},
349 MyBytes2: []MyString{"15", "", "fifteen"},
350
351 MyStrings3: NamedStrings{"16", "", "sixteen"},
352 MyStrings4: NamedBytes{[]byte("17"), nil, []byte("seventeen")},
353 MyBytes3: NamedBytes{[]byte("18"), nil, []byte("eighteen")},
354 MyBytes4: NamedStrings{"19", "", "nineteen"},
355 })
356 wantFS := want.KnownFields()
357
358 testMessage(t, nil, mi.MessageOf(&RepeatedScalars{}), messageOps{
359 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},
360 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)},
361 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)},
362 vectorFields{
363 2: {
364 lenVector(0),
365 appendVector{V(int32(2)), V(int32(math.MinInt32)), V(int32(math.MaxInt32))},
366 getVector{0: V(int32(2)), 1: V(int32(math.MinInt32)), 2: V(int32(math.MaxInt32))},
367 equalVector(wantFS.Get(2).Vector()),
368 },
369 4: {
370 appendVector{V(uint32(0)), V(uint32(0)), V(uint32(0))},
371 setVector{0: V(uint32(4)), 1: V(uint32(math.MaxUint32 / 2)), 2: V(uint32(math.MaxUint32))},
372 lenVector(3),
373 },
374 6: {
375 appendVector{V(float32(6)), V(float32(math.SmallestNonzeroFloat32)), V(float32(math.NaN())), V(float32(math.MaxFloat32))},
376 equalVector(wantFS.Get(6).Vector()),
377 },
378 8: {
379 appendVector{V(""), V(""), V(""), V(""), V(""), V("")},
380 lenVector(6),
381 setVector{0: V("8"), 2: V("eight")},
382 truncVector(3),
383 equalVector(wantFS.Get(8).Vector()),
384 },
385 10: {
386 appendVector{V([]byte(nil)), V([]byte(nil))},
387 setVector{0: V([]byte("10"))},
388 appendVector{V([]byte("wrong"))},
389 setVector{2: V([]byte("ten"))},
390 equalVector(wantFS.Get(10).Vector()),
391 },
392 12: {
393 appendVector{V("12"), V("wrong"), V("twelve")},
394 setVector{1: V("")},
395 equalVector(wantFS.Get(12).Vector()),
396 },
397 14: {
398 appendVector{V([]byte("14")), V([]byte(nil)), V([]byte("fourteen"))},
399 equalVector(wantFS.Get(14).Vector()),
400 },
401 16: {
402 appendVector{V("16"), V(""), V("sixteen"), V("extra")},
403 truncVector(3),
404 equalVector(wantFS.Get(16).Vector()),
405 },
406 18: {
407 appendVector{V([]byte("18")), V([]byte(nil)), V([]byte("eighteen"))},
408 equalVector(wantFS.Get(18).Vector()),
409 },
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700410 },
Joe Tsai91e14662018-09-13 13:24:35 -0700411 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},
412 equalMessage(want),
413 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},
Joe Tsaibbfaeb72018-10-17 00:27:21 +0000414 equalMessage(empty),
415 })
416}
417
418func TestMapScalars(t *testing.T) {
419 type MapScalars struct {
420 KeyBools map[bool]string `protobuf:"1"`
421 KeyInt32s map[int32]string `protobuf:"2"`
422 KeyInt64s map[int64]string `protobuf:"3"`
423 KeyUint32s map[uint32]string `protobuf:"4"`
424 KeyUint64s map[uint64]string `protobuf:"5"`
425 KeyStrings map[string]string `protobuf:"6"`
426
427 ValBools map[string]bool `protobuf:"7"`
428 ValInt32s map[string]int32 `protobuf:"8"`
429 ValInt64s map[string]int64 `protobuf:"9"`
430 ValUint32s map[string]uint32 `protobuf:"10"`
431 ValUint64s map[string]uint64 `protobuf:"11"`
432 ValFloat32s map[string]float32 `protobuf:"12"`
433 ValFloat64s map[string]float64 `protobuf:"13"`
434 ValStrings map[string]string `protobuf:"14"`
435 ValStringsA map[string][]byte `protobuf:"15"`
436 ValBytes map[string][]byte `protobuf:"16"`
437 ValBytesA map[string]string `protobuf:"17"`
438
439 MyStrings1 map[MyString]MyString `protobuf:"18"`
440 MyStrings2 map[MyString]MyBytes `protobuf:"19"`
441 MyBytes1 map[MyString]MyBytes `protobuf:"20"`
442 MyBytes2 map[MyString]MyString `protobuf:"21"`
443
444 MyStrings3 MapStrings `protobuf:"22"`
445 MyStrings4 MapBytes `protobuf:"23"`
446 MyBytes3 MapBytes `protobuf:"24"`
447 MyBytes4 MapStrings `protobuf:"25"`
448 }
449
450 mustMakeMapEntry := func(n pref.FieldNumber, keyKind, valKind pref.Kind) ptype.Field {
451 return ptype.Field{
452 Name: pref.Name(fmt.Sprintf("f%d", n)),
453 Number: n,
454 Cardinality: pref.Repeated,
455 Kind: pref.MessageKind,
456 MessageType: mustMakeMessageDesc(ptype.StandaloneMessage{
457 Syntax: pref.Proto2,
458 FullName: pref.FullName(fmt.Sprintf("MapScalars.F%dEntry", n)),
459 Fields: []ptype.Field{
460 {Name: "key", Number: 1, Cardinality: pref.Optional, Kind: keyKind},
461 {Name: "value", Number: 2, Cardinality: pref.Optional, Kind: valKind},
462 },
463 IsMapEntry: true,
464 }),
465 }
466 }
467 mi := MessageType{Desc: mustMakeMessageDesc(ptype.StandaloneMessage{
468 Syntax: pref.Proto2,
469 FullName: "MapScalars",
470 Fields: []ptype.Field{
471 mustMakeMapEntry(1, pref.BoolKind, pref.StringKind),
472 mustMakeMapEntry(2, pref.Int32Kind, pref.StringKind),
473 mustMakeMapEntry(3, pref.Int64Kind, pref.StringKind),
474 mustMakeMapEntry(4, pref.Uint32Kind, pref.StringKind),
475 mustMakeMapEntry(5, pref.Uint64Kind, pref.StringKind),
476 mustMakeMapEntry(6, pref.StringKind, pref.StringKind),
477
478 mustMakeMapEntry(7, pref.StringKind, pref.BoolKind),
479 mustMakeMapEntry(8, pref.StringKind, pref.Int32Kind),
480 mustMakeMapEntry(9, pref.StringKind, pref.Int64Kind),
481 mustMakeMapEntry(10, pref.StringKind, pref.Uint32Kind),
482 mustMakeMapEntry(11, pref.StringKind, pref.Uint64Kind),
483 mustMakeMapEntry(12, pref.StringKind, pref.FloatKind),
484 mustMakeMapEntry(13, pref.StringKind, pref.DoubleKind),
485 mustMakeMapEntry(14, pref.StringKind, pref.StringKind),
486 mustMakeMapEntry(15, pref.StringKind, pref.StringKind),
487 mustMakeMapEntry(16, pref.StringKind, pref.BytesKind),
488 mustMakeMapEntry(17, pref.StringKind, pref.BytesKind),
489
490 mustMakeMapEntry(18, pref.StringKind, pref.StringKind),
491 mustMakeMapEntry(19, pref.StringKind, pref.StringKind),
492 mustMakeMapEntry(20, pref.StringKind, pref.BytesKind),
493 mustMakeMapEntry(21, pref.StringKind, pref.BytesKind),
494
495 mustMakeMapEntry(22, pref.StringKind, pref.StringKind),
496 mustMakeMapEntry(23, pref.StringKind, pref.StringKind),
497 mustMakeMapEntry(24, pref.StringKind, pref.BytesKind),
498 mustMakeMapEntry(25, pref.StringKind, pref.BytesKind),
499 },
500 })}
501
502 empty := mi.MessageOf(&MapScalars{})
503 emptyFS := empty.KnownFields()
504
505 want := mi.MessageOf(&MapScalars{
506 KeyBools: map[bool]string{true: "true", false: "false"},
507 KeyInt32s: map[int32]string{0: "zero", -1: "one", 2: "two"},
508 KeyInt64s: map[int64]string{0: "zero", -10: "ten", 20: "twenty"},
509 KeyUint32s: map[uint32]string{0: "zero", 1: "one", 2: "two"},
510 KeyUint64s: map[uint64]string{0: "zero", 10: "ten", 20: "twenty"},
511 KeyStrings: map[string]string{"": "", "foo": "bar"},
512
513 ValBools: map[string]bool{"true": true, "false": false},
514 ValInt32s: map[string]int32{"one": 1, "two": 2, "three": 3},
515 ValInt64s: map[string]int64{"ten": 10, "twenty": -20, "thirty": 30},
516 ValUint32s: map[string]uint32{"0x00": 0x00, "0xff": 0xff, "0xdead": 0xdead},
517 ValUint64s: map[string]uint64{"0x00": 0x00, "0xff": 0xff, "0xdead": 0xdead},
518 ValFloat32s: map[string]float32{"nan": float32(math.NaN()), "pi": float32(math.Pi)},
519 ValFloat64s: map[string]float64{"nan": float64(math.NaN()), "pi": float64(math.Pi)},
520 ValStrings: map[string]string{"s1": "s1", "s2": "s2"},
521 ValStringsA: map[string][]byte{"s1": []byte("s1"), "s2": []byte("s2")},
522 ValBytes: map[string][]byte{"s1": []byte("s1"), "s2": []byte("s2")},
523 ValBytesA: map[string]string{"s1": "s1", "s2": "s2"},
524
525 MyStrings1: map[MyString]MyString{"s1": "s1", "s2": "s2"},
526 MyStrings2: map[MyString]MyBytes{"s1": []byte("s1"), "s2": []byte("s2")},
527 MyBytes1: map[MyString]MyBytes{"s1": []byte("s1"), "s2": []byte("s2")},
528 MyBytes2: map[MyString]MyString{"s1": "s1", "s2": "s2"},
529
530 MyStrings3: MapStrings{"s1": "s1", "s2": "s2"},
531 MyStrings4: MapBytes{"s1": []byte("s1"), "s2": []byte("s2")},
532 MyBytes3: MapBytes{"s1": []byte("s1"), "s2": []byte("s2")},
533 MyBytes4: MapStrings{"s1": "s1", "s2": "s2"},
534 })
535 wantFS := want.KnownFields()
536
537 testMessage(t, nil, mi.MessageOf(&MapScalars{}), messageOps{
538 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, 20: false, 21: false, 22: false, 23: false, 24: false, 25: false},
539 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), 21: emptyFS.Get(21), 23: emptyFS.Get(23), 25: emptyFS.Get(25)},
540 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), 21: wantFS.Get(21), 23: wantFS.Get(23), 25: wantFS.Get(25)},
541 mapFields{
542 2: {
543 lenMap(0),
544 hasMap{int32(0): false, int32(-1): false, int32(2): false},
545 setMap{int32(0): V("zero")},
546 lenMap(1),
547 hasMap{int32(0): true, int32(-1): false, int32(2): false},
548 setMap{int32(-1): V("one")},
549 lenMap(2),
550 hasMap{int32(0): true, int32(-1): true, int32(2): false},
551 setMap{int32(2): V("two")},
552 lenMap(3),
553 hasMap{int32(0): true, int32(-1): true, int32(2): true},
554 },
555 4: {
556 setMap{uint32(0): V("zero"), uint32(1): V("one"), uint32(2): V("two")},
557 equalMap(wantFS.Get(4).Map()),
558 },
559 6: {
560 clearMap{"noexist": true},
561 setMap{"foo": V("bar")},
562 setMap{"": V("empty")},
563 getMap{"": V("empty"), "foo": V("bar"), "noexist": V(nil)},
564 setMap{"": V(""), "extra": V("extra")},
565 clearMap{"extra": true, "noexist": true},
566 },
567 8: {
568 equalMap(emptyFS.Get(8).Map()),
569 setMap{"one": V(int32(1)), "two": V(int32(2)), "three": V(int32(3))},
570 },
571 10: {
572 setMap{"0x00": V(uint32(0x00)), "0xff": V(uint32(0xff)), "0xdead": V(uint32(0xdead))},
573 lenMap(3),
574 equalMap(wantFS.Get(10).Map()),
575 getMap{"0x00": V(uint32(0x00)), "0xff": V(uint32(0xff)), "0xdead": V(uint32(0xdead)), "0xdeadbeef": V(nil)},
576 },
577 12: {
578 setMap{"nan": V(float32(math.NaN())), "pi": V(float32(math.Pi)), "e": V(float32(math.E))},
579 clearMap{"e": true, "phi": true},
580 rangeMap{"nan": V(float32(math.NaN())), "pi": V(float32(math.Pi))},
581 },
582 14: {
583 equalMap(emptyFS.Get(14).Map()),
584 setMap{"s1": V("s1"), "s2": V("s2")},
585 },
586 16: {
587 setMap{"s1": V([]byte("s1")), "s2": V([]byte("s2"))},
588 equalMap(wantFS.Get(16).Map()),
589 },
590 18: {
591 hasMap{"s1": false, "s2": false, "s3": false},
592 setMap{"s1": V("s1"), "s2": V("s2")},
593 hasMap{"s1": true, "s2": true, "s3": false},
594 },
595 20: {
596 equalMap(emptyFS.Get(20).Map()),
597 setMap{"s1": V([]byte("s1")), "s2": V([]byte("s2"))},
598 },
599 22: {
600 rangeMap{},
601 setMap{"s1": V("s1"), "s2": V("s2")},
602 rangeMap{"s1": V("s1"), "s2": V("s2")},
603 lenMap(2),
604 },
605 24: {
606 setMap{"s1": V([]byte("s1")), "s2": V([]byte("s2"))},
607 equalMap(wantFS.Get(24).Map()),
608 },
609 },
610 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, 20: true, 21: true, 22: true, 23: true, 24: true, 25: true},
611 equalMessage(want),
612 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, 20: true, 21: true, 22: true, 23: true, 24: true, 25: true},
613 equalMessage(empty),
Joe Tsai91e14662018-09-13 13:24:35 -0700614 })
615}
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700616
Joe Tsai91e14662018-09-13 13:24:35 -0700617// TODO: Need to test singular and repeated messages
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700618
Joe Tsai91e14662018-09-13 13:24:35 -0700619var cmpOpts = cmp.Options{
620 cmp.Transformer("UnwrapValue", func(v pref.Value) interface{} {
621 return v.Interface()
622 }),
623 cmp.Transformer("UnwrapMessage", func(m pref.Message) interface{} {
624 v := m.Interface()
625 if v, ok := v.(interface{ Unwrap() interface{} }); ok {
626 return v.Unwrap()
627 }
628 return v
629 }),
630 cmp.Transformer("UnwrapVector", func(v pref.Vector) interface{} {
631 return v.(interface{ Unwrap() interface{} }).Unwrap()
632 }),
633 cmp.Transformer("UnwrapMap", func(m pref.Map) interface{} {
634 return m.(interface{ Unwrap() interface{} }).Unwrap()
635 }),
636 cmpopts.EquateNaNs(),
637}
638
639func testMessage(t *testing.T, p path, m pref.Message, tt messageOps) {
640 fs := m.KnownFields()
641 for i, op := range tt {
642 p.Push(i)
643 switch op := op.(type) {
644 case equalMessage:
645 if diff := cmp.Diff(op, m, cmpOpts); diff != "" {
646 t.Errorf("operation %v, message mismatch (-want, +got):\n%s", p, diff)
647 }
648 case hasFields:
649 got := map[pref.FieldNumber]bool{}
650 want := map[pref.FieldNumber]bool(op)
651 for n := range want {
652 got[n] = fs.Has(n)
653 }
654 if diff := cmp.Diff(want, got); diff != "" {
655 t.Errorf("operation %v, KnownFields.Has mismatch (-want, +got):\n%s", p, diff)
656 }
657 case getFields:
658 got := map[pref.FieldNumber]pref.Value{}
659 want := map[pref.FieldNumber]pref.Value(op)
660 for n := range want {
661 got[n] = fs.Get(n)
662 }
663 if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
664 t.Errorf("operation %v, KnownFields.Get mismatch (-want, +got):\n%s", p, diff)
665 }
666 case setFields:
667 for n, v := range op {
668 fs.Set(n, v)
669 }
670 case clearFields:
671 for n, ok := range op {
672 if ok {
673 fs.Clear(n)
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700674 }
675 }
Joe Tsai91e14662018-09-13 13:24:35 -0700676 case vectorFields:
677 for n, tt := range op {
678 p.Push(int(n))
679 testVectors(t, p, fs.Mutable(n).(pref.Vector), tt)
680 p.Pop()
681 }
Joe Tsaibbfaeb72018-10-17 00:27:21 +0000682 case mapFields:
683 for n, tt := range op {
684 p.Push(int(n))
685 testMaps(t, p, fs.Mutable(n).(pref.Map), tt)
686 p.Pop()
687 }
Joe Tsai91e14662018-09-13 13:24:35 -0700688 default:
689 t.Fatalf("operation %v, invalid operation: %T", p, op)
690 }
691 p.Pop()
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700692 }
693}
Joe Tsai91e14662018-09-13 13:24:35 -0700694
695func testVectors(t *testing.T, p path, v pref.Vector, tt vectorOps) {
696 for i, op := range tt {
697 p.Push(i)
698 switch op := op.(type) {
699 case equalVector:
700 if diff := cmp.Diff(op, v, cmpOpts); diff != "" {
701 t.Errorf("operation %v, vector mismatch (-want, +got):\n%s", p, diff)
702 }
703 case lenVector:
704 if got, want := v.Len(), int(op); got != want {
705 t.Errorf("operation %v, Vector.Len = %d, want %d", p, got, want)
706 }
707 case getVector:
708 got := map[int]pref.Value{}
709 want := map[int]pref.Value(op)
710 for n := range want {
711 got[n] = v.Get(n)
712 }
713 if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
714 t.Errorf("operation %v, Vector.Get mismatch (-want, +got):\n%s", p, diff)
715 }
716 case setVector:
717 for n, e := range op {
718 v.Set(n, e)
719 }
720 case appendVector:
721 for _, e := range op {
722 v.Append(e)
723 }
724 case truncVector:
725 v.Truncate(int(op))
726 default:
727 t.Fatalf("operation %v, invalid operation: %T", p, op)
728 }
729 p.Pop()
730 }
731}
732
Joe Tsaibbfaeb72018-10-17 00:27:21 +0000733func testMaps(t *testing.T, p path, m pref.Map, tt mapOps) {
734 for i, op := range tt {
735 p.Push(i)
736 switch op := op.(type) {
737 case equalMap:
738 if diff := cmp.Diff(op, m, cmpOpts); diff != "" {
739 t.Errorf("operation %v, map mismatch (-want, +got):\n%s", p, diff)
740 }
741 case lenMap:
742 if got, want := m.Len(), int(op); got != want {
743 t.Errorf("operation %v, Map.Len = %d, want %d", p, got, want)
744 }
745 case hasMap:
746 got := map[interface{}]bool{}
747 want := map[interface{}]bool(op)
748 for k := range want {
749 got[k] = m.Has(V(k).MapKey())
750 }
751 if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
752 t.Errorf("operation %v, Map.Has mismatch (-want, +got):\n%s", p, diff)
753 }
754 case getMap:
755 got := map[interface{}]pref.Value{}
756 want := map[interface{}]pref.Value(op)
757 for k := range want {
758 got[k] = m.Get(V(k).MapKey())
759 }
760 if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
761 t.Errorf("operation %v, Map.Get mismatch (-want, +got):\n%s", p, diff)
762 }
763 case setMap:
764 for k, v := range op {
765 m.Set(V(k).MapKey(), v)
766 }
767 case clearMap:
768 for v, ok := range op {
769 if ok {
770 m.Clear(V(v).MapKey())
771 }
772 }
773 case rangeMap:
774 got := map[interface{}]pref.Value{}
775 want := map[interface{}]pref.Value(op)
776 m.Range(func(k pref.MapKey, v pref.Value) bool {
777 got[k.Interface()] = v
778 return true
779 })
780 if diff := cmp.Diff(want, got, cmpOpts); diff != "" {
781 t.Errorf("operation %v, Map.Range mismatch (-want, +got):\n%s", p, diff)
782 }
783 default:
784 t.Fatalf("operation %v, invalid operation: %T", p, op)
785 }
786 p.Pop()
787 }
788}
789
Joe Tsai91e14662018-09-13 13:24:35 -0700790type path []int
791
792func (p *path) Push(i int) { *p = append(*p, i) }
793func (p *path) Pop() { *p = (*p)[:len(*p)-1] }
794func (p path) String() string {
795 var ss []string
796 for _, i := range p {
797 ss = append(ss, fmt.Sprint(i))
798 }
799 return strings.Join(ss, ".")
800}