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