blob: c21c40e2f240d6c40330989f7a152622831c64ec [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 (
8 "reflect"
9 "testing"
10
11 "github.com/google/go-cmp/cmp"
12
Joe Tsai01ab2962018-09-21 17:44:00 -070013 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
14 ptype "github.com/golang/protobuf/v2/reflect/prototype"
Joe Tsaifa02f4e2018-09-12 16:20:37 -070015)
16
Joe Tsaic6b75612018-09-13 14:24:37 -070017func mustMakeMessageDesc(t ptype.StandaloneMessage) pref.MessageDescriptor {
18 md, err := ptype.NewMessage(&t)
19 if err != nil {
20 panic(err)
21 }
22 return md
23}
24
Joe Tsaifa02f4e2018-09-12 16:20:37 -070025type (
26 MyBool bool
27 MyInt32 int32
28 MyInt64 int64
29 MyUint32 uint32
30 MyUint64 uint64
31 MyFloat32 float32
32 MyFloat64 float64
33 MyString string
34 MyBytes []byte
35)
36
37type ScalarProto2 struct {
38 Bool *bool `protobuf:"1"`
39 Int32 *int32 `protobuf:"2"`
40 Int64 *int64 `protobuf:"3"`
41 Uint32 *uint32 `protobuf:"4"`
42 Uint64 *uint64 `protobuf:"5"`
43 Float32 *float32 `protobuf:"6"`
44 Float64 *float64 `protobuf:"7"`
45 String *string `protobuf:"8"`
46 StringA []byte `protobuf:"9"`
47 Bytes []byte `protobuf:"10"`
48 BytesA *string `protobuf:"11"`
49
50 MyBool *MyBool `protobuf:"12"`
51 MyInt32 *MyInt32 `protobuf:"13"`
52 MyInt64 *MyInt64 `protobuf:"14"`
53 MyUint32 *MyUint32 `protobuf:"15"`
54 MyUint64 *MyUint64 `protobuf:"16"`
55 MyFloat32 *MyFloat32 `protobuf:"17"`
56 MyFloat64 *MyFloat64 `protobuf:"18"`
57 MyString *MyString `protobuf:"19"`
58 MyStringA MyBytes `protobuf:"20"`
59 MyBytes MyBytes `protobuf:"21"`
60 MyBytesA *MyString `protobuf:"22"`
61}
62
Joe Tsaic6b75612018-09-13 14:24:37 -070063var scalarProto2Desc = mustMakeMessageDesc(ptype.StandaloneMessage{
64 Syntax: pref.Proto2,
65 FullName: "ScalarProto2",
66 Fields: []ptype.Field{
67 {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: pref.ValueOf(bool(true))},
68 {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: pref.ValueOf(int32(2))},
69 {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: pref.ValueOf(int64(3))},
70 {Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: pref.ValueOf(uint32(4))},
71 {Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: pref.ValueOf(uint64(5))},
72 {Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: pref.ValueOf(float32(6))},
73 {Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: pref.ValueOf(float64(7))},
74 {Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind, Default: pref.ValueOf(string("8"))},
75 {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind, Default: pref.ValueOf(string("9"))},
76 {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: pref.ValueOf([]byte("10"))},
77 {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: pref.ValueOf([]byte("11"))},
78
79 {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind, Default: pref.ValueOf(bool(true))},
80 {Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind, Default: pref.ValueOf(int32(13))},
81 {Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind, Default: pref.ValueOf(int64(14))},
82 {Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind, Default: pref.ValueOf(uint32(15))},
83 {Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind, Default: pref.ValueOf(uint64(16))},
84 {Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind, Default: pref.ValueOf(float32(17))},
85 {Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind, Default: pref.ValueOf(float64(18))},
86 {Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind, Default: pref.ValueOf(string("19"))},
87 {Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind, Default: pref.ValueOf(string("20"))},
88 {Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: pref.ValueOf([]byte("21"))},
89 {Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind, Default: pref.ValueOf([]byte("22"))},
90 },
91})
92
Joe Tsaifa02f4e2018-09-12 16:20:37 -070093type ScalarProto3 struct {
94 Bool bool `protobuf:"1"`
95 Int32 int32 `protobuf:"2"`
96 Int64 int64 `protobuf:"3"`
97 Uint32 uint32 `protobuf:"4"`
98 Uint64 uint64 `protobuf:"5"`
99 Float32 float32 `protobuf:"6"`
100 Float64 float64 `protobuf:"7"`
101 String string `protobuf:"8"`
102 StringA []byte `protobuf:"9"`
103 Bytes []byte `protobuf:"10"`
104 BytesA string `protobuf:"11"`
105
106 MyBool MyBool `protobuf:"12"`
107 MyInt32 MyInt32 `protobuf:"13"`
108 MyInt64 MyInt64 `protobuf:"14"`
109 MyUint32 MyUint32 `protobuf:"15"`
110 MyUint64 MyUint64 `protobuf:"16"`
111 MyFloat32 MyFloat32 `protobuf:"17"`
112 MyFloat64 MyFloat64 `protobuf:"18"`
113 MyString MyString `protobuf:"19"`
114 MyStringA MyBytes `protobuf:"20"`
115 MyBytes MyBytes `protobuf:"21"`
116 MyBytesA MyString `protobuf:"22"`
117}
118
Joe Tsaic6b75612018-09-13 14:24:37 -0700119var scalarProto3Desc = mustMakeMessageDesc(ptype.StandaloneMessage{
120 Syntax: pref.Proto3,
121 FullName: "ScalarProto3",
122 Fields: []ptype.Field{
123 {Name: "f1", Number: 1, Cardinality: pref.Optional, Kind: pref.BoolKind},
124 {Name: "f2", Number: 2, Cardinality: pref.Optional, Kind: pref.Int32Kind},
125 {Name: "f3", Number: 3, Cardinality: pref.Optional, Kind: pref.Int64Kind},
126 {Name: "f4", Number: 4, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
127 {Name: "f5", Number: 5, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
128 {Name: "f6", Number: 6, Cardinality: pref.Optional, Kind: pref.FloatKind},
129 {Name: "f7", Number: 7, Cardinality: pref.Optional, Kind: pref.DoubleKind},
130 {Name: "f8", Number: 8, Cardinality: pref.Optional, Kind: pref.StringKind},
131 {Name: "f9", Number: 9, Cardinality: pref.Optional, Kind: pref.StringKind},
132 {Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.BytesKind},
133 {Name: "f11", Number: 11, Cardinality: pref.Optional, Kind: pref.BytesKind},
134
135 {Name: "f12", Number: 12, Cardinality: pref.Optional, Kind: pref.BoolKind},
136 {Name: "f13", Number: 13, Cardinality: pref.Optional, Kind: pref.Int32Kind},
137 {Name: "f14", Number: 14, Cardinality: pref.Optional, Kind: pref.Int64Kind},
138 {Name: "f15", Number: 15, Cardinality: pref.Optional, Kind: pref.Uint32Kind},
139 {Name: "f16", Number: 16, Cardinality: pref.Optional, Kind: pref.Uint64Kind},
140 {Name: "f17", Number: 17, Cardinality: pref.Optional, Kind: pref.FloatKind},
141 {Name: "f18", Number: 18, Cardinality: pref.Optional, Kind: pref.DoubleKind},
142 {Name: "f19", Number: 19, Cardinality: pref.Optional, Kind: pref.StringKind},
143 {Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.StringKind},
144 {Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.BytesKind},
145 {Name: "f22", Number: 22, Cardinality: pref.Optional, Kind: pref.BytesKind},
146 },
147})
148
149func TestKnownFields(t *testing.T) {
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700150 V := pref.ValueOf
151 type (
152 // has checks that each field matches the list.
153 hasOp []bool
154 // get checks that each field returns values matching the list.
155 getOp []pref.Value
156 // set calls set on each field with the given value in the list.
157 setOp []pref.Value
158 // clear calls clear on each field.
159 clearOp []bool
160 // equal checks that the current message equals the provided value.
161 equalOp struct{ want interface{} }
162
163 testOp interface{} // has | get | set | clear | equal
164 )
165
166 tests := []struct {
167 structType reflect.Type
Joe Tsaic6b75612018-09-13 14:24:37 -0700168 messageDesc pref.MessageDescriptor
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700169 testOps []testOp
170 }{{
Joe Tsaic6b75612018-09-13 14:24:37 -0700171 structType: reflect.TypeOf(ScalarProto2{}),
172 messageDesc: scalarProto2Desc,
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700173 testOps: []testOp{
174 hasOp([]bool{
175 false, false, false, false, false, false, false, false, false, false, false,
176 false, false, false, false, false, false, false, false, false, false, false,
177 }),
178 getOp([]pref.Value{
179 V(bool(true)), V(int32(2)), V(int64(3)), V(uint32(4)), V(uint64(5)), V(float32(6)), V(float64(7)), V(string("8")), V(string("9")), V([]byte("10")), V([]byte("11")),
180 V(bool(true)), V(int32(13)), V(int64(14)), V(uint32(15)), V(uint64(16)), V(float32(17)), V(float64(18)), V(string("19")), V(string("20")), V([]byte("21")), V([]byte("22")),
181 }),
182 setOp([]pref.Value{
183 V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
184 V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
185 }),
186 hasOp([]bool{
187 true, true, true, true, true, true, true, true, true, true, true,
188 true, true, true, true, true, true, true, true, true, true, true,
189 }),
190 equalOp{&ScalarProto2{
191 new(bool), new(int32), new(int64), new(uint32), new(uint64), new(float32), new(float64), new(string), []byte{}, []byte{}, new(string),
192 new(MyBool), new(MyInt32), new(MyInt64), new(MyUint32), new(MyUint64), new(MyFloat32), new(MyFloat64), new(MyString), MyBytes{}, MyBytes{}, new(MyString),
193 }},
194 clearOp([]bool{
195 true, true, true, true, true, true, true, true, true, true, true,
196 true, true, true, true, true, true, true, true, true, true, true,
197 }),
198 equalOp{&ScalarProto2{}},
199 },
200 }, {
Joe Tsaic6b75612018-09-13 14:24:37 -0700201 structType: reflect.TypeOf(ScalarProto3{}),
202 messageDesc: scalarProto3Desc,
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700203 testOps: []testOp{
204 hasOp([]bool{
205 false, false, false, false, false, false, false, false, false, false, false,
206 false, false, false, false, false, false, false, false, false, false, false,
207 }),
208 getOp([]pref.Value{
209 V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
210 V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
211 }),
212 setOp([]pref.Value{
213 V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
214 V(bool(false)), V(int32(0)), V(int64(0)), V(uint32(0)), V(uint64(0)), V(float32(0)), V(float64(0)), V(string("")), V(string("")), V([]byte(nil)), V([]byte(nil)),
215 }),
216 hasOp([]bool{
217 false, false, false, false, false, false, false, false, false, false, false,
218 false, false, false, false, false, false, false, false, false, false, false,
219 }),
220 equalOp{&ScalarProto3{}},
221 setOp([]pref.Value{
222 V(bool(true)), V(int32(2)), V(int64(3)), V(uint32(4)), V(uint64(5)), V(float32(6)), V(float64(7)), V(string("8")), V(string("9")), V([]byte("10")), V([]byte("11")),
223 V(bool(true)), V(int32(13)), V(int64(14)), V(uint32(15)), V(uint64(16)), V(float32(17)), V(float64(18)), V(string("19")), V(string("20")), V([]byte("21")), V([]byte("22")),
224 }),
225 hasOp([]bool{
226 true, true, true, true, true, true, true, true, true, true, true,
227 true, true, true, true, true, true, true, true, true, true, true,
228 }),
229 equalOp{&ScalarProto3{
230 true, 2, 3, 4, 5, 6, 7, "8", []byte("9"), []byte("10"), "11",
231 true, 13, 14, 15, 16, 17, 18, "19", []byte("20"), []byte("21"), "22",
232 }},
233 clearOp([]bool{
234 true, true, true, true, true, true, true, true, true, true, true,
235 true, true, true, true, true, true, true, true, true, true, true,
236 }),
237 equalOp{&ScalarProto3{}},
238 },
239 }}
240
241 for _, tt := range tests {
242 t.Run(tt.structType.Name(), func(t *testing.T) {
Joe Tsaic6b75612018-09-13 14:24:37 -0700243 mi := MessageType{Desc: tt.messageDesc}
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700244
245 // Test the field functions.
Joe Tsaic6b75612018-09-13 14:24:37 -0700246 p := reflect.New(tt.structType).Interface()
247 m := mi.MessageOf(p)
248 fs := m.KnownFields()
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700249 for i, op := range tt.testOps {
250 switch op := op.(type) {
251 case hasOp:
252 got := map[pref.FieldNumber]bool{}
253 want := map[pref.FieldNumber]bool{}
254 for j, ok := range op {
255 n := pref.FieldNumber(j + 1)
Joe Tsaic6b75612018-09-13 14:24:37 -0700256 got[n] = fs.Has(n)
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700257 want[n] = ok
258 }
259 if diff := cmp.Diff(want, got); diff != "" {
260 t.Errorf("operation %d, has mismatch (-want, +got):\n%s", i, diff)
261 }
262 case getOp:
263 got := map[pref.FieldNumber]pref.Value{}
264 want := map[pref.FieldNumber]pref.Value{}
265 for j, v := range op {
266 n := pref.FieldNumber(j + 1)
Joe Tsaic6b75612018-09-13 14:24:37 -0700267 got[n] = fs.Get(n)
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700268 want[n] = v
269 }
270 xformValue := cmp.Transformer("", func(v pref.Value) interface{} {
271 return v.Interface()
272 })
273 if diff := cmp.Diff(want, got, xformValue); diff != "" {
274 t.Errorf("operation %d, get mismatch (-want, +got):\n%s", i, diff)
275 }
276 case setOp:
277 for j, v := range op {
278 n := pref.FieldNumber(j + 1)
Joe Tsaic6b75612018-09-13 14:24:37 -0700279 fs.Set(n, v)
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700280 }
281 case clearOp:
282 for j, ok := range op {
283 n := pref.FieldNumber(j + 1)
284 if ok {
Joe Tsaic6b75612018-09-13 14:24:37 -0700285 fs.Clear(n)
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700286 }
287 }
288 case equalOp:
Joe Tsaic6b75612018-09-13 14:24:37 -0700289 got := m.(interface{ Unwrap() interface{} }).Unwrap()
Joe Tsaifa02f4e2018-09-12 16:20:37 -0700290 if diff := cmp.Diff(op.want, got); diff != "" {
291 t.Errorf("operation %d, equal mismatch (-want, +got):\n%s", i, diff)
292 }
293 }
294 }
295 })
296 }
297}