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