1// Copyright 2019 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 proto_test
6
7import (
8	"fmt"
9	"reflect"
10	"sync"
11	"testing"
12
13	"github.com/google/go-cmp/cmp"
14
15	"google.golang.org/protobuf/encoding/prototext"
16	"google.golang.org/protobuf/internal/protobuild"
17	"google.golang.org/protobuf/proto"
18	"google.golang.org/protobuf/reflect/protoreflect"
19	"google.golang.org/protobuf/testing/protocmp"
20	"google.golang.org/protobuf/testing/protopack"
21	"google.golang.org/protobuf/types/dynamicpb"
22
23	legacypb "google.golang.org/protobuf/internal/testprotos/legacy"
24	testpb "google.golang.org/protobuf/internal/testprotos/test"
25	test3pb "google.golang.org/protobuf/internal/testprotos/test3"
26)
27
28type testMerge struct {
29	desc  string
30	dst   protobuild.Message
31	src   protobuild.Message
32	want  protobuild.Message // if dst and want are nil, want = src
33	types []proto.Message
34}
35
36var testMerges = []testMerge{{
37	desc: "clone a large message",
38	src: protobuild.Message{
39		"optional_int32":       1001,
40		"optional_int64":       1002,
41		"optional_uint32":      1003,
42		"optional_uint64":      1004,
43		"optional_sint32":      1005,
44		"optional_sint64":      1006,
45		"optional_fixed32":     1007,
46		"optional_fixed64":     1008,
47		"optional_sfixed32":    1009,
48		"optional_sfixed64":    1010,
49		"optional_float":       1011.5,
50		"optional_double":      1012.5,
51		"optional_bool":        true,
52		"optional_string":      "string",
53		"optional_bytes":       []byte("bytes"),
54		"optional_nested_enum": 1,
55		"optional_nested_message": protobuild.Message{
56			"a": 100,
57		},
58		"repeated_int32":       []int32{1001, 2001},
59		"repeated_int64":       []int64{1002, 2002},
60		"repeated_uint32":      []uint32{1003, 2003},
61		"repeated_uint64":      []uint64{1004, 2004},
62		"repeated_sint32":      []int32{1005, 2005},
63		"repeated_sint64":      []int64{1006, 2006},
64		"repeated_fixed32":     []uint32{1007, 2007},
65		"repeated_fixed64":     []uint64{1008, 2008},
66		"repeated_sfixed32":    []int32{1009, 2009},
67		"repeated_sfixed64":    []int64{1010, 2010},
68		"repeated_float":       []float32{1011.5, 2011.5},
69		"repeated_double":      []float64{1012.5, 2012.5},
70		"repeated_bool":        []bool{true, false},
71		"repeated_string":      []string{"foo", "bar"},
72		"repeated_bytes":       []string{"FOO", "BAR"},
73		"repeated_nested_enum": []string{"FOO", "BAR"},
74		"repeated_nested_message": []protobuild.Message{
75			{"a": 200},
76			{"a": 300},
77		},
78	},
79}, {
80	desc: "clone maps",
81	src: protobuild.Message{
82		"map_int32_int32":       map[int32]int32{1056: 1156, 2056: 2156},
83		"map_int64_int64":       map[int64]int64{1057: 1157, 2057: 2157},
84		"map_uint32_uint32":     map[uint32]uint32{1058: 1158, 2058: 2158},
85		"map_uint64_uint64":     map[uint64]uint64{1059: 1159, 2059: 2159},
86		"map_sint32_sint32":     map[int32]int32{1060: 1160, 2060: 2160},
87		"map_sint64_sint64":     map[int64]int64{1061: 1161, 2061: 2161},
88		"map_fixed32_fixed32":   map[uint32]uint32{1062: 1162, 2062: 2162},
89		"map_fixed64_fixed64":   map[uint64]uint64{1063: 1163, 2063: 2163},
90		"map_sfixed32_sfixed32": map[int32]int32{1064: 1164, 2064: 2164},
91		"map_sfixed64_sfixed64": map[int64]int64{1065: 1165, 2065: 2165},
92		"map_int32_float":       map[int32]float32{1066: 1166.5, 2066: 2166.5},
93		"map_int32_double":      map[int32]float64{1067: 1167.5, 2067: 2167.5},
94		"map_bool_bool":         map[bool]bool{true: false, false: true},
95		"map_string_string":     map[string]string{"69.1.key": "69.1.val", "69.2.key": "69.2.val"},
96		"map_string_bytes":      map[string][]byte{"70.1.key": []byte("70.1.val"), "70.2.key": []byte("70.2.val")},
97		"map_string_nested_message": map[string]protobuild.Message{
98			"71.1.key": {"a": 1171},
99			"71.2.key": {"a": 2171},
100		},
101		"map_string_nested_enum": map[string]string{"73.1.key": "FOO", "73.2.key": "BAR"},
102	},
103	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
104}, {
105	desc: "clone oneof uint32",
106	src: protobuild.Message{
107		"oneof_uint32": 1111,
108	},
109	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
110}, {
111	desc: "clone oneof string",
112	src: protobuild.Message{
113		"oneof_string": "string",
114	},
115	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
116}, {
117	desc: "clone oneof bytes",
118	src: protobuild.Message{
119		"oneof_bytes": "bytes",
120	},
121	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
122}, {
123	desc: "clone oneof bool",
124	src: protobuild.Message{
125		"oneof_bool": true,
126	},
127	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
128}, {
129	desc: "clone oneof uint64",
130	src: protobuild.Message{
131		"oneof_uint64": 100,
132	},
133	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
134}, {
135	desc: "clone oneof float",
136	src: protobuild.Message{
137		"oneof_float": 100,
138	},
139	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
140}, {
141	desc: "clone oneof double",
142	src: protobuild.Message{
143		"oneof_double": 1111,
144	},
145	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
146}, {
147	desc: "clone oneof enum",
148	src: protobuild.Message{
149		"oneof_enum": 1,
150	},
151	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
152}, {
153	desc: "clone oneof message",
154	src: protobuild.Message{
155		"oneof_nested_message": protobuild.Message{
156			"a": 1,
157		},
158	},
159	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
160}, {
161	desc: "clone oneof group",
162	src: protobuild.Message{
163		"oneofgroup": protobuild.Message{
164			"a": 1,
165		},
166	},
167	types: []proto.Message{&testpb.TestAllTypes{}},
168}, {
169	desc: "merge bytes",
170	dst: protobuild.Message{
171		"optional_bytes":   []byte{1, 2, 3},
172		"repeated_bytes":   [][]byte{{1, 2}, {3, 4}},
173		"map_string_bytes": map[string][]byte{"alpha": {1, 2, 3}},
174	},
175	src: protobuild.Message{
176		"optional_bytes":   []byte{4, 5, 6},
177		"repeated_bytes":   [][]byte{{5, 6}, {7, 8}},
178		"map_string_bytes": map[string][]byte{"alpha": {4, 5, 6}, "bravo": {1, 2, 3}},
179	},
180	want: protobuild.Message{
181		"optional_bytes":   []byte{4, 5, 6},
182		"repeated_bytes":   [][]byte{{1, 2}, {3, 4}, {5, 6}, {7, 8}},
183		"map_string_bytes": map[string][]byte{"alpha": {4, 5, 6}, "bravo": {1, 2, 3}},
184	},
185	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
186}, {
187	desc: "merge singular fields",
188	dst: protobuild.Message{
189		"optional_int32":       1,
190		"optional_int64":       1,
191		"optional_uint32":      1,
192		"optional_uint64":      1,
193		"optional_sint32":      1,
194		"optional_sint64":      1,
195		"optional_fixed32":     1,
196		"optional_fixed64":     1,
197		"optional_sfixed32":    1,
198		"optional_sfixed64":    1,
199		"optional_float":       1,
200		"optional_double":      1,
201		"optional_bool":        false,
202		"optional_string":      "1",
203		"optional_bytes":       "1",
204		"optional_nested_enum": 1,
205		"optional_nested_message": protobuild.Message{
206			"a": 1,
207			"corecursive": protobuild.Message{
208				"optional_int64": 1,
209			},
210		},
211	},
212	src: protobuild.Message{
213		"optional_int32":       2,
214		"optional_int64":       2,
215		"optional_uint32":      2,
216		"optional_uint64":      2,
217		"optional_sint32":      2,
218		"optional_sint64":      2,
219		"optional_fixed32":     2,
220		"optional_fixed64":     2,
221		"optional_sfixed32":    2,
222		"optional_sfixed64":    2,
223		"optional_float":       2,
224		"optional_double":      2,
225		"optional_bool":        true,
226		"optional_string":      "2",
227		"optional_bytes":       "2",
228		"optional_nested_enum": 2,
229		"optional_nested_message": protobuild.Message{
230			"a": 2,
231			"corecursive": protobuild.Message{
232				"optional_int64": 2,
233			},
234		},
235	},
236	want: protobuild.Message{
237		"optional_int32":       2,
238		"optional_int64":       2,
239		"optional_uint32":      2,
240		"optional_uint64":      2,
241		"optional_sint32":      2,
242		"optional_sint64":      2,
243		"optional_fixed32":     2,
244		"optional_fixed64":     2,
245		"optional_sfixed32":    2,
246		"optional_sfixed64":    2,
247		"optional_float":       2,
248		"optional_double":      2,
249		"optional_bool":        true,
250		"optional_string":      "2",
251		"optional_bytes":       "2",
252		"optional_nested_enum": 2,
253		"optional_nested_message": protobuild.Message{
254			"a": 2,
255			"corecursive": protobuild.Message{
256				"optional_int64": 2,
257			},
258		},
259	},
260}, {
261	desc: "no merge of empty singular fields",
262	dst: protobuild.Message{
263		"optional_int32":       1,
264		"optional_int64":       1,
265		"optional_uint32":      1,
266		"optional_uint64":      1,
267		"optional_sint32":      1,
268		"optional_sint64":      1,
269		"optional_fixed32":     1,
270		"optional_fixed64":     1,
271		"optional_sfixed32":    1,
272		"optional_sfixed64":    1,
273		"optional_float":       1,
274		"optional_double":      1,
275		"optional_bool":        false,
276		"optional_string":      "1",
277		"optional_bytes":       "1",
278		"optional_nested_enum": 1,
279		"optional_nested_message": protobuild.Message{
280			"a": 1,
281			"corecursive": protobuild.Message{
282				"optional_int64": 1,
283			},
284		},
285	},
286	src: protobuild.Message{
287		"optional_nested_message": protobuild.Message{
288			"a": 1,
289			"corecursive": protobuild.Message{
290				"optional_int32": 2,
291			},
292		},
293	},
294	want: protobuild.Message{
295		"optional_int32":       1,
296		"optional_int64":       1,
297		"optional_uint32":      1,
298		"optional_uint64":      1,
299		"optional_sint32":      1,
300		"optional_sint64":      1,
301		"optional_fixed32":     1,
302		"optional_fixed64":     1,
303		"optional_sfixed32":    1,
304		"optional_sfixed64":    1,
305		"optional_float":       1,
306		"optional_double":      1,
307		"optional_bool":        false,
308		"optional_string":      "1",
309		"optional_bytes":       "1",
310		"optional_nested_enum": 1,
311		"optional_nested_message": protobuild.Message{
312			"a": 1,
313			"corecursive": protobuild.Message{
314				"optional_int32": 2,
315				"optional_int64": 1,
316			},
317		},
318	},
319}, {
320	desc: "merge list fields",
321	dst: protobuild.Message{
322		"repeated_int32":       []int32{1, 2, 3},
323		"repeated_int64":       []int64{1, 2, 3},
324		"repeated_uint32":      []uint32{1, 2, 3},
325		"repeated_uint64":      []uint64{1, 2, 3},
326		"repeated_sint32":      []int32{1, 2, 3},
327		"repeated_sint64":      []int64{1, 2, 3},
328		"repeated_fixed32":     []uint32{1, 2, 3},
329		"repeated_fixed64":     []uint64{1, 2, 3},
330		"repeated_sfixed32":    []int32{1, 2, 3},
331		"repeated_sfixed64":    []int64{1, 2, 3},
332		"repeated_float":       []float32{1, 2, 3},
333		"repeated_double":      []float64{1, 2, 3},
334		"repeated_bool":        []bool{true},
335		"repeated_string":      []string{"a", "b", "c"},
336		"repeated_bytes":       []string{"a", "b", "c"},
337		"repeated_nested_enum": []int{1, 2, 3},
338		"repeated_nested_message": []protobuild.Message{
339			{"a": 100},
340			{"a": 200},
341		},
342	},
343	src: protobuild.Message{
344		"repeated_int32":       []int32{4, 5, 6},
345		"repeated_int64":       []int64{4, 5, 6},
346		"repeated_uint32":      []uint32{4, 5, 6},
347		"repeated_uint64":      []uint64{4, 5, 6},
348		"repeated_sint32":      []int32{4, 5, 6},
349		"repeated_sint64":      []int64{4, 5, 6},
350		"repeated_fixed32":     []uint32{4, 5, 6},
351		"repeated_fixed64":     []uint64{4, 5, 6},
352		"repeated_sfixed32":    []int32{4, 5, 6},
353		"repeated_sfixed64":    []int64{4, 5, 6},
354		"repeated_float":       []float32{4, 5, 6},
355		"repeated_double":      []float64{4, 5, 6},
356		"repeated_bool":        []bool{false},
357		"repeated_string":      []string{"d", "e", "f"},
358		"repeated_bytes":       []string{"d", "e", "f"},
359		"repeated_nested_enum": []int{4, 5, 6},
360		"repeated_nested_message": []protobuild.Message{
361			{"a": 300},
362			{"a": 400},
363		},
364	},
365	want: protobuild.Message{
366		"repeated_int32":       []int32{1, 2, 3, 4, 5, 6},
367		"repeated_int64":       []int64{1, 2, 3, 4, 5, 6},
368		"repeated_uint32":      []uint32{1, 2, 3, 4, 5, 6},
369		"repeated_uint64":      []uint64{1, 2, 3, 4, 5, 6},
370		"repeated_sint32":      []int32{1, 2, 3, 4, 5, 6},
371		"repeated_sint64":      []int64{1, 2, 3, 4, 5, 6},
372		"repeated_fixed32":     []uint32{1, 2, 3, 4, 5, 6},
373		"repeated_fixed64":     []uint64{1, 2, 3, 4, 5, 6},
374		"repeated_sfixed32":    []int32{1, 2, 3, 4, 5, 6},
375		"repeated_sfixed64":    []int64{1, 2, 3, 4, 5, 6},
376		"repeated_float":       []float32{1, 2, 3, 4, 5, 6},
377		"repeated_double":      []float64{1, 2, 3, 4, 5, 6},
378		"repeated_bool":        []bool{true, false},
379		"repeated_string":      []string{"a", "b", "c", "d", "e", "f"},
380		"repeated_bytes":       []string{"a", "b", "c", "d", "e", "f"},
381		"repeated_nested_enum": []int{1, 2, 3, 4, 5, 6},
382		"repeated_nested_message": []protobuild.Message{
383			{"a": 100},
384			{"a": 200},
385			{"a": 300},
386			{"a": 400},
387		},
388	},
389}, {
390	desc: "merge map fields",
391	dst: protobuild.Message{
392		"map_int32_int32":       map[int]int{1: 1, 3: 1},
393		"map_int64_int64":       map[int]int{1: 1, 3: 1},
394		"map_uint32_uint32":     map[int]int{1: 1, 3: 1},
395		"map_uint64_uint64":     map[int]int{1: 1, 3: 1},
396		"map_sint32_sint32":     map[int]int{1: 1, 3: 1},
397		"map_sint64_sint64":     map[int]int{1: 1, 3: 1},
398		"map_fixed32_fixed32":   map[int]int{1: 1, 3: 1},
399		"map_fixed64_fixed64":   map[int]int{1: 1, 3: 1},
400		"map_sfixed32_sfixed32": map[int]int{1: 1, 3: 1},
401		"map_sfixed64_sfixed64": map[int]int{1: 1, 3: 1},
402		"map_int32_float":       map[int]int{1: 1, 3: 1},
403		"map_int32_double":      map[int]int{1: 1, 3: 1},
404		"map_bool_bool":         map[bool]bool{true: true},
405		"map_string_string":     map[string]string{"a": "1", "ab": "1"},
406		"map_string_bytes":      map[string]string{"a": "1", "ab": "1"},
407		"map_string_nested_message": map[string]protobuild.Message{
408			"a": {"a": 1},
409			"ab": {
410				"a": 1,
411				"corecursive": protobuild.Message{
412					"map_int32_int32": map[int]int{1: 1, 3: 1},
413				},
414			},
415		},
416		"map_string_nested_enum": map[string]int{"a": 1, "ab": 1},
417	},
418	src: protobuild.Message{
419		"map_int32_int32":       map[int]int{2: 2, 3: 2},
420		"map_int64_int64":       map[int]int{2: 2, 3: 2},
421		"map_uint32_uint32":     map[int]int{2: 2, 3: 2},
422		"map_uint64_uint64":     map[int]int{2: 2, 3: 2},
423		"map_sint32_sint32":     map[int]int{2: 2, 3: 2},
424		"map_sint64_sint64":     map[int]int{2: 2, 3: 2},
425		"map_fixed32_fixed32":   map[int]int{2: 2, 3: 2},
426		"map_fixed64_fixed64":   map[int]int{2: 2, 3: 2},
427		"map_sfixed32_sfixed32": map[int]int{2: 2, 3: 2},
428		"map_sfixed64_sfixed64": map[int]int{2: 2, 3: 2},
429		"map_int32_float":       map[int]int{2: 2, 3: 2},
430		"map_int32_double":      map[int]int{2: 2, 3: 2},
431		"map_bool_bool":         map[bool]bool{false: false},
432		"map_string_string":     map[string]string{"b": "2", "ab": "2"},
433		"map_string_bytes":      map[string]string{"b": "2", "ab": "2"},
434		"map_string_nested_message": map[string]protobuild.Message{
435			"b": {"a": 2},
436			"ab": {
437				"a": 2,
438				"corecursive": protobuild.Message{
439					"map_int32_int32": map[int]int{2: 2, 3: 2},
440				},
441			},
442		},
443		"map_string_nested_enum": map[string]int{"b": 2, "ab": 2},
444	},
445	want: protobuild.Message{
446		"map_int32_int32":       map[int]int{1: 1, 2: 2, 3: 2},
447		"map_int64_int64":       map[int]int{1: 1, 2: 2, 3: 2},
448		"map_uint32_uint32":     map[int]int{1: 1, 2: 2, 3: 2},
449		"map_uint64_uint64":     map[int]int{1: 1, 2: 2, 3: 2},
450		"map_sint32_sint32":     map[int]int{1: 1, 2: 2, 3: 2},
451		"map_sint64_sint64":     map[int]int{1: 1, 2: 2, 3: 2},
452		"map_fixed32_fixed32":   map[int]int{1: 1, 2: 2, 3: 2},
453		"map_fixed64_fixed64":   map[int]int{1: 1, 2: 2, 3: 2},
454		"map_sfixed32_sfixed32": map[int]int{1: 1, 2: 2, 3: 2},
455		"map_sfixed64_sfixed64": map[int]int{1: 1, 2: 2, 3: 2},
456		"map_int32_float":       map[int]int{1: 1, 2: 2, 3: 2},
457		"map_int32_double":      map[int]int{1: 1, 2: 2, 3: 2},
458		"map_bool_bool":         map[bool]bool{true: true, false: false},
459		"map_string_string":     map[string]string{"a": "1", "b": "2", "ab": "2"},
460		"map_string_bytes":      map[string]string{"a": "1", "b": "2", "ab": "2"},
461		"map_string_nested_message": map[string]protobuild.Message{
462			"a": {"a": 1},
463			"b": {"a": 2},
464			"ab": {
465				"a": 2,
466				"corecursive": protobuild.Message{
467					// The map item "ab" was entirely replaced, so
468					// this does not contain 1:1 from dst.
469					"map_int32_int32": map[int]int{2: 2, 3: 2},
470				},
471			},
472		},
473		"map_string_nested_enum": map[string]int{"a": 1, "b": 2, "ab": 2},
474	},
475	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
476}, {
477	desc: "merge oneof message fields",
478	dst: protobuild.Message{
479		"oneof_nested_message": protobuild.Message{
480			"a": 100,
481		},
482	},
483	src: protobuild.Message{
484		"oneof_nested_message": protobuild.Message{
485			"corecursive": protobuild.Message{
486				"optional_int64": 1000,
487			},
488		},
489	},
490	want: protobuild.Message{
491		"oneof_nested_message": protobuild.Message{
492			"a": 100,
493			"corecursive": protobuild.Message{
494				"optional_int64": 1000,
495			},
496		},
497	},
498	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
499}, {
500	desc: "merge oneof scalar fields",
501	dst: protobuild.Message{
502		"oneof_uint32": 100,
503	},
504	src: protobuild.Message{
505		"oneof_float": 3.14152,
506	},
507	want: protobuild.Message{
508		"oneof_float": 3.14152,
509	},
510	types: []proto.Message{&testpb.TestAllTypes{}, &test3pb.TestAllTypes{}},
511}, {
512	desc: "merge unknown fields",
513	dst: protobuild.Message{
514		protobuild.Unknown: protopack.Message{
515			protopack.Tag{Number: 50000, Type: protopack.VarintType}, protopack.Svarint(-5),
516		}.Marshal(),
517	},
518	src: protobuild.Message{
519		protobuild.Unknown: protopack.Message{
520			protopack.Tag{Number: 500000, Type: protopack.VarintType}, protopack.Svarint(-50),
521		}.Marshal(),
522	},
523	want: protobuild.Message{
524		protobuild.Unknown: protopack.Message{
525			protopack.Tag{Number: 50000, Type: protopack.VarintType}, protopack.Svarint(-5),
526			protopack.Tag{Number: 500000, Type: protopack.VarintType}, protopack.Svarint(-50),
527		}.Marshal(),
528	},
529}, {
530	desc: "clone legacy message",
531	src: protobuild.Message{"f1": protobuild.Message{
532		"optional_int32":        1,
533		"optional_int64":        1,
534		"optional_uint32":       1,
535		"optional_uint64":       1,
536		"optional_sint32":       1,
537		"optional_sint64":       1,
538		"optional_fixed32":      1,
539		"optional_fixed64":      1,
540		"optional_sfixed32":     1,
541		"optional_sfixed64":     1,
542		"optional_float":        1,
543		"optional_double":       1,
544		"optional_bool":         true,
545		"optional_string":       "string",
546		"optional_bytes":        "bytes",
547		"optional_sibling_enum": 1,
548		"optional_sibling_message": protobuild.Message{
549			"f1": "value",
550		},
551		"repeated_int32":        []int32{1},
552		"repeated_int64":        []int64{1},
553		"repeated_uint32":       []uint32{1},
554		"repeated_uint64":       []uint64{1},
555		"repeated_sint32":       []int32{1},
556		"repeated_sint64":       []int64{1},
557		"repeated_fixed32":      []uint32{1},
558		"repeated_fixed64":      []uint64{1},
559		"repeated_sfixed32":     []int32{1},
560		"repeated_sfixed64":     []int64{1},
561		"repeated_float":        []float32{1},
562		"repeated_double":       []float64{1},
563		"repeated_bool":         []bool{true},
564		"repeated_string":       []string{"string"},
565		"repeated_bytes":        []string{"bytes"},
566		"repeated_sibling_enum": []int{1},
567		"repeated_sibling_message": []protobuild.Message{
568			{"f1": "1"},
569		},
570		"map_bool_int32":    map[bool]int{true: 1},
571		"map_bool_int64":    map[bool]int{true: 1},
572		"map_bool_uint32":   map[bool]int{true: 1},
573		"map_bool_uint64":   map[bool]int{true: 1},
574		"map_bool_sint32":   map[bool]int{true: 1},
575		"map_bool_sint64":   map[bool]int{true: 1},
576		"map_bool_fixed32":  map[bool]int{true: 1},
577		"map_bool_fixed64":  map[bool]int{true: 1},
578		"map_bool_sfixed32": map[bool]int{true: 1},
579		"map_bool_sfixed64": map[bool]int{true: 1},
580		"map_bool_float":    map[bool]int{true: 1},
581		"map_bool_double":   map[bool]int{true: 1},
582		"map_bool_bool":     map[bool]bool{true: false},
583		"map_bool_string":   map[bool]string{true: "1"},
584		"map_bool_bytes":    map[bool]string{true: "1"},
585		"map_bool_sibling_message": map[bool]protobuild.Message{
586			true: {"f1": "1"},
587		},
588		"map_bool_sibling_enum": map[bool]int{true: 1},
589		"oneof_sibling_message": protobuild.Message{
590			"f1": "1",
591		},
592	}},
593	types: []proto.Message{&legacypb.Legacy{}},
594}}
595
596func TestMerge(t *testing.T) {
597	for _, tt := range testMerges {
598		for _, mt := range templateMessages(tt.types...) {
599			t.Run(fmt.Sprintf("%s (%v)", tt.desc, mt.Descriptor().FullName()), func(t *testing.T) {
600				dst := mt.New().Interface()
601				tt.dst.Build(dst.ProtoReflect())
602
603				src := mt.New().Interface()
604				tt.src.Build(src.ProtoReflect())
605
606				want := mt.New().Interface()
607				if tt.dst == nil && tt.want == nil {
608					tt.src.Build(want.ProtoReflect())
609				} else {
610					tt.want.Build(want.ProtoReflect())
611				}
612
613				// Merge should be semantically equivalent to unmarshaling the
614				// encoded form of src into the current dst.
615				b1, err := proto.MarshalOptions{AllowPartial: true}.Marshal(dst)
616				if err != nil {
617					t.Fatalf("Marshal(dst) error: %v", err)
618				}
619				b2, err := proto.MarshalOptions{AllowPartial: true}.Marshal(src)
620				if err != nil {
621					t.Fatalf("Marshal(src) error: %v", err)
622				}
623				unmarshaled := dst.ProtoReflect().New().Interface()
624				err = proto.UnmarshalOptions{AllowPartial: true}.Unmarshal(append(b1, b2...), unmarshaled)
625				if err != nil {
626					t.Fatalf("Unmarshal() error: %v", err)
627				}
628				if !proto.Equal(unmarshaled, want) {
629					t.Fatalf("Unmarshal(Marshal(dst)+Marshal(src)) mismatch:\n got %v\nwant %v\ndiff (-want,+got):\n%v", unmarshaled, want, cmp.Diff(want, unmarshaled, protocmp.Transform()))
630				}
631
632				// Test heterogeneous MessageTypes by merging into a
633				// dynamic message.
634				ddst := dynamicpb.NewMessage(mt.Descriptor())
635				tt.dst.Build(ddst.ProtoReflect())
636				proto.Merge(ddst, src)
637				if !proto.Equal(ddst, want) {
638					t.Fatalf("Merge() into dynamic message mismatch:\n got %v\nwant %v\ndiff (-want,+got):\n%v", ddst, want, cmp.Diff(want, ddst, protocmp.Transform()))
639				}
640
641				proto.Merge(dst, src)
642				if !proto.Equal(dst, want) {
643					t.Fatalf("Merge() mismatch:\n got %v\nwant %v\ndiff (-want,+got):\n%v", dst, want, cmp.Diff(want, dst, protocmp.Transform()))
644				}
645				mutateValue(protoreflect.ValueOfMessage(src.ProtoReflect()))
646				if !proto.Equal(dst, want) {
647					t.Fatalf("mutation observed after modifying source:\n got %v\nwant %v\ndiff (-want,+got):\n%v", dst, want, cmp.Diff(want, dst, protocmp.Transform()))
648				}
649			})
650		}
651	}
652}
653
654func TestMergeFromNil(t *testing.T) {
655	dst := &testpb.TestAllTypes{}
656	proto.Merge(dst, (*testpb.TestAllTypes)(nil))
657	if !proto.Equal(dst, &testpb.TestAllTypes{}) {
658		t.Errorf("destination should be empty after merging from nil message; got:\n%v", prototext.Format(dst))
659	}
660}
661
662// TestMergeAberrant tests inputs that are beyond the protobuf data model.
663// Just because there is a test for the current behavior does not mean that
664// this will behave the same way in the future.
665func TestMergeAberrant(t *testing.T) {
666	tests := []struct {
667		label string
668		dst   proto.Message
669		src   proto.Message
670		check func(proto.Message) bool
671	}{{
672		label: "Proto2EmptyBytes",
673		dst:   &testpb.TestAllTypes{OptionalBytes: nil},
674		src:   &testpb.TestAllTypes{OptionalBytes: []byte{}},
675		check: func(m proto.Message) bool {
676			return m.(*testpb.TestAllTypes).OptionalBytes != nil
677		},
678	}, {
679		label: "Proto3EmptyBytes",
680		dst:   &test3pb.TestAllTypes{SingularBytes: nil},
681		src:   &test3pb.TestAllTypes{SingularBytes: []byte{}},
682		check: func(m proto.Message) bool {
683			return m.(*test3pb.TestAllTypes).SingularBytes == nil
684		},
685	}, {
686		label: "EmptyList",
687		dst:   &testpb.TestAllTypes{RepeatedInt32: nil},
688		src:   &testpb.TestAllTypes{RepeatedInt32: []int32{}},
689		check: func(m proto.Message) bool {
690			return m.(*testpb.TestAllTypes).RepeatedInt32 == nil
691		},
692	}, {
693		label: "ListWithNilBytes",
694		dst:   &testpb.TestAllTypes{RepeatedBytes: nil},
695		src:   &testpb.TestAllTypes{RepeatedBytes: [][]byte{nil}},
696		check: func(m proto.Message) bool {
697			return reflect.DeepEqual(m.(*testpb.TestAllTypes).RepeatedBytes, [][]byte{{}})
698		},
699	}, {
700		label: "ListWithEmptyBytes",
701		dst:   &testpb.TestAllTypes{RepeatedBytes: nil},
702		src:   &testpb.TestAllTypes{RepeatedBytes: [][]byte{{}}},
703		check: func(m proto.Message) bool {
704			return reflect.DeepEqual(m.(*testpb.TestAllTypes).RepeatedBytes, [][]byte{{}})
705		},
706	}, {
707		label: "ListWithNilMessage",
708		dst:   &testpb.TestAllTypes{RepeatedNestedMessage: nil},
709		src:   &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{nil}},
710		check: func(m proto.Message) bool {
711			return m.(*testpb.TestAllTypes).RepeatedNestedMessage[0] != nil
712		},
713	}, {
714		label: "EmptyMap",
715		dst:   &testpb.TestAllTypes{MapStringString: nil},
716		src:   &testpb.TestAllTypes{MapStringString: map[string]string{}},
717		check: func(m proto.Message) bool {
718			return m.(*testpb.TestAllTypes).MapStringString == nil
719		},
720	}, {
721		label: "MapWithNilBytes",
722		dst:   &testpb.TestAllTypes{MapStringBytes: nil},
723		src:   &testpb.TestAllTypes{MapStringBytes: map[string][]byte{"k": nil}},
724		check: func(m proto.Message) bool {
725			return reflect.DeepEqual(m.(*testpb.TestAllTypes).MapStringBytes, map[string][]byte{"k": {}})
726		},
727	}, {
728		label: "MapWithEmptyBytes",
729		dst:   &testpb.TestAllTypes{MapStringBytes: nil},
730		src:   &testpb.TestAllTypes{MapStringBytes: map[string][]byte{"k": {}}},
731		check: func(m proto.Message) bool {
732			return reflect.DeepEqual(m.(*testpb.TestAllTypes).MapStringBytes, map[string][]byte{"k": {}})
733		},
734	}, {
735		label: "MapWithNilMessage",
736		dst:   &testpb.TestAllTypes{MapStringNestedMessage: nil},
737		src:   &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": nil}},
738		check: func(m proto.Message) bool {
739			return m.(*testpb.TestAllTypes).MapStringNestedMessage["k"] != nil
740		},
741	}, {
742		label: "OneofWithTypedNilWrapper",
743		dst:   &testpb.TestAllTypes{OneofField: nil},
744		src:   &testpb.TestAllTypes{OneofField: (*testpb.TestAllTypes_OneofNestedMessage)(nil)},
745		check: func(m proto.Message) bool {
746			return m.(*testpb.TestAllTypes).OneofField == nil
747		},
748	}, {
749		label: "OneofWithNilMessage",
750		dst:   &testpb.TestAllTypes{OneofField: nil},
751		src:   &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofNestedMessage{OneofNestedMessage: nil}},
752		check: func(m proto.Message) bool {
753			return m.(*testpb.TestAllTypes).OneofField.(*testpb.TestAllTypes_OneofNestedMessage).OneofNestedMessage != nil
754		},
755		// TODO: extension, nil message
756		// TODO: repeated extension, nil
757		// TODO: extension bytes
758		// TODO: repeated extension, nil message
759	}}
760
761	for _, tt := range tests {
762		t.Run(tt.label, func(t *testing.T) {
763			var pass bool
764			func() {
765				defer func() { recover() }()
766				proto.Merge(tt.dst, tt.src)
767				pass = tt.check(tt.dst)
768			}()
769			if !pass {
770				t.Error("check failed")
771			}
772		})
773	}
774}
775
776func TestMergeRace(t *testing.T) {
777	dst := new(testpb.TestAllTypes)
778	srcs := []*testpb.TestAllTypes{
779		{OptionalInt32: proto.Int32(1)},
780		{OptionalString: proto.String("hello")},
781		{RepeatedInt32: []int32{2, 3, 4}},
782		{RepeatedString: []string{"goodbye"}},
783		{MapStringString: map[string]string{"key": "value"}},
784		{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
785			A: proto.Int32(5),
786		}},
787		func() *testpb.TestAllTypes {
788			m := new(testpb.TestAllTypes)
789			m.ProtoReflect().SetUnknown(protopack.Message{
790				protopack.Tag{Number: 50000, Type: protopack.VarintType}, protopack.Svarint(-5),
791			}.Marshal())
792			return m
793		}(),
794	}
795
796	// It should be safe to concurrently merge non-overlapping fields.
797	var wg sync.WaitGroup
798	defer wg.Wait()
799	for _, src := range srcs {
800		wg.Add(1)
801		go func(src proto.Message) {
802			defer wg.Done()
803			proto.Merge(dst, src)
804		}(src)
805	}
806}
807
808func TestMergeSelf(t *testing.T) {
809	got := &testpb.TestAllTypes{
810		OptionalInt32:   proto.Int32(1),
811		OptionalString:  proto.String("hello"),
812		RepeatedInt32:   []int32{2, 3, 4},
813		RepeatedString:  []string{"goodbye"},
814		MapStringString: map[string]string{"key": "value"},
815		OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
816			A: proto.Int32(5),
817		},
818	}
819	got.ProtoReflect().SetUnknown(protopack.Message{
820		protopack.Tag{Number: 50000, Type: protopack.VarintType}, protopack.Svarint(-5),
821	}.Marshal())
822	proto.Merge(got, got)
823
824	// The main impact of merging to self is that repeated fields and
825	// unknown fields are doubled.
826	want := &testpb.TestAllTypes{
827		OptionalInt32:   proto.Int32(1),
828		OptionalString:  proto.String("hello"),
829		RepeatedInt32:   []int32{2, 3, 4, 2, 3, 4},
830		RepeatedString:  []string{"goodbye", "goodbye"},
831		MapStringString: map[string]string{"key": "value"},
832		OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
833			A: proto.Int32(5),
834		},
835	}
836	want.ProtoReflect().SetUnknown(protopack.Message{
837		protopack.Tag{Number: 50000, Type: protopack.VarintType}, protopack.Svarint(-5),
838		protopack.Tag{Number: 50000, Type: protopack.VarintType}, protopack.Svarint(-5),
839	}.Marshal())
840
841	if !proto.Equal(got, want) {
842		t.Errorf("Equal mismatch:\ngot  %v\nwant %v", got, want)
843	}
844}
845
846func TestClone(t *testing.T) {
847	want := &testpb.TestAllTypes{
848		OptionalInt32: proto.Int32(1),
849	}
850	got := proto.Clone(want).(*testpb.TestAllTypes)
851	if !proto.Equal(got, want) {
852		t.Errorf("Clone(src) != src:\n got %v\nwant %v", got, want)
853	}
854}
855
856// mutateValue changes a Value, returning a new value.
857//
858// For scalar values, it returns a value different from the input.
859// For Message, List, and Map values, it mutates the input and returns it.
860func mutateValue(v protoreflect.Value) protoreflect.Value {
861	switch v := v.Interface().(type) {
862	case bool:
863		return protoreflect.ValueOfBool(!v)
864	case protoreflect.EnumNumber:
865		return protoreflect.ValueOfEnum(v + 1)
866	case int32:
867		return protoreflect.ValueOfInt32(v + 1)
868	case int64:
869		return protoreflect.ValueOfInt64(v + 1)
870	case uint32:
871		return protoreflect.ValueOfUint32(v + 1)
872	case uint64:
873		return protoreflect.ValueOfUint64(v + 1)
874	case float32:
875		return protoreflect.ValueOfFloat32(v + 1)
876	case float64:
877		return protoreflect.ValueOfFloat64(v + 1)
878	case []byte:
879		for i := range v {
880			v[i]++
881		}
882		return protoreflect.ValueOfBytes(v)
883	case string:
884		return protoreflect.ValueOfString("_" + v)
885	case protoreflect.Message:
886		v.Range(func(fd protoreflect.FieldDescriptor, val protoreflect.Value) bool {
887			v.Set(fd, mutateValue(val))
888			return true
889		})
890		return protoreflect.ValueOfMessage(v)
891	case protoreflect.List:
892		for i := 0; i < v.Len(); i++ {
893			v.Set(i, mutateValue(v.Get(i)))
894		}
895		return protoreflect.ValueOfList(v)
896	case protoreflect.Map:
897		v.Range(func(mk protoreflect.MapKey, mv protoreflect.Value) bool {
898			v.Set(mk, mutateValue(mv))
899			return true
900		})
901		return protoreflect.ValueOfMap(v)
902	default:
903		panic(fmt.Sprintf("unknown value type %T", v))
904	}
905}
906