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