equal_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  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. "math"
  7. "testing"
  8. "google.golang.org/protobuf/encoding/prototext"
  9. "google.golang.org/protobuf/internal/pragma"
  10. "google.golang.org/protobuf/proto"
  11. "google.golang.org/protobuf/testing/protopack"
  12. testpb "google.golang.org/protobuf/internal/testprotos/test"
  13. test3pb "google.golang.org/protobuf/internal/testprotos/test3"
  14. )
  15. func TestEqual(t *testing.T) {
  16. identicalPtrPb := &testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "d"}}
  17. type incomparableMessage struct {
  18. *testpb.TestAllTypes
  19. pragma.DoNotCompare
  20. }
  21. tests := []struct {
  22. x, y proto.Message
  23. eq bool
  24. }{
  25. {
  26. x: nil,
  27. y: nil,
  28. eq: true,
  29. }, {
  30. x: (*testpb.TestAllTypes)(nil),
  31. y: nil,
  32. eq: false,
  33. }, {
  34. x: (*testpb.TestAllTypes)(nil),
  35. y: (*testpb.TestAllTypes)(nil),
  36. eq: true,
  37. }, {
  38. x: new(testpb.TestAllTypes),
  39. y: (*testpb.TestAllTypes)(nil),
  40. eq: false,
  41. }, {
  42. x: new(testpb.TestAllTypes),
  43. y: new(testpb.TestAllTypes),
  44. eq: true,
  45. }, {
  46. x: (*testpb.TestAllTypes)(nil),
  47. y: (*testpb.TestAllExtensions)(nil),
  48. eq: false,
  49. }, {
  50. x: (*testpb.TestAllTypes)(nil),
  51. y: new(testpb.TestAllExtensions),
  52. eq: false,
  53. }, {
  54. x: new(testpb.TestAllTypes),
  55. y: new(testpb.TestAllExtensions),
  56. eq: false,
  57. },
  58. // Identical input pointers
  59. {
  60. x: identicalPtrPb,
  61. y: identicalPtrPb,
  62. eq: true,
  63. },
  64. // Incomparable types. The top-level types are not actually directly
  65. // compared (which would panic), but rather the comparison happens on the
  66. // objects returned by ProtoReflect(). These tests are here just to ensure
  67. // that any short-circuit checks do not accidentally try to compare
  68. // incomparable top-level types.
  69. {
  70. x: incomparableMessage{TestAllTypes: identicalPtrPb},
  71. y: incomparableMessage{TestAllTypes: identicalPtrPb},
  72. eq: true,
  73. },
  74. {
  75. x: identicalPtrPb,
  76. y: incomparableMessage{TestAllTypes: identicalPtrPb},
  77. eq: true,
  78. },
  79. {
  80. x: identicalPtrPb,
  81. y: &incomparableMessage{TestAllTypes: identicalPtrPb},
  82. eq: true,
  83. },
  84. // Proto2 scalars.
  85. {
  86. x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)},
  87. y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
  88. }, {
  89. x: &testpb.TestAllTypes{OptionalInt64: proto.Int64(1)},
  90. y: &testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
  91. }, {
  92. x: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(1)},
  93. y: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
  94. }, {
  95. x: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(1)},
  96. y: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
  97. }, {
  98. x: &testpb.TestAllTypes{OptionalSint32: proto.Int32(1)},
  99. y: &testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
  100. }, {
  101. x: &testpb.TestAllTypes{OptionalSint64: proto.Int64(1)},
  102. y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
  103. }, {
  104. x: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(1)},
  105. y: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
  106. }, {
  107. x: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(1)},
  108. y: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
  109. }, {
  110. x: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(1)},
  111. y: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
  112. }, {
  113. x: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(1)},
  114. y: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
  115. }, {
  116. x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(1)},
  117. y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
  118. }, {
  119. x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(1)},
  120. y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
  121. }, {
  122. x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
  123. y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(0)},
  124. }, {
  125. x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
  126. y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(0)},
  127. }, {
  128. x: &testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
  129. y: &testpb.TestAllTypes{OptionalBool: proto.Bool(false)},
  130. }, {
  131. x: &testpb.TestAllTypes{OptionalString: proto.String("a")},
  132. y: &testpb.TestAllTypes{OptionalString: proto.String("b")},
  133. }, {
  134. x: &testpb.TestAllTypes{OptionalBytes: []byte("a")},
  135. y: &testpb.TestAllTypes{OptionalBytes: []byte("b")},
  136. }, {
  137. x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
  138. y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
  139. }, {
  140. x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
  141. y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
  142. eq: true,
  143. }, {
  144. x: &testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
  145. y: &testpb.TestAllTypes{OptionalInt64: proto.Int64(2)},
  146. eq: true,
  147. }, {
  148. x: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
  149. y: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(2)},
  150. eq: true,
  151. }, {
  152. x: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
  153. y: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(2)},
  154. eq: true,
  155. }, {
  156. x: &testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
  157. y: &testpb.TestAllTypes{OptionalSint32: proto.Int32(2)},
  158. eq: true,
  159. }, {
  160. x: &testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
  161. y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(2)},
  162. eq: true,
  163. }, {
  164. x: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
  165. y: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(2)},
  166. eq: true,
  167. }, {
  168. x: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
  169. y: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(2)},
  170. eq: true,
  171. }, {
  172. x: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
  173. y: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(2)},
  174. eq: true,
  175. }, {
  176. x: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
  177. y: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(2)},
  178. eq: true,
  179. }, {
  180. x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
  181. y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(2)},
  182. eq: true,
  183. }, {
  184. x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
  185. y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(2)},
  186. eq: true,
  187. }, {
  188. x: &testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
  189. y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(float32(math.NaN()))},
  190. eq: true,
  191. }, {
  192. x: &testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
  193. y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(float64(math.NaN()))},
  194. eq: true,
  195. }, {
  196. x: &testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
  197. y: &testpb.TestAllTypes{OptionalBool: proto.Bool(true)},
  198. eq: true,
  199. }, {
  200. x: &testpb.TestAllTypes{OptionalString: proto.String("abc")},
  201. y: &testpb.TestAllTypes{OptionalString: proto.String("abc")},
  202. eq: true,
  203. }, {
  204. x: &testpb.TestAllTypes{OptionalBytes: []byte("abc")},
  205. y: &testpb.TestAllTypes{OptionalBytes: []byte("abc")},
  206. eq: true,
  207. }, {
  208. x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
  209. y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
  210. eq: true,
  211. },
  212. // Proto2 presence.
  213. {
  214. x: &testpb.TestAllTypes{},
  215. y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(0)},
  216. }, {
  217. x: &testpb.TestAllTypes{},
  218. y: &testpb.TestAllTypes{OptionalInt64: proto.Int64(0)},
  219. }, {
  220. x: &testpb.TestAllTypes{},
  221. y: &testpb.TestAllTypes{OptionalUint32: proto.Uint32(0)},
  222. }, {
  223. x: &testpb.TestAllTypes{},
  224. y: &testpb.TestAllTypes{OptionalUint64: proto.Uint64(0)},
  225. }, {
  226. x: &testpb.TestAllTypes{},
  227. y: &testpb.TestAllTypes{OptionalSint32: proto.Int32(0)},
  228. }, {
  229. x: &testpb.TestAllTypes{},
  230. y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(0)},
  231. }, {
  232. x: &testpb.TestAllTypes{},
  233. y: &testpb.TestAllTypes{OptionalFixed32: proto.Uint32(0)},
  234. }, {
  235. x: &testpb.TestAllTypes{},
  236. y: &testpb.TestAllTypes{OptionalFixed64: proto.Uint64(0)},
  237. }, {
  238. x: &testpb.TestAllTypes{},
  239. y: &testpb.TestAllTypes{OptionalSfixed32: proto.Int32(0)},
  240. }, {
  241. x: &testpb.TestAllTypes{},
  242. y: &testpb.TestAllTypes{OptionalSfixed64: proto.Int64(0)},
  243. }, {
  244. x: &testpb.TestAllTypes{},
  245. y: &testpb.TestAllTypes{OptionalFloat: proto.Float32(0)},
  246. }, {
  247. x: &testpb.TestAllTypes{},
  248. y: &testpb.TestAllTypes{OptionalDouble: proto.Float64(0)},
  249. }, {
  250. x: &testpb.TestAllTypes{},
  251. y: &testpb.TestAllTypes{OptionalBool: proto.Bool(false)},
  252. }, {
  253. x: &testpb.TestAllTypes{},
  254. y: &testpb.TestAllTypes{OptionalString: proto.String("")},
  255. }, {
  256. x: &testpb.TestAllTypes{},
  257. y: &testpb.TestAllTypes{OptionalBytes: []byte{}},
  258. }, {
  259. x: &testpb.TestAllTypes{},
  260. y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
  261. },
  262. // Proto3 presence.
  263. {
  264. x: &test3pb.TestAllTypes{},
  265. y: &test3pb.TestAllTypes{OptionalInt32: proto.Int32(0)},
  266. }, {
  267. x: &test3pb.TestAllTypes{},
  268. y: &test3pb.TestAllTypes{OptionalInt64: proto.Int64(0)},
  269. }, {
  270. x: &test3pb.TestAllTypes{},
  271. y: &test3pb.TestAllTypes{OptionalUint32: proto.Uint32(0)},
  272. }, {
  273. x: &test3pb.TestAllTypes{},
  274. y: &test3pb.TestAllTypes{OptionalUint64: proto.Uint64(0)},
  275. }, {
  276. x: &test3pb.TestAllTypes{},
  277. y: &test3pb.TestAllTypes{OptionalSint32: proto.Int32(0)},
  278. }, {
  279. x: &test3pb.TestAllTypes{},
  280. y: &test3pb.TestAllTypes{OptionalSint64: proto.Int64(0)},
  281. }, {
  282. x: &test3pb.TestAllTypes{},
  283. y: &test3pb.TestAllTypes{OptionalFixed32: proto.Uint32(0)},
  284. }, {
  285. x: &test3pb.TestAllTypes{},
  286. y: &test3pb.TestAllTypes{OptionalFixed64: proto.Uint64(0)},
  287. }, {
  288. x: &test3pb.TestAllTypes{},
  289. y: &test3pb.TestAllTypes{OptionalSfixed32: proto.Int32(0)},
  290. }, {
  291. x: &test3pb.TestAllTypes{},
  292. y: &test3pb.TestAllTypes{OptionalSfixed64: proto.Int64(0)},
  293. }, {
  294. x: &test3pb.TestAllTypes{},
  295. y: &test3pb.TestAllTypes{OptionalFloat: proto.Float32(0)},
  296. }, {
  297. x: &test3pb.TestAllTypes{},
  298. y: &test3pb.TestAllTypes{OptionalDouble: proto.Float64(0)},
  299. }, {
  300. x: &test3pb.TestAllTypes{},
  301. y: &test3pb.TestAllTypes{OptionalBool: proto.Bool(false)},
  302. }, {
  303. x: &test3pb.TestAllTypes{},
  304. y: &test3pb.TestAllTypes{OptionalString: proto.String("")},
  305. }, {
  306. x: &test3pb.TestAllTypes{},
  307. y: &test3pb.TestAllTypes{OptionalBytes: []byte{}},
  308. }, {
  309. x: &test3pb.TestAllTypes{},
  310. y: &test3pb.TestAllTypes{OptionalNestedEnum: test3pb.TestAllTypes_FOO.Enum()},
  311. },
  312. // Proto2 default values are not considered by Equal, so the following are still unequal.
  313. {
  314. x: &testpb.TestAllTypes{DefaultInt32: proto.Int32(81)},
  315. y: &testpb.TestAllTypes{},
  316. }, {
  317. x: &testpb.TestAllTypes{},
  318. y: &testpb.TestAllTypes{DefaultInt32: proto.Int32(81)},
  319. }, {
  320. x: &testpb.TestAllTypes{},
  321. y: &testpb.TestAllTypes{DefaultInt64: proto.Int64(82)},
  322. }, {
  323. x: &testpb.TestAllTypes{},
  324. y: &testpb.TestAllTypes{DefaultUint32: proto.Uint32(83)},
  325. }, {
  326. x: &testpb.TestAllTypes{},
  327. y: &testpb.TestAllTypes{DefaultUint64: proto.Uint64(84)},
  328. }, {
  329. x: &testpb.TestAllTypes{},
  330. y: &testpb.TestAllTypes{DefaultSint32: proto.Int32(-85)},
  331. }, {
  332. x: &testpb.TestAllTypes{},
  333. y: &testpb.TestAllTypes{DefaultSint64: proto.Int64(86)},
  334. }, {
  335. x: &testpb.TestAllTypes{},
  336. y: &testpb.TestAllTypes{DefaultFixed32: proto.Uint32(87)},
  337. }, {
  338. x: &testpb.TestAllTypes{},
  339. y: &testpb.TestAllTypes{DefaultFixed64: proto.Uint64(88)},
  340. }, {
  341. x: &testpb.TestAllTypes{},
  342. y: &testpb.TestAllTypes{DefaultSfixed32: proto.Int32(89)},
  343. }, {
  344. x: &testpb.TestAllTypes{},
  345. y: &testpb.TestAllTypes{DefaultSfixed64: proto.Int64(-90)},
  346. }, {
  347. x: &testpb.TestAllTypes{},
  348. y: &testpb.TestAllTypes{DefaultFloat: proto.Float32(91.5)},
  349. }, {
  350. x: &testpb.TestAllTypes{},
  351. y: &testpb.TestAllTypes{DefaultDouble: proto.Float64(92e3)},
  352. }, {
  353. x: &testpb.TestAllTypes{},
  354. y: &testpb.TestAllTypes{DefaultBool: proto.Bool(true)},
  355. }, {
  356. x: &testpb.TestAllTypes{},
  357. y: &testpb.TestAllTypes{DefaultString: proto.String("hello")},
  358. }, {
  359. x: &testpb.TestAllTypes{},
  360. y: &testpb.TestAllTypes{DefaultBytes: []byte("world")},
  361. }, {
  362. x: &testpb.TestAllTypes{},
  363. y: &testpb.TestAllTypes{DefaultNestedEnum: testpb.TestAllTypes_BAR.Enum()},
  364. },
  365. // Groups.
  366. {
  367. x: &testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
  368. A: proto.Int32(1),
  369. }},
  370. y: &testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{
  371. A: proto.Int32(2),
  372. }},
  373. }, {
  374. x: &testpb.TestAllTypes{},
  375. y: &testpb.TestAllTypes{Optionalgroup: &testpb.TestAllTypes_OptionalGroup{}},
  376. },
  377. // Messages.
  378. {
  379. x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
  380. A: proto.Int32(1),
  381. }},
  382. y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
  383. A: proto.Int32(2),
  384. }},
  385. }, {
  386. x: &testpb.TestAllTypes{},
  387. y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{}},
  388. }, {
  389. x: &test3pb.TestAllTypes{},
  390. y: &test3pb.TestAllTypes{OptionalNestedMessage: &test3pb.TestAllTypes_NestedMessage{}},
  391. },
  392. // Lists.
  393. {
  394. x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}},
  395. y: &testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
  396. }, {
  397. x: &testpb.TestAllTypes{RepeatedInt32: []int32{1, 2}},
  398. y: &testpb.TestAllTypes{RepeatedInt32: []int32{1, 3}},
  399. }, {
  400. x: &testpb.TestAllTypes{RepeatedInt64: []int64{1, 2}},
  401. y: &testpb.TestAllTypes{RepeatedInt64: []int64{1, 3}},
  402. }, {
  403. x: &testpb.TestAllTypes{RepeatedUint32: []uint32{1, 2}},
  404. y: &testpb.TestAllTypes{RepeatedUint32: []uint32{1, 3}},
  405. }, {
  406. x: &testpb.TestAllTypes{RepeatedUint64: []uint64{1, 2}},
  407. y: &testpb.TestAllTypes{RepeatedUint64: []uint64{1, 3}},
  408. }, {
  409. x: &testpb.TestAllTypes{RepeatedSint32: []int32{1, 2}},
  410. y: &testpb.TestAllTypes{RepeatedSint32: []int32{1, 3}},
  411. }, {
  412. x: &testpb.TestAllTypes{RepeatedSint64: []int64{1, 2}},
  413. y: &testpb.TestAllTypes{RepeatedSint64: []int64{1, 3}},
  414. }, {
  415. x: &testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 2}},
  416. y: &testpb.TestAllTypes{RepeatedFixed32: []uint32{1, 3}},
  417. }, {
  418. x: &testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 2}},
  419. y: &testpb.TestAllTypes{RepeatedFixed64: []uint64{1, 3}},
  420. }, {
  421. x: &testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 2}},
  422. y: &testpb.TestAllTypes{RepeatedSfixed32: []int32{1, 3}},
  423. }, {
  424. x: &testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 2}},
  425. y: &testpb.TestAllTypes{RepeatedSfixed64: []int64{1, 3}},
  426. }, {
  427. x: &testpb.TestAllTypes{RepeatedFloat: []float32{1, 2}},
  428. y: &testpb.TestAllTypes{RepeatedFloat: []float32{1, 3}},
  429. }, {
  430. x: &testpb.TestAllTypes{RepeatedDouble: []float64{1, 2}},
  431. y: &testpb.TestAllTypes{RepeatedDouble: []float64{1, 3}},
  432. }, {
  433. x: &testpb.TestAllTypes{RepeatedBool: []bool{true, false}},
  434. y: &testpb.TestAllTypes{RepeatedBool: []bool{true, true}},
  435. }, {
  436. x: &testpb.TestAllTypes{RepeatedString: []string{"a", "b"}},
  437. y: &testpb.TestAllTypes{RepeatedString: []string{"a", "c"}},
  438. }, {
  439. x: &testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("b")}},
  440. y: &testpb.TestAllTypes{RepeatedBytes: [][]byte{[]byte("a"), []byte("c")}},
  441. }, {
  442. x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
  443. y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
  444. }, {
  445. x: &testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
  446. {A: proto.Int32(1)},
  447. {A: proto.Int32(2)},
  448. }},
  449. y: &testpb.TestAllTypes{Repeatedgroup: []*testpb.TestAllTypes_RepeatedGroup{
  450. {A: proto.Int32(1)},
  451. {A: proto.Int32(3)},
  452. }},
  453. }, {
  454. x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
  455. {A: proto.Int32(1)},
  456. {A: proto.Int32(2)},
  457. }},
  458. y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{
  459. {A: proto.Int32(1)},
  460. {A: proto.Int32(3)},
  461. }},
  462. },
  463. // Maps: various configurations.
  464. {
  465. x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
  466. y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{3: 4}},
  467. }, {
  468. x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
  469. y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
  470. }, {
  471. x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
  472. y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2}},
  473. },
  474. // Maps: various types.
  475. {
  476. x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 4}},
  477. y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 2, 3: 5}},
  478. }, {
  479. x: &testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 4}},
  480. y: &testpb.TestAllTypes{MapInt64Int64: map[int64]int64{1: 2, 3: 5}},
  481. }, {
  482. x: &testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 4}},
  483. y: &testpb.TestAllTypes{MapUint32Uint32: map[uint32]uint32{1: 2, 3: 5}},
  484. }, {
  485. x: &testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 4}},
  486. y: &testpb.TestAllTypes{MapUint64Uint64: map[uint64]uint64{1: 2, 3: 5}},
  487. }, {
  488. x: &testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 4}},
  489. y: &testpb.TestAllTypes{MapSint32Sint32: map[int32]int32{1: 2, 3: 5}},
  490. }, {
  491. x: &testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 4}},
  492. y: &testpb.TestAllTypes{MapSint64Sint64: map[int64]int64{1: 2, 3: 5}},
  493. }, {
  494. x: &testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 4}},
  495. y: &testpb.TestAllTypes{MapFixed32Fixed32: map[uint32]uint32{1: 2, 3: 5}},
  496. }, {
  497. x: &testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 4}},
  498. y: &testpb.TestAllTypes{MapFixed64Fixed64: map[uint64]uint64{1: 2, 3: 5}},
  499. }, {
  500. x: &testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 4}},
  501. y: &testpb.TestAllTypes{MapSfixed32Sfixed32: map[int32]int32{1: 2, 3: 5}},
  502. }, {
  503. x: &testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 4}},
  504. y: &testpb.TestAllTypes{MapSfixed64Sfixed64: map[int64]int64{1: 2, 3: 5}},
  505. }, {
  506. x: &testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 4}},
  507. y: &testpb.TestAllTypes{MapInt32Float: map[int32]float32{1: 2, 3: 5}},
  508. }, {
  509. x: &testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 4}},
  510. y: &testpb.TestAllTypes{MapInt32Double: map[int32]float64{1: 2, 3: 5}},
  511. }, {
  512. x: &testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: true}},
  513. y: &testpb.TestAllTypes{MapBoolBool: map[bool]bool{true: false, false: false}},
  514. }, {
  515. x: &testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "d"}},
  516. y: &testpb.TestAllTypes{MapStringString: map[string]string{"a": "b", "c": "e"}},
  517. }, {
  518. x: &testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("d")}},
  519. y: &testpb.TestAllTypes{MapStringBytes: map[string][]byte{"a": []byte("b"), "c": []byte("e")}},
  520. }, {
  521. x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
  522. "a": {A: proto.Int32(1)},
  523. "b": {A: proto.Int32(2)},
  524. }},
  525. y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{
  526. "a": {A: proto.Int32(1)},
  527. "b": {A: proto.Int32(3)},
  528. }},
  529. }, {
  530. x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
  531. "a": testpb.TestAllTypes_FOO,
  532. "b": testpb.TestAllTypes_BAR,
  533. }},
  534. y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{
  535. "a": testpb.TestAllTypes_FOO,
  536. "b": testpb.TestAllTypes_BAZ,
  537. }},
  538. },
  539. // Extensions.
  540. {
  541. x: build(&testpb.TestAllExtensions{},
  542. extend(testpb.E_OptionalInt32, int32(1)),
  543. ),
  544. y: build(&testpb.TestAllExtensions{},
  545. extend(testpb.E_OptionalInt32, int32(2)),
  546. ),
  547. }, {
  548. x: &testpb.TestAllExtensions{},
  549. y: build(&testpb.TestAllExtensions{},
  550. extend(testpb.E_OptionalInt32, int32(2)),
  551. ),
  552. },
  553. // Unknown fields.
  554. {
  555. x: build(&testpb.TestAllTypes{}, unknown(protopack.Message{
  556. protopack.Tag{100000, protopack.VarintType}, protopack.Varint(1),
  557. }.Marshal())),
  558. y: build(&testpb.TestAllTypes{}, unknown(protopack.Message{
  559. protopack.Tag{100000, protopack.VarintType}, protopack.Varint(2),
  560. }.Marshal())),
  561. }, {
  562. x: build(&testpb.TestAllTypes{}, unknown(protopack.Message{
  563. protopack.Tag{100000, protopack.VarintType}, protopack.Varint(1),
  564. }.Marshal())),
  565. y: &testpb.TestAllTypes{},
  566. },
  567. }
  568. for _, tt := range tests {
  569. if !tt.eq && !proto.Equal(tt.x, tt.x) {
  570. t.Errorf("Equal(x, x) = false, want true\n==== x ====\n%v", prototext.Format(tt.x))
  571. }
  572. if !tt.eq && !proto.Equal(tt.y, tt.y) {
  573. t.Errorf("Equal(y, y) = false, want true\n==== y ====\n%v", prototext.Format(tt.y))
  574. }
  575. if eq := proto.Equal(tt.x, tt.y); eq != tt.eq {
  576. t.Errorf("Equal(x, y) = %v, want %v\n==== x ====\n%v==== y ====\n%v", eq, tt.eq, prototext.Format(tt.x), prototext.Format(tt.y))
  577. }
  578. }
  579. }
  580. func BenchmarkEqualWithSmallEmpty(b *testing.B) {
  581. x := &testpb.ForeignMessage{}
  582. y := &testpb.ForeignMessage{}
  583. b.ResetTimer()
  584. for i := 0; i < b.N; i++ {
  585. proto.Equal(x, y)
  586. }
  587. }
  588. func BenchmarkEqualWithIdenticalPtrEmpty(b *testing.B) {
  589. x := &testpb.ForeignMessage{}
  590. b.ResetTimer()
  591. for i := 0; i < b.N; i++ {
  592. proto.Equal(x, x)
  593. }
  594. }
  595. func BenchmarkEqualWithLargeEmpty(b *testing.B) {
  596. x := &testpb.TestAllTypes{}
  597. y := &testpb.TestAllTypes{}
  598. b.ResetTimer()
  599. for i := 0; i < b.N; i++ {
  600. proto.Equal(x, y)
  601. }
  602. }
  603. func makeNested(depth int) *testpb.TestAllTypes {
  604. if depth <= 0 {
  605. return nil
  606. }
  607. return &testpb.TestAllTypes{
  608. OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{
  609. Corecursive: makeNested(depth - 1),
  610. },
  611. }
  612. }
  613. func BenchmarkEqualWithDeeplyNestedEqual(b *testing.B) {
  614. x := makeNested(20)
  615. y := makeNested(20)
  616. b.ResetTimer()
  617. for i := 0; i < b.N; i++ {
  618. proto.Equal(x, y)
  619. }
  620. }
  621. func BenchmarkEqualWithDeeplyNestedDifferent(b *testing.B) {
  622. x := makeNested(20)
  623. y := makeNested(21)
  624. b.ResetTimer()
  625. for i := 0; i < b.N; i++ {
  626. proto.Equal(x, y)
  627. }
  628. }
  629. func BenchmarkEqualWithDeeplyNestedIdenticalPtr(b *testing.B) {
  630. x := makeNested(20)
  631. b.ResetTimer()
  632. for i := 0; i < b.N; i++ {
  633. proto.Equal(x, x)
  634. }
  635. }