1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package proto_test
33
34 import (
35 "testing"
36
37 "github.com/gogo/protobuf/proto"
38
39 proto3pb "github.com/gogo/protobuf/proto/proto3_proto"
40 pb "github.com/gogo/protobuf/proto/test_proto"
41 )
42
43 var cloneTestMessage = &pb.MyMessage{
44 Count: proto.Int32(42),
45 Name: proto.String("Dave"),
46 Pet: []string{"bunny", "kitty", "horsey"},
47 Inner: &pb.InnerMessage{
48 Host: proto.String("niles"),
49 Port: proto.Int32(9099),
50 Connected: proto.Bool(true),
51 },
52 Others: []*pb.OtherMessage{
53 {
54 Value: []byte("some bytes"),
55 },
56 },
57 Somegroup: &pb.MyMessage_SomeGroup{
58 GroupField: proto.Int32(6),
59 },
60 RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
61 }
62
63 func init() {
64 ext := &pb.Ext{
65 Data: proto.String("extension"),
66 }
67 if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil {
68 panic("SetExtension: " + err.Error())
69 }
70 }
71
72 func TestClone(t *testing.T) {
73 m := proto.Clone(cloneTestMessage).(*pb.MyMessage)
74 if !proto.Equal(m, cloneTestMessage) {
75 t.Fatalf("Clone(%v) = %v", cloneTestMessage, m)
76 }
77
78
79 *m.Inner.Port++
80 if proto.Equal(m, cloneTestMessage) {
81 t.Error("Mutating clone changed the original")
82 }
83
84 if &m.Pet[0] == &cloneTestMessage.Pet[0] {
85 t.Error("Pet: repeated field not copied")
86 }
87 if &m.Others[0] == &cloneTestMessage.Others[0] {
88 t.Error("Others: repeated field not copied")
89 }
90 if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] {
91 t.Error("Others[0].Value: bytes field not copied")
92 }
93 if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] {
94 t.Error("RepBytes: repeated field not copied")
95 }
96 if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] {
97 t.Error("RepBytes[0]: bytes field not copied")
98 }
99 }
100
101 func TestCloneNil(t *testing.T) {
102 var m *pb.MyMessage
103 if c := proto.Clone(m); !proto.Equal(m, c) {
104 t.Errorf("Clone(%v) = %v", m, c)
105 }
106 }
107
108 var mergeTests = []struct {
109 src, dst, want proto.Message
110 }{
111 {
112 src: &pb.MyMessage{
113 Count: proto.Int32(42),
114 },
115 dst: &pb.MyMessage{
116 Name: proto.String("Dave"),
117 },
118 want: &pb.MyMessage{
119 Count: proto.Int32(42),
120 Name: proto.String("Dave"),
121 },
122 },
123 {
124 src: &pb.MyMessage{
125 Inner: &pb.InnerMessage{
126 Host: proto.String("hey"),
127 Connected: proto.Bool(true),
128 },
129 Pet: []string{"horsey"},
130 Others: []*pb.OtherMessage{
131 {
132 Value: []byte("some bytes"),
133 },
134 },
135 },
136 dst: &pb.MyMessage{
137 Inner: &pb.InnerMessage{
138 Host: proto.String("niles"),
139 Port: proto.Int32(9099),
140 },
141 Pet: []string{"bunny", "kitty"},
142 Others: []*pb.OtherMessage{
143 {
144 Key: proto.Int64(31415926535),
145 },
146 {
147
148 Inner: nil,
149 },
150 },
151 },
152 want: &pb.MyMessage{
153 Inner: &pb.InnerMessage{
154 Host: proto.String("hey"),
155 Connected: proto.Bool(true),
156 Port: proto.Int32(9099),
157 },
158 Pet: []string{"bunny", "kitty", "horsey"},
159 Others: []*pb.OtherMessage{
160 {
161 Key: proto.Int64(31415926535),
162 },
163 {},
164 {
165 Value: []byte("some bytes"),
166 },
167 },
168 },
169 },
170 {
171 src: &pb.MyMessage{
172 RepBytes: [][]byte{[]byte("wow")},
173 },
174 dst: &pb.MyMessage{
175 Somegroup: &pb.MyMessage_SomeGroup{
176 GroupField: proto.Int32(6),
177 },
178 RepBytes: [][]byte{[]byte("sham")},
179 },
180 want: &pb.MyMessage{
181 Somegroup: &pb.MyMessage_SomeGroup{
182 GroupField: proto.Int32(6),
183 },
184 RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
185 },
186 },
187
188 {
189 src: &pb.OtherMessage{Value: []byte("foo")},
190 dst: &pb.OtherMessage{Value: []byte("bar")},
191 want: &pb.OtherMessage{Value: []byte("foo")},
192 },
193 {
194 src: &pb.MessageWithMap{
195 NameMapping: map[int32]string{6: "Nigel"},
196 MsgMapping: map[int64]*pb.FloatingPoint{
197 0x4001: {F: proto.Float64(2.0)},
198 0x4002: {
199 F: proto.Float64(2.0),
200 },
201 },
202 ByteMapping: map[bool][]byte{true: []byte("wowsa")},
203 },
204 dst: &pb.MessageWithMap{
205 NameMapping: map[int32]string{
206 6: "Bruce",
207 7: "Andrew",
208 },
209 MsgMapping: map[int64]*pb.FloatingPoint{
210 0x4002: {
211 F: proto.Float64(3.0),
212 Exact: proto.Bool(true),
213 },
214 },
215 },
216 want: &pb.MessageWithMap{
217 NameMapping: map[int32]string{
218 6: "Nigel",
219 7: "Andrew",
220 },
221 MsgMapping: map[int64]*pb.FloatingPoint{
222 0x4001: {F: proto.Float64(2.0)},
223 0x4002: {
224 F: proto.Float64(2.0),
225 },
226 },
227 ByteMapping: map[bool][]byte{true: []byte("wowsa")},
228 },
229 },
230
231
232 {
233 src: &proto3pb.Message{
234 Name: "Aaron",
235 Data: []byte(""),
236 },
237 dst: &proto3pb.Message{
238 HeightInCm: 176,
239 Data: []byte("texas!"),
240 },
241 want: &proto3pb.Message{
242 Name: "Aaron",
243 HeightInCm: 176,
244 Data: []byte("texas!"),
245 },
246 },
247
248 {
249 src: &pb.Communique{
250 Union: &pb.Communique_Number{Number: 41},
251 },
252 dst: &pb.Communique{
253 Union: &pb.Communique_Name{Name: "Bobby Tables"},
254 },
255 want: &pb.Communique{
256 Union: &pb.Communique_Number{Number: 41},
257 },
258 },
259 {
260 src: &pb.Communique{},
261 dst: &pb.Communique{Union: &pb.Communique_Name{Name: "Bobby Tables"}},
262 want: &pb.Communique{Union: &pb.Communique_Name{Name: "Bobby Tables"}},
263 },
264 {
265 src: &pb.Communique{Union: &pb.Communique_Number{Number: 1337}},
266 dst: &pb.Communique{},
267 want: &pb.Communique{Union: &pb.Communique_Number{Number: 1337}},
268 },
269 {
270 src: &pb.Communique{Union: &pb.Communique_Col{Col: pb.MyMessage_RED}},
271 dst: &pb.Communique{},
272 want: &pb.Communique{Union: &pb.Communique_Col{Col: pb.MyMessage_RED}},
273 },
274 {
275 src: &pb.Communique{Union: &pb.Communique_Data{Data: []byte("hello")}},
276 dst: &pb.Communique{},
277 want: &pb.Communique{Union: &pb.Communique_Data{Data: []byte("hello")}},
278 },
279 {
280 src: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{BytesField: []byte{1, 2, 3}}}},
281 dst: &pb.Communique{},
282 want: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{BytesField: []byte{1, 2, 3}}}},
283 },
284 {
285 src: &pb.Communique{Union: &pb.Communique_Msg{}},
286 dst: &pb.Communique{},
287 want: &pb.Communique{Union: &pb.Communique_Msg{}},
288 },
289 {
290 src: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{StringField: proto.String("123")}}},
291 dst: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{BytesField: []byte{1, 2, 3}}}},
292 want: &pb.Communique{Union: &pb.Communique_Msg{Msg: &pb.Strings{StringField: proto.String("123"), BytesField: []byte{1, 2, 3}}}},
293 },
294 {
295 src: &proto3pb.Message{
296 Terrain: map[string]*proto3pb.Nested{
297 "kay_a": {Cute: true},
298 "kay_b": {Bunny: "rabbit"},
299 },
300 },
301 dst: &proto3pb.Message{
302 Terrain: map[string]*proto3pb.Nested{
303 "kay_a": {Bunny: "lost"},
304 "kay_c": {Bunny: "bunny"},
305 },
306 },
307 want: &proto3pb.Message{
308 Terrain: map[string]*proto3pb.Nested{
309 "kay_a": {Cute: true},
310 "kay_b": {Bunny: "rabbit"},
311 "kay_c": {Bunny: "bunny"},
312 },
313 },
314 },
315 {
316 src: &pb.GoTest{
317 F_BoolRepeated: []bool{},
318 F_Int32Repeated: []int32{},
319 F_Int64Repeated: []int64{},
320 F_Uint32Repeated: []uint32{},
321 F_Uint64Repeated: []uint64{},
322 F_FloatRepeated: []float32{},
323 F_DoubleRepeated: []float64{},
324 F_StringRepeated: []string{},
325 F_BytesRepeated: [][]byte{},
326 },
327 dst: &pb.GoTest{},
328 want: &pb.GoTest{
329 F_BoolRepeated: []bool{},
330 F_Int32Repeated: []int32{},
331 F_Int64Repeated: []int64{},
332 F_Uint32Repeated: []uint32{},
333 F_Uint64Repeated: []uint64{},
334 F_FloatRepeated: []float32{},
335 F_DoubleRepeated: []float64{},
336 F_StringRepeated: []string{},
337 F_BytesRepeated: [][]byte{},
338 },
339 },
340 {
341 src: &pb.GoTest{},
342 dst: &pb.GoTest{
343 F_BoolRepeated: []bool{},
344 F_Int32Repeated: []int32{},
345 F_Int64Repeated: []int64{},
346 F_Uint32Repeated: []uint32{},
347 F_Uint64Repeated: []uint64{},
348 F_FloatRepeated: []float32{},
349 F_DoubleRepeated: []float64{},
350 F_StringRepeated: []string{},
351 F_BytesRepeated: [][]byte{},
352 },
353 want: &pb.GoTest{
354 F_BoolRepeated: []bool{},
355 F_Int32Repeated: []int32{},
356 F_Int64Repeated: []int64{},
357 F_Uint32Repeated: []uint32{},
358 F_Uint64Repeated: []uint64{},
359 F_FloatRepeated: []float32{},
360 F_DoubleRepeated: []float64{},
361 F_StringRepeated: []string{},
362 F_BytesRepeated: [][]byte{},
363 },
364 },
365 {
366 src: &pb.GoTest{
367 F_BytesRepeated: [][]byte{nil, {}, {0}},
368 },
369 dst: &pb.GoTest{},
370 want: &pb.GoTest{
371 F_BytesRepeated: [][]byte{nil, {}, {0}},
372 },
373 },
374 {
375 src: &pb.MyMessage{
376 Others: []*pb.OtherMessage{},
377 },
378 dst: &pb.MyMessage{},
379 want: &pb.MyMessage{
380 Others: []*pb.OtherMessage{},
381 },
382 },
383 }
384
385 func TestMerge(t *testing.T) {
386 for _, m := range mergeTests {
387 got := proto.Clone(m.dst)
388 if !proto.Equal(got, m.dst) {
389 t.Errorf("Clone()\ngot %v\nwant %v", got, m.dst)
390 continue
391 }
392 proto.Merge(got, m.src)
393 if !proto.Equal(got, m.want) {
394 t.Errorf("Merge(%v, %v)\ngot %v\nwant %v", m.dst, m.src, got, m.want)
395 }
396 }
397 }
398
View as plain text