merge_test.go 30 KB

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