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 protocmp 6 7import ( 8 "math" 9 "math/rand" 10 "sort" 11 "testing" 12 13 "github.com/google/go-cmp/cmp" 14 15 "google.golang.org/protobuf/proto" 16 "google.golang.org/protobuf/reflect/protoreflect" 17 "google.golang.org/protobuf/testing/protopack" 18 "google.golang.org/protobuf/types/dynamicpb" 19 20 testpb "google.golang.org/protobuf/internal/testprotos/test" 21) 22 23func TestEqual(t *testing.T) { 24 type test struct { 25 x, y interface{} 26 opts cmp.Options 27 want bool 28 } 29 var tests []test 30 31 allTypesDesc := (*testpb.TestAllTypes)(nil).ProtoReflect().Descriptor() 32 33 // Test nil and empty messages of differing types. 34 tests = append(tests, []test{{ 35 x: (*testpb.TestAllTypes)(nil), 36 y: (*testpb.TestAllTypes)(nil), 37 opts: cmp.Options{Transform()}, 38 want: true, 39 }, { 40 x: (*testpb.TestAllTypes)(nil), 41 y: (*testpb.TestAllExtensions)(nil), 42 opts: cmp.Options{Transform()}, 43 want: false, 44 }, { 45 x: (*testpb.TestAllTypes)(nil), 46 y: new(testpb.TestAllTypes), 47 opts: cmp.Options{Transform()}, 48 want: false, 49 }, { 50 x: (*testpb.TestAllTypes)(nil), 51 y: dynamicpb.NewMessage(allTypesDesc), 52 opts: cmp.Options{Transform()}, 53 want: false, 54 }, { 55 x: (*testpb.TestAllTypes)(nil), 56 y: new(testpb.TestAllTypes), 57 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 58 want: true, 59 }, { 60 x: (*testpb.TestAllTypes)(nil), 61 y: dynamicpb.NewMessage(allTypesDesc), 62 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 63 want: true, 64 }, { 65 x: new(testpb.TestAllTypes), 66 y: new(testpb.TestAllTypes), 67 opts: cmp.Options{Transform()}, 68 want: true, 69 }, { 70 x: new(testpb.TestAllTypes), 71 y: dynamicpb.NewMessage(allTypesDesc), 72 opts: cmp.Options{Transform()}, 73 want: true, 74 }, { 75 x: new(testpb.TestAllTypes), 76 y: new(testpb.TestAllExtensions), 77 opts: cmp.Options{Transform()}, 78 want: false, 79 }, { 80 x: struct{ I interface{} }{(*testpb.TestAllTypes)(nil)}, 81 y: struct{ I interface{} }{(*testpb.TestAllTypes)(nil)}, 82 opts: cmp.Options{Transform()}, 83 want: true, 84 }, { 85 x: struct{ I interface{} }{(*testpb.TestAllTypes)(nil)}, 86 y: struct{ I interface{} }{new(testpb.TestAllTypes)}, 87 opts: cmp.Options{Transform()}, 88 want: false, 89 }, { 90 x: struct{ I interface{} }{(*testpb.TestAllTypes)(nil)}, 91 y: struct{ I interface{} }{dynamicpb.NewMessage(allTypesDesc)}, 92 opts: cmp.Options{Transform()}, 93 want: false, 94 }, { 95 x: struct{ I interface{} }{(*testpb.TestAllTypes)(nil)}, 96 y: struct{ I interface{} }{new(testpb.TestAllTypes)}, 97 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 98 want: true, 99 }, { 100 x: struct{ I interface{} }{(*testpb.TestAllTypes)(nil)}, 101 y: struct{ I interface{} }{dynamicpb.NewMessage(allTypesDesc)}, 102 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 103 want: true, 104 }, { 105 x: struct{ I interface{} }{new(testpb.TestAllTypes)}, 106 y: struct{ I interface{} }{new(testpb.TestAllTypes)}, 107 opts: cmp.Options{Transform()}, 108 want: true, 109 }, { 110 x: struct{ I interface{} }{new(testpb.TestAllTypes)}, 111 y: struct{ I interface{} }{dynamicpb.NewMessage(allTypesDesc)}, 112 opts: cmp.Options{Transform()}, 113 want: true, 114 }, { 115 x: struct{ M proto.Message }{(*testpb.TestAllTypes)(nil)}, 116 y: struct{ M proto.Message }{(*testpb.TestAllTypes)(nil)}, 117 opts: cmp.Options{Transform()}, 118 want: true, 119 }, { 120 x: struct{ M proto.Message }{(*testpb.TestAllTypes)(nil)}, 121 y: struct{ M proto.Message }{new(testpb.TestAllTypes)}, 122 opts: cmp.Options{Transform()}, 123 want: false, 124 }, { 125 x: struct{ M proto.Message }{(*testpb.TestAllTypes)(nil)}, 126 y: struct{ M proto.Message }{dynamicpb.NewMessage(allTypesDesc)}, 127 opts: cmp.Options{Transform()}, 128 want: false, 129 }, { 130 x: struct{ M proto.Message }{(*testpb.TestAllTypes)(nil)}, 131 y: struct{ M proto.Message }{new(testpb.TestAllTypes)}, 132 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 133 want: true, 134 }, { 135 x: struct{ M proto.Message }{(*testpb.TestAllTypes)(nil)}, 136 y: struct{ M proto.Message }{dynamicpb.NewMessage(allTypesDesc)}, 137 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 138 want: true, 139 }, { 140 x: struct{ M proto.Message }{new(testpb.TestAllTypes)}, 141 y: struct{ M proto.Message }{new(testpb.TestAllTypes)}, 142 opts: cmp.Options{Transform()}, 143 want: true, 144 }, { 145 x: struct{ M proto.Message }{new(testpb.TestAllTypes)}, 146 y: struct{ M proto.Message }{dynamicpb.NewMessage(allTypesDesc)}, 147 opts: cmp.Options{Transform()}, 148 want: true, 149 }}...) 150 151 // Test message values. 152 tests = append(tests, []test{{ 153 x: testpb.TestAllTypes{OptionalSint64: proto.Int64(1)}, 154 y: testpb.TestAllTypes{OptionalSint64: proto.Int64(1)}, 155 opts: cmp.Options{Transform()}, 156 want: true, 157 }, { 158 x: testpb.TestAllTypes{OptionalSint64: proto.Int64(1)}, 159 y: testpb.TestAllTypes{OptionalSint64: proto.Int64(2)}, 160 opts: cmp.Options{Transform()}, 161 want: false, 162 }, { 163 x: struct{ M testpb.TestAllTypes }{M: testpb.TestAllTypes{OptionalSint64: proto.Int64(1)}}, 164 y: struct{ M testpb.TestAllTypes }{M: testpb.TestAllTypes{OptionalSint64: proto.Int64(1)}}, 165 opts: cmp.Options{Transform()}, 166 want: true, 167 }, { 168 x: struct{ M testpb.TestAllTypes }{M: testpb.TestAllTypes{OptionalSint64: proto.Int64(1)}}, 169 y: struct{ M testpb.TestAllTypes }{M: testpb.TestAllTypes{OptionalSint64: proto.Int64(2)}}, 170 opts: cmp.Options{Transform()}, 171 want: false, 172 }, { 173 x: struct{ M []testpb.TestAllTypes }{M: []testpb.TestAllTypes{{OptionalSint64: proto.Int64(1)}}}, 174 y: struct{ M []testpb.TestAllTypes }{M: []testpb.TestAllTypes{{OptionalSint64: proto.Int64(1)}}}, 175 opts: cmp.Options{Transform()}, 176 want: true, 177 }, { 178 x: struct{ M []testpb.TestAllTypes }{M: []testpb.TestAllTypes{{OptionalSint64: proto.Int64(1)}}}, 179 y: struct{ M []testpb.TestAllTypes }{M: []testpb.TestAllTypes{{OptionalSint64: proto.Int64(2)}}}, 180 opts: cmp.Options{Transform()}, 181 want: false, 182 }, { 183 x: struct { 184 M map[string]testpb.TestAllTypes 185 }{ 186 M: map[string]testpb.TestAllTypes{"k": {OptionalSint64: proto.Int64(1)}}, 187 }, 188 y: struct { 189 M map[string]testpb.TestAllTypes 190 }{ 191 M: map[string]testpb.TestAllTypes{"k": {OptionalSint64: proto.Int64(1)}}, 192 }, 193 opts: cmp.Options{Transform()}, 194 want: true, 195 }, { 196 x: struct { 197 M map[string]testpb.TestAllTypes 198 }{ 199 M: map[string]testpb.TestAllTypes{"k": {OptionalSint64: proto.Int64(1)}}, 200 }, 201 y: struct { 202 M map[string]testpb.TestAllTypes 203 }{ 204 M: map[string]testpb.TestAllTypes{"k": {OptionalSint64: proto.Int64(2)}}, 205 }, 206 opts: cmp.Options{Transform()}, 207 want: false, 208 }}...) 209 210 // Test IgnoreUnknown. 211 raw := protopack.Message{ 212 protopack.Tag{1, protopack.BytesType}, protopack.String("Hello, goodbye!"), 213 }.Marshal() 214 tests = append(tests, []test{{ 215 x: apply(&testpb.TestAllTypes{OptionalSint64: proto.Int64(5)}, setUnknown{raw}), 216 y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(5)}, 217 opts: cmp.Options{Transform()}, 218 want: false, 219 }, { 220 x: apply(&testpb.TestAllTypes{OptionalSint64: proto.Int64(5)}, setUnknown{raw}), 221 y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(5)}, 222 opts: cmp.Options{Transform(), IgnoreUnknown()}, 223 want: true, 224 }, { 225 x: apply(&testpb.TestAllTypes{OptionalSint64: proto.Int64(5)}, setUnknown{raw}), 226 y: &testpb.TestAllTypes{OptionalSint64: proto.Int64(6)}, 227 opts: cmp.Options{Transform(), IgnoreUnknown()}, 228 want: false, 229 }, { 230 x: apply(&testpb.TestAllTypes{OptionalSint64: proto.Int64(5)}, setUnknown{raw}), 231 y: apply(dynamicpb.NewMessage(allTypesDesc), setField{6, int64(5)}), 232 opts: cmp.Options{Transform()}, 233 want: false, 234 }, { 235 x: apply(&testpb.TestAllTypes{OptionalSint64: proto.Int64(5)}, setUnknown{raw}), 236 y: apply(dynamicpb.NewMessage(allTypesDesc), setField{6, int64(5)}), 237 opts: cmp.Options{Transform(), IgnoreUnknown()}, 238 want: true, 239 }}...) 240 241 // Test IgnoreDefaultScalars. 242 tests = append(tests, []test{{ 243 x: &testpb.TestAllTypes{ 244 DefaultInt32: proto.Int32(81), 245 DefaultUint32: proto.Uint32(83), 246 DefaultFloat: proto.Float32(91.5), 247 DefaultBool: proto.Bool(true), 248 DefaultBytes: []byte("world"), 249 }, 250 y: &testpb.TestAllTypes{ 251 DefaultInt64: proto.Int64(82), 252 DefaultUint64: proto.Uint64(84), 253 DefaultDouble: proto.Float64(92e3), 254 DefaultString: proto.String("hello"), 255 DefaultForeignEnum: testpb.ForeignEnum_FOREIGN_BAR.Enum(), 256 }, 257 opts: cmp.Options{Transform()}, 258 want: false, 259 }, { 260 x: &testpb.TestAllTypes{ 261 DefaultInt32: proto.Int32(81), 262 DefaultUint32: proto.Uint32(83), 263 DefaultFloat: proto.Float32(91.5), 264 DefaultBool: proto.Bool(true), 265 DefaultBytes: []byte("world"), 266 }, 267 y: &testpb.TestAllTypes{ 268 DefaultInt64: proto.Int64(82), 269 DefaultUint64: proto.Uint64(84), 270 DefaultDouble: proto.Float64(92e3), 271 DefaultString: proto.String("hello"), 272 DefaultForeignEnum: testpb.ForeignEnum_FOREIGN_BAR.Enum(), 273 }, 274 opts: cmp.Options{Transform(), IgnoreDefaultScalars()}, 275 want: true, 276 }, { 277 x: &testpb.TestAllTypes{ 278 OptionalInt32: proto.Int32(81), 279 OptionalUint32: proto.Uint32(83), 280 OptionalFloat: proto.Float32(91.5), 281 OptionalBool: proto.Bool(true), 282 OptionalBytes: []byte("world"), 283 }, 284 y: &testpb.TestAllTypes{ 285 OptionalInt64: proto.Int64(82), 286 OptionalUint64: proto.Uint64(84), 287 OptionalDouble: proto.Float64(92e3), 288 OptionalString: proto.String("hello"), 289 OptionalForeignEnum: testpb.ForeignEnum_FOREIGN_BAR.Enum(), 290 }, 291 opts: cmp.Options{Transform(), IgnoreDefaultScalars()}, 292 want: false, 293 }, { 294 x: &testpb.TestAllTypes{ 295 OptionalInt32: proto.Int32(0), 296 OptionalUint32: proto.Uint32(0), 297 OptionalFloat: proto.Float32(0), 298 OptionalBool: proto.Bool(false), 299 OptionalBytes: []byte(""), 300 }, 301 y: &testpb.TestAllTypes{ 302 OptionalInt64: proto.Int64(0), 303 OptionalUint64: proto.Uint64(0), 304 OptionalDouble: proto.Float64(0), 305 OptionalString: proto.String(""), 306 OptionalForeignEnum: testpb.ForeignEnum_FOREIGN_FOO.Enum(), 307 }, 308 opts: cmp.Options{Transform(), IgnoreDefaultScalars()}, 309 want: true, 310 }, { 311 x: apply(new(testpb.TestAllExtensions), 312 setExtension{testpb.E_DefaultInt32, int32(81)}, 313 setExtension{testpb.E_DefaultUint32, uint32(83)}, 314 setExtension{testpb.E_DefaultFloat, float32(91.5)}, 315 setExtension{testpb.E_DefaultBool, bool(true)}, 316 setExtension{testpb.E_DefaultBytes, []byte("world")}), 317 y: apply(new(testpb.TestAllExtensions), 318 setExtension{testpb.E_DefaultInt64, int64(82)}, 319 setExtension{testpb.E_DefaultUint64, uint64(84)}, 320 setExtension{testpb.E_DefaultDouble, float64(92e3)}, 321 setExtension{testpb.E_DefaultString, string("hello")}), 322 opts: cmp.Options{Transform()}, 323 want: false, 324 }, { 325 x: apply(new(testpb.TestAllExtensions), 326 setExtension{testpb.E_DefaultInt32, int32(81)}, 327 setExtension{testpb.E_DefaultUint32, uint32(83)}, 328 setExtension{testpb.E_DefaultFloat, float32(91.5)}, 329 setExtension{testpb.E_DefaultBool, bool(true)}, 330 setExtension{testpb.E_DefaultBytes, []byte("world")}), 331 y: apply(new(testpb.TestAllExtensions), 332 setExtension{testpb.E_DefaultInt64, int64(82)}, 333 setExtension{testpb.E_DefaultUint64, uint64(84)}, 334 setExtension{testpb.E_DefaultDouble, float64(92e3)}, 335 setExtension{testpb.E_DefaultString, string("hello")}), 336 opts: cmp.Options{Transform(), IgnoreDefaultScalars()}, 337 want: true, 338 }, { 339 x: apply(new(testpb.TestAllExtensions), 340 setExtension{testpb.E_OptionalInt32, int32(0)}, 341 setExtension{testpb.E_OptionalUint32, uint32(0)}, 342 setExtension{testpb.E_OptionalFloat, float32(0)}, 343 setExtension{testpb.E_OptionalBool, bool(false)}, 344 setExtension{testpb.E_OptionalBytes, []byte("")}), 345 y: apply(new(testpb.TestAllExtensions), 346 setExtension{testpb.E_OptionalInt64, int64(0)}, 347 setExtension{testpb.E_OptionalUint64, uint64(0)}, 348 setExtension{testpb.E_OptionalDouble, float64(0)}, 349 setExtension{testpb.E_OptionalString, string("")}), 350 opts: cmp.Options{Transform()}, 351 want: false, 352 }, { 353 x: apply(new(testpb.TestAllExtensions), 354 setExtension{testpb.E_OptionalInt32, int32(0)}, 355 setExtension{testpb.E_OptionalUint32, uint32(0)}, 356 setExtension{testpb.E_OptionalFloat, float32(0)}, 357 setExtension{testpb.E_OptionalBool, bool(false)}, 358 setExtension{testpb.E_OptionalBytes, []byte("")}), 359 y: apply(new(testpb.TestAllExtensions), 360 setExtension{testpb.E_OptionalInt64, int64(0)}, 361 setExtension{testpb.E_OptionalUint64, uint64(0)}, 362 setExtension{testpb.E_OptionalDouble, float64(0)}, 363 setExtension{testpb.E_OptionalString, string("")}), 364 opts: cmp.Options{Transform(), IgnoreDefaultScalars()}, 365 want: true, 366 }, { 367 x: &testpb.TestAllTypes{ 368 DefaultFloat: proto.Float32(91.6), 369 }, 370 y: &testpb.TestAllTypes{}, 371 opts: cmp.Options{Transform(), IgnoreDefaultScalars()}, 372 want: false, 373 }, { 374 x: &testpb.TestAllTypes{ 375 OptionalForeignMessage: &testpb.ForeignMessage{}, 376 }, 377 y: &testpb.TestAllTypes{}, 378 opts: cmp.Options{Transform(), IgnoreDefaultScalars()}, 379 want: false, 380 }}...) 381 382 // Test IgnoreEmptyMessages. 383 tests = append(tests, []test{{ 384 x: []*testpb.TestAllTypes{nil, {}, {OptionalInt32: proto.Int32(5)}}, 385 y: []*testpb.TestAllTypes{nil, {}, {OptionalInt32: proto.Int32(5)}}, 386 opts: cmp.Options{Transform()}, 387 want: true, 388 }, { 389 x: []*testpb.TestAllTypes{nil, {}, {OptionalInt32: proto.Int32(5)}}, 390 y: []*testpb.TestAllTypes{{OptionalInt32: proto.Int32(5)}}, 391 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 392 want: false, 393 }, { 394 x: &testpb.TestAllTypes{OptionalForeignMessage: &testpb.ForeignMessage{}}, 395 y: &testpb.TestAllTypes{OptionalForeignMessage: nil}, 396 opts: cmp.Options{Transform()}, 397 want: false, 398 }, { 399 x: &testpb.TestAllTypes{OptionalForeignMessage: &testpb.ForeignMessage{}}, 400 y: &testpb.TestAllTypes{OptionalForeignMessage: nil}, 401 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 402 want: true, 403 }, { 404 x: &testpb.TestAllTypes{OptionalForeignMessage: &testpb.ForeignMessage{C: proto.Int32(5)}}, 405 y: &testpb.TestAllTypes{OptionalForeignMessage: nil}, 406 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 407 want: false, 408 }, { 409 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{}}, 410 y: &testpb.TestAllTypes{RepeatedForeignMessage: nil}, 411 opts: cmp.Options{Transform()}, 412 want: true, 413 }, { 414 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {}}}, 415 y: &testpb.TestAllTypes{RepeatedForeignMessage: nil}, 416 opts: cmp.Options{Transform()}, 417 want: false, 418 }, { 419 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {}}}, 420 y: &testpb.TestAllTypes{RepeatedForeignMessage: nil}, 421 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 422 want: true, 423 }, { 424 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(5)}, {}}}, 425 y: &testpb.TestAllTypes{RepeatedForeignMessage: nil}, 426 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 427 want: false, 428 }, { 429 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(5)}, {}}}, 430 y: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {}, nil, {}, {C: proto.Int32(5)}, {}}}, 431 opts: cmp.Options{Transform()}, 432 want: false, 433 }, { 434 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(5)}, {}}}, 435 y: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {}, nil, {}, {C: proto.Int32(5)}, {}}}, 436 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 437 want: true, 438 }, { 439 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{}}, 440 y: &testpb.TestAllTypes{MapStringNestedMessage: nil}, 441 opts: cmp.Options{Transform()}, 442 want: true, 443 }, { 444 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"1": nil, "2": {}}}, 445 y: &testpb.TestAllTypes{MapStringNestedMessage: nil}, 446 opts: cmp.Options{Transform()}, 447 want: false, 448 }, { 449 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"1": nil, "2": {}}}, 450 y: &testpb.TestAllTypes{MapStringNestedMessage: nil}, 451 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 452 want: true, 453 }, { 454 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"1": nil, "2": {A: proto.Int32(5)}, "3": {}}}, 455 y: &testpb.TestAllTypes{MapStringNestedMessage: nil}, 456 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 457 want: false, 458 }, { 459 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"1": nil, "2": {A: proto.Int32(5)}, "3": {}}}, 460 y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"1": {}, "1a": {}, "1b": nil, "2": {A: proto.Int32(5)}, "4": {}}}, 461 opts: cmp.Options{Transform()}, 462 want: false, 463 }, { 464 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"1": nil, "2": {A: proto.Int32(5)}, "3": {}}}, 465 y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"1": {}, "1a": {}, "1b": nil, "2": {A: proto.Int32(5)}, "4": {}}}, 466 opts: cmp.Options{Transform(), IgnoreEmptyMessages()}, 467 want: true, 468 }}...) 469 470 // Test IgnoreEnums and IgnoreMessages. 471 tests = append(tests, []test{{ 472 x: &testpb.TestAllTypes{ 473 OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}, 474 RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}, 475 MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"3": {A: proto.Int32(3)}}, 476 }, 477 y: &testpb.TestAllTypes{}, 478 opts: cmp.Options{Transform()}, 479 want: false, 480 }, { 481 x: &testpb.TestAllTypes{ 482 OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}, 483 RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}, 484 MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"3": {A: proto.Int32(3)}}, 485 }, 486 y: &testpb.TestAllTypes{}, 487 opts: cmp.Options{Transform(), IgnoreMessages(&testpb.TestAllTypes{})}, 488 want: true, 489 }, { 490 x: &testpb.TestAllTypes{ 491 OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum(), 492 RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}, 493 MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"baz": testpb.TestAllTypes_BAZ}, 494 }, 495 y: &testpb.TestAllTypes{}, 496 opts: cmp.Options{Transform()}, 497 want: false, 498 }, { 499 x: &testpb.TestAllTypes{ 500 OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum(), 501 RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}, 502 MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"baz": testpb.TestAllTypes_BAZ}, 503 }, 504 y: &testpb.TestAllTypes{}, 505 opts: cmp.Options{Transform(), IgnoreEnums(testpb.TestAllTypes_NestedEnum(0))}, 506 want: true, 507 }, { 508 x: &testpb.TestAllTypes{ 509 OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum(), 510 RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}, 511 MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"baz": testpb.TestAllTypes_BAZ}, 512 513 OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}, 514 RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}, 515 MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"3": {A: proto.Int32(3)}}, 516 }, 517 y: &testpb.TestAllTypes{}, 518 opts: cmp.Options{Transform(), 519 IgnoreMessages(&testpb.TestAllExtensions{}), 520 IgnoreEnums(testpb.ForeignEnum(0)), 521 }, 522 want: false, 523 }}...) 524 525 // Test IgnoreFields and IgnoreOneofs. 526 tests = append(tests, []test{{ 527 x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(5)}, 528 y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(6)}, 529 opts: cmp.Options{Transform()}, 530 want: false, 531 }, { 532 x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(5)}, 533 y: &testpb.TestAllTypes{}, 534 opts: cmp.Options{Transform(), 535 IgnoreFields(&testpb.TestAllTypes{}, "optional_int32")}, 536 want: true, 537 }, { 538 x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(5)}, 539 y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(6)}, 540 opts: cmp.Options{Transform(), 541 IgnoreFields(&testpb.TestAllTypes{}, "optional_int32")}, 542 want: true, 543 }, { 544 x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(5)}, 545 y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(6)}, 546 opts: cmp.Options{Transform(), 547 IgnoreFields(&testpb.TestAllTypes{}, "optional_int64")}, 548 want: false, 549 }, { 550 x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{5}}, 551 y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofString{"5"}}, 552 opts: cmp.Options{Transform()}, 553 want: false, 554 }, { 555 x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{5}}, 556 y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofString{"5"}}, 557 opts: cmp.Options{Transform(), 558 IgnoreFields(&testpb.TestAllTypes{}, "oneof_uint32"), 559 IgnoreFields(&testpb.TestAllTypes{}, "oneof_string")}, 560 want: true, 561 }, { 562 x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{5}}, 563 y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofString{"5"}}, 564 opts: cmp.Options{Transform(), 565 IgnoreOneofs(&testpb.TestAllTypes{}, "oneof_field")}, 566 want: true, 567 }, { 568 x: apply(new(testpb.TestAllExtensions), 569 setExtension{testpb.E_OptionalString, "hello"}), 570 y: apply(new(testpb.TestAllExtensions), 571 setExtension{testpb.E_OptionalString, "goodbye"}), 572 opts: cmp.Options{Transform()}, 573 want: false, 574 }, { 575 x: apply(new(testpb.TestAllExtensions), 576 setExtension{testpb.E_OptionalString, "hello"}), 577 y: new(testpb.TestAllExtensions), 578 opts: cmp.Options{Transform(), 579 IgnoreDescriptors(testpb.E_OptionalString.TypeDescriptor())}, 580 want: true, 581 }, { 582 x: apply(new(testpb.TestAllExtensions), 583 setExtension{testpb.E_OptionalString, "hello"}), 584 y: apply(new(testpb.TestAllExtensions), 585 setExtension{testpb.E_OptionalString, "goodbye"}), 586 opts: cmp.Options{Transform(), 587 IgnoreDescriptors(testpb.E_OptionalString.TypeDescriptor())}, 588 want: true, 589 }, { 590 x: apply(new(testpb.TestAllExtensions), 591 setExtension{testpb.E_OptionalString, "hello"}), 592 y: apply(new(testpb.TestAllExtensions), 593 setExtension{testpb.E_OptionalString, "goodbye"}), 594 opts: cmp.Options{Transform(), 595 IgnoreDescriptors(testpb.E_OptionalInt32.TypeDescriptor())}, 596 want: false, 597 }}...) 598 599 // Test FilterEnum. 600 tests = append(tests, []test{{ 601 x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()}, 602 y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()}, 603 opts: cmp.Options{Transform()}, 604 want: false, 605 }, { 606 x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()}, 607 y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()}, 608 opts: cmp.Options{ 609 Transform(), 610 FilterEnum(testpb.ForeignEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })), 611 }, 612 want: false, // mismatching filter type 613 }, { 614 x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()}, 615 y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()}, 616 opts: cmp.Options{ 617 Transform(), 618 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y int) bool { return true })), 619 }, 620 want: false, // matching filter type, but mismatching comparer type 621 }, { 622 x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()}, 623 y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()}, 624 opts: cmp.Options{ 625 Transform(), 626 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y testpb.TestAllTypes_NestedEnum) bool { return true })), 627 }, 628 want: false, // matching filter type, but mismatching comparer type 629 }, { 630 x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()}, 631 y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()}, 632 opts: cmp.Options{ 633 Transform(), 634 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })), 635 }, 636 want: true, 637 }, { 638 x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()}, 639 y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()}, 640 opts: cmp.Options{ 641 Transform(), 642 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y Enum) bool { return true })), 643 }, 644 want: true, 645 }, { 646 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}}, 647 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}}, 648 opts: cmp.Options{Transform()}, 649 want: false, 650 }, { 651 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}}, 652 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}}, 653 opts: cmp.Options{ 654 Transform(), 655 FilterEnum(testpb.ForeignEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })), 656 }, 657 want: false, // mismatching filter type 658 }, { 659 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}}, 660 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}}, 661 opts: cmp.Options{ 662 Transform(), 663 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y int) bool { return true })), 664 }, 665 want: false, // matching filter type, but mismatching comparer type 666 }, { 667 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}}, 668 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}}, 669 opts: cmp.Options{ 670 Transform(), 671 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y []testpb.TestAllTypes_NestedEnum) bool { return true })), 672 }, 673 want: false, // matching filter type, but mismatching comparer type 674 }, { 675 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}}, 676 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}}, 677 opts: cmp.Options{ 678 Transform(), 679 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })), 680 }, 681 want: true, 682 }, { 683 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}}, 684 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}}, 685 opts: cmp.Options{ 686 Transform(), 687 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y []Enum) bool { return true })), 688 }, 689 want: true, 690 }, { 691 x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}}, 692 y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}}, 693 opts: cmp.Options{Transform()}, 694 want: false, 695 }, { 696 x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}}, 697 y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}}, 698 opts: cmp.Options{ 699 Transform(), 700 FilterEnum(testpb.ForeignEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })), 701 }, 702 want: false, // mismatching filter type 703 }, { 704 x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}}, 705 y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}}, 706 opts: cmp.Options{ 707 Transform(), 708 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y int) bool { return true })), 709 }, 710 want: false, // matching filter type, but mismatching comparer type 711 }, { 712 x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}}, 713 y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}}, 714 opts: cmp.Options{ 715 Transform(), 716 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y map[string]testpb.TestAllTypes_NestedEnum) bool { return true })), 717 }, 718 want: false, // matching filter type, but mismatching comparer type 719 }, { 720 x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}}, 721 y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}}, 722 opts: cmp.Options{ 723 Transform(), 724 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })), 725 }, 726 want: true, 727 }, { 728 x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}}, 729 y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}}, 730 opts: cmp.Options{ 731 Transform(), 732 FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y map[string]Enum) bool { return true })), 733 }, 734 want: true, 735 }}...) 736 737 // Test FilterMessage. 738 tests = append(tests, []test{{ 739 x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}}, 740 y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}}, 741 opts: cmp.Options{Transform()}, 742 want: false, 743 }, { 744 x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}}, 745 y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}}, 746 opts: cmp.Options{ 747 Transform(), 748 FilterMessage(new(testpb.TestAllExtensions), cmp.Comparer(func(x, y interface{}) bool { return true })), 749 }, 750 want: false, // mismatching filter type 751 }, { 752 x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}}, 753 y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}}, 754 opts: cmp.Options{ 755 Transform(), 756 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y int) bool { return true })), 757 }, 758 want: false, // matching filter type, but mismatching comparer type 759 }, { 760 x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}}, 761 y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}}, 762 opts: cmp.Options{ 763 Transform(), 764 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y *testpb.TestAllTypes_NestedMessage) bool { return true })), 765 }, 766 want: false, // matching filter type, but mismatching comparer type 767 }, { 768 x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}}, 769 y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}}, 770 opts: cmp.Options{ 771 Transform(), 772 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y interface{}) bool { return true })), 773 }, 774 want: true, 775 }, { 776 x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}}, 777 y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}}, 778 opts: cmp.Options{ 779 Transform(), 780 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y Message) bool { return true })), 781 }, 782 want: true, 783 }, { 784 x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}}, 785 y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}}, 786 opts: cmp.Options{Transform()}, 787 want: false, 788 }, { 789 x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}}, 790 y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}}, 791 opts: cmp.Options{ 792 Transform(), 793 FilterMessage(new(testpb.TestAllExtensions), cmp.Comparer(func(x, y interface{}) bool { return true })), 794 }, 795 want: false, // mismatching filter type 796 }, { 797 x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}}, 798 y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}}, 799 opts: cmp.Options{ 800 Transform(), 801 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y int) bool { return true })), 802 }, 803 want: false, // matching filter type, but mismatching comparer type 804 }, { 805 x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}}, 806 y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}}, 807 opts: cmp.Options{ 808 Transform(), 809 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y []*testpb.TestAllTypes_NestedMessage) bool { return true })), 810 }, 811 want: false, // matching filter type, but mismatching comparer type 812 }, { 813 x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}}, 814 y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}}, 815 opts: cmp.Options{ 816 Transform(), 817 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y interface{}) bool { return true })), 818 }, 819 want: true, 820 }, { 821 x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}}, 822 y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}}, 823 opts: cmp.Options{ 824 Transform(), 825 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y []Message) bool { return true })), 826 }, 827 want: true, 828 }, { 829 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}}, 830 y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}}, 831 opts: cmp.Options{Transform()}, 832 want: false, 833 }, { 834 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}}, 835 y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}}, 836 opts: cmp.Options{ 837 Transform(), 838 FilterMessage(new(testpb.TestAllExtensions), cmp.Comparer(func(x, y interface{}) bool { return true })), 839 }, 840 want: false, // mismatching filter type 841 }, { 842 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}}, 843 y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}}, 844 opts: cmp.Options{ 845 Transform(), 846 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y int) bool { return true })), 847 }, 848 want: false, // matching filter type, but mismatching comparer type 849 }, { 850 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}}, 851 y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}}, 852 opts: cmp.Options{ 853 Transform(), 854 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y map[string]*testpb.TestAllTypes_NestedMessage) bool { return true })), 855 }, 856 want: false, // matching filter type, but mismatching comparer type 857 }, { 858 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}}, 859 y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}}, 860 opts: cmp.Options{ 861 Transform(), 862 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y interface{}) bool { return true })), 863 }, 864 want: true, 865 }, { 866 x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}}, 867 y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}}, 868 opts: cmp.Options{ 869 Transform(), 870 FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y map[string]Message) bool { return true })), 871 }, 872 want: true, 873 }}...) 874 875 // Test FilterField. 876 tests = append(tests, []test{{ 877 x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)}, 878 y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)}, 879 opts: cmp.Options{Transform()}, 880 want: false, 881 }, { 882 x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)}, 883 y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)}, 884 opts: cmp.Options{ 885 Transform(), 886 FilterField(new(testpb.TestAllTypes), "optional_int64", cmp.Comparer(func(x, y interface{}) bool { return true })), 887 }, 888 want: false, // mismatching filter name 889 }, { 890 x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)}, 891 y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)}, 892 opts: cmp.Options{ 893 Transform(), 894 FilterField(new(testpb.TestAllTypes), "optional_int32", cmp.Comparer(func(x, y int64) bool { return true })), 895 }, 896 want: false, // matching filter name, but mismatching comparer type 897 }, { 898 x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)}, 899 y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)}, 900 opts: cmp.Options{ 901 Transform(), 902 FilterField(new(testpb.TestAllTypes), "optional_int32", cmp.Comparer(func(x, y interface{}) bool { return true })), 903 }, 904 want: true, 905 }, { 906 x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)}, 907 y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)}, 908 opts: cmp.Options{ 909 Transform(), 910 FilterField(new(testpb.TestAllTypes), "optional_int32", cmp.Comparer(func(x, y int32) bool { return true })), 911 }, 912 want: true, 913 }, { 914 x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}}, 915 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}}, 916 opts: cmp.Options{Transform()}, 917 want: false, 918 }, { 919 x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}}, 920 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}}, 921 opts: cmp.Options{ 922 Transform(), 923 FilterField(new(testpb.TestAllTypes), "repeated_int64", cmp.Comparer(func(x, y interface{}) bool { return true })), 924 }, 925 want: false, // mismatching filter name 926 }, { 927 x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}}, 928 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}}, 929 opts: cmp.Options{ 930 Transform(), 931 FilterField(new(testpb.TestAllTypes), "repeated_int32", cmp.Comparer(func(x, y []int64) bool { return true })), 932 }, 933 want: false, // matching filter name, but mismatching comparer type 934 }, { 935 x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}}, 936 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}}, 937 opts: cmp.Options{ 938 Transform(), 939 FilterField(new(testpb.TestAllTypes), "repeated_int32", cmp.Comparer(func(x, y interface{}) bool { return true })), 940 }, 941 want: true, 942 }, { 943 x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}}, 944 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}}, 945 opts: cmp.Options{ 946 Transform(), 947 FilterField(new(testpb.TestAllTypes), "repeated_int32", cmp.Comparer(func(x, y []int32) bool { return true })), 948 }, 949 want: true, 950 }, { 951 x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}}, 952 y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}}, 953 opts: cmp.Options{Transform()}, 954 want: false, 955 }, { 956 x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}}, 957 y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}}, 958 opts: cmp.Options{ 959 Transform(), 960 FilterField(new(testpb.TestAllTypes), "map_int64_int64", cmp.Comparer(func(x, y interface{}) bool { return true })), 961 }, 962 want: false, // mismatching filter name 963 }, { 964 x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}}, 965 y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}}, 966 opts: cmp.Options{ 967 Transform(), 968 FilterField(new(testpb.TestAllTypes), "map_int32_int32", cmp.Comparer(func(x, y map[int64]int64) bool { return true })), 969 }, 970 want: false, // matching filter name, but mismatching comparer type 971 }, { 972 x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}}, 973 y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}}, 974 opts: cmp.Options{ 975 Transform(), 976 FilterField(new(testpb.TestAllTypes), "map_int32_int32", cmp.Comparer(func(x, y interface{}) bool { return true })), 977 }, 978 want: true, 979 }, { 980 x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}}, 981 y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}}, 982 opts: cmp.Options{ 983 Transform(), 984 FilterField(new(testpb.TestAllTypes), "map_int32_int32", cmp.Comparer(func(x, y map[int32]int32) bool { return true })), 985 }, 986 want: true, 987 }}...) 988 989 // Test FilterOneof 990 tests = append(tests, []test{{ 991 x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}}, 992 y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}}, 993 opts: cmp.Options{Transform()}, 994 want: false, 995 }, { 996 x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}}, 997 y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}}, 998 opts: cmp.Options{ 999 Transform(), 1000 FilterOneof(new(testpb.TestAllTypes), "oneof_optional", cmp.Comparer(func(x, y interface{}) bool { return true })), 1001 }, 1002 want: false, // mismatching filter name 1003 }, { 1004 x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}}, 1005 y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}}, 1006 opts: cmp.Options{ 1007 Transform(), 1008 FilterOneof(new(testpb.TestAllTypes), "oneof_field", cmp.Comparer(func(x, y string) bool { return true })), 1009 }, 1010 want: false, // matching filter name, but mismatching comparer type 1011 }, { 1012 x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}}, 1013 y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}}, 1014 opts: cmp.Options{ 1015 Transform(), 1016 FilterOneof(new(testpb.TestAllTypes), "oneof_field", cmp.Comparer(func(x, y uint32) bool { return true })), 1017 }, 1018 want: true, 1019 }, { 1020 x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}}, 1021 y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}}, 1022 opts: cmp.Options{ 1023 Transform(), 1024 FilterOneof(new(testpb.TestAllTypes), "oneof_field", cmp.Comparer(func(x, y interface{}) bool { return true })), 1025 }, 1026 want: true, 1027 }}...) 1028 1029 // Test SortRepeated. 1030 type higherOrderType struct { 1031 M *testpb.TestAllTypes 1032 I32s []int32 1033 Es []testpb.TestAllTypes_NestedEnum 1034 Ms []*testpb.ForeignMessage 1035 } 1036 tests = append(tests, []test{{ 1037 x: &testpb.TestAllTypes{RepeatedInt32: []int32{3, 2, 1, 2, 3, 3}}, 1038 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2, 3, 3, 2, 1, 3}}, 1039 opts: cmp.Options{Transform()}, 1040 want: false, 1041 }, { 1042 x: &testpb.TestAllTypes{RepeatedInt32: []int32{3, 2, 1, 2, 3, 3}}, 1043 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2, 3, 3, 2, 1, 3}}, 1044 opts: cmp.Options{ 1045 Transform(), 1046 SortRepeated(func(x, y int32) bool { return x < y }), 1047 }, 1048 want: true, 1049 }, { 1050 x: higherOrderType{ 1051 M: &testpb.TestAllTypes{RepeatedInt32: []int32{3, 2, 1, 2, 3, 3}}, 1052 I32s: []int32{3, 2, 1, 2, 3, 3}, 1053 }, 1054 y: higherOrderType{ 1055 M: &testpb.TestAllTypes{RepeatedInt32: []int32{2, 3, 3, 2, 1, 3}}, 1056 I32s: []int32{2, 3, 3, 2, 1, 3}, 1057 }, 1058 opts: cmp.Options{ 1059 Transform(), 1060 SortRepeated(func(x, y int32) bool { return x < y }), 1061 }, 1062 want: false, // sort does not apply to []int32 outside of a message 1063 }, { 1064 x: &testpb.TestAllTypes{RepeatedInt32: []int32{3, 2, 1, 2, 3, 3}}, 1065 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2, 3, 3, 2, 1, 3}}, 1066 opts: cmp.Options{ 1067 Transform(), 1068 SortRepeated(func(x, y int64) bool { return x < y }), 1069 }, 1070 want: false, // wrong sort type: int32 != int64 1071 }, { 1072 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAR, testpb.TestAllTypes_BAZ}}, 1073 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR, testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAZ}}, 1074 opts: cmp.Options{Transform()}, 1075 want: false, 1076 }, { 1077 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAR, testpb.TestAllTypes_BAZ}}, 1078 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR, testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAZ}}, 1079 opts: cmp.Options{ 1080 Transform(), 1081 SortRepeated(func(x, y testpb.TestAllTypes_NestedEnum) bool { return x < y }), 1082 }, 1083 want: true, 1084 }, { 1085 x: higherOrderType{ 1086 M: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAR, testpb.TestAllTypes_BAZ}}, 1087 Es: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAR, testpb.TestAllTypes_BAZ}, 1088 }, 1089 y: higherOrderType{ 1090 M: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR, testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAZ}}, 1091 Es: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR, testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAZ}, 1092 }, 1093 opts: cmp.Options{ 1094 Transform(), 1095 SortRepeated(func(x, y testpb.TestAllTypes_NestedEnum) bool { return x < y }), 1096 }, 1097 want: false, // sort does not apply to []testpb.TestAllTypes_NestedEnum outside of a message 1098 }, { 1099 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAR, testpb.TestAllTypes_BAZ}}, 1100 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR, testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAZ}}, 1101 opts: cmp.Options{ 1102 Transform(), 1103 SortRepeated(func(x, y testpb.ForeignEnum) bool { return x < y }), 1104 }, 1105 want: false, // wrong sort type: testpb.TestAllTypes_NestedEnum != testpb.ForeignEnum 1106 }, { 1107 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {C: proto.Int32(3)}, nil, {C: proto.Int32(3)}, {C: proto.Int32(5)}, {C: proto.Int32(4)}}}, 1108 y: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(3)}, {}, {C: proto.Int32(4)}, {C: proto.Int32(3)}, {C: proto.Int32(5)}}}, 1109 opts: cmp.Options{Transform()}, 1110 want: false, 1111 }, { 1112 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {C: proto.Int32(3)}, nil, {C: proto.Int32(3)}, {C: proto.Int32(5)}, {C: proto.Int32(4)}}}, 1113 y: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(3)}, {}, {C: proto.Int32(4)}, {C: proto.Int32(3)}, {C: proto.Int32(5)}}}, 1114 opts: cmp.Options{ 1115 Transform(), 1116 SortRepeated(func(x, y *testpb.ForeignMessage) bool { return x.GetC() < y.GetC() }), 1117 }, 1118 want: true, 1119 }, { 1120 x: higherOrderType{ 1121 M: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {C: proto.Int32(3)}, nil, {C: proto.Int32(3)}, {C: proto.Int32(5)}, {C: proto.Int32(4)}}}, 1122 Ms: []*testpb.ForeignMessage{{}, {C: proto.Int32(3)}, nil, {C: proto.Int32(3)}, {C: proto.Int32(5)}, {C: proto.Int32(4)}}, 1123 }, 1124 y: higherOrderType{ 1125 M: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(3)}, {}, {C: proto.Int32(4)}, {C: proto.Int32(3)}, {C: proto.Int32(5)}}}, 1126 Ms: []*testpb.ForeignMessage{nil, {C: proto.Int32(3)}, {}, {C: proto.Int32(4)}, {C: proto.Int32(3)}, {C: proto.Int32(5)}}, 1127 }, 1128 opts: cmp.Options{ 1129 Transform(), 1130 SortRepeated(func(x, y *testpb.ForeignMessage) bool { return x.GetC() < y.GetC() }), 1131 }, 1132 want: false, // sort does not apply to []*testpb.ForeignMessage outside of a message 1133 }, { 1134 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {C: proto.Int32(3)}, nil, {C: proto.Int32(3)}, {C: proto.Int32(5)}, {C: proto.Int32(4)}}}, 1135 y: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(3)}, {}, {C: proto.Int32(4)}, {C: proto.Int32(3)}, {C: proto.Int32(5)}}}, 1136 opts: cmp.Options{ 1137 Transform(), 1138 SortRepeated(func(x, y *testpb.TestAllTypes_NestedMessage) bool { return x.GetA() < y.GetA() }), 1139 }, 1140 want: false, // wrong sort type: *testpb.ForeignMessage != *testpb.TestAllTypes_NestedMessage 1141 }, { 1142 x: &testpb.TestAllTypes{ 1143 RepeatedInt32: []int32{-32, +32}, 1144 RepeatedSint32: []int32{-32, +32}, 1145 RepeatedSfixed32: []int32{-32, +32}, 1146 RepeatedInt64: []int64{-64, +64}, 1147 RepeatedSint64: []int64{-64, +64}, 1148 RepeatedSfixed64: []int64{-64, +64}, 1149 RepeatedUint32: []uint32{0, 32}, 1150 RepeatedFixed32: []uint32{0, 32}, 1151 RepeatedUint64: []uint64{0, 64}, 1152 RepeatedFixed64: []uint64{0, 64}, 1153 }, 1154 y: &testpb.TestAllTypes{ 1155 RepeatedInt32: []int32{+32, -32}, 1156 RepeatedSint32: []int32{+32, -32}, 1157 RepeatedSfixed32: []int32{+32, -32}, 1158 RepeatedInt64: []int64{+64, -64}, 1159 RepeatedSint64: []int64{+64, -64}, 1160 RepeatedSfixed64: []int64{+64, -64}, 1161 RepeatedUint32: []uint32{32, 0}, 1162 RepeatedFixed32: []uint32{32, 0}, 1163 RepeatedUint64: []uint64{64, 0}, 1164 RepeatedFixed64: []uint64{64, 0}, 1165 }, 1166 opts: cmp.Options{ 1167 Transform(), 1168 SortRepeated(func(x, y int32) bool { return x < y }), 1169 SortRepeated(func(x, y int64) bool { return x < y }), 1170 SortRepeated(func(x, y uint32) bool { return x < y }), 1171 SortRepeated(func(x, y uint64) bool { return x < y }), 1172 }, 1173 want: true, 1174 }}...) 1175 1176 // Test SortRepeatedFields. 1177 tests = append(tests, []test{{ 1178 x: &testpb.TestAllTypes{RepeatedInt32: []int32{3, 2, 1, 2, 3, 3}}, 1179 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2, 3, 3, 2, 1, 3}}, 1180 opts: cmp.Options{Transform()}, 1181 want: false, 1182 }, { 1183 x: &testpb.TestAllTypes{RepeatedInt32: []int32{3, 2, 1, 2, 3, 3}}, 1184 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2, 3, 3, 2, 1, 3}}, 1185 opts: cmp.Options{ 1186 Transform(), 1187 SortRepeatedFields(new(testpb.TestAllTypes), "repeated_int32"), 1188 }, 1189 want: true, 1190 }, { 1191 x: &testpb.TestAllTypes{RepeatedInt32: []int32{3, 2, 1, 2, 3, 3}}, 1192 y: &testpb.TestAllTypes{RepeatedInt32: []int32{2, 3, 3, 2, 1, 3}}, 1193 opts: cmp.Options{ 1194 Transform(), 1195 SortRepeatedFields(new(testpb.TestAllTypes), "repeated_int64"), 1196 }, 1197 want: false, // wrong field: repeated_int32 != repeated_int64 1198 }, { 1199 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAR, testpb.TestAllTypes_BAZ}}, 1200 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR, testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAZ}}, 1201 opts: cmp.Options{Transform()}, 1202 want: false, 1203 }, { 1204 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAR, testpb.TestAllTypes_BAZ}}, 1205 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR, testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAZ}}, 1206 opts: cmp.Options{ 1207 Transform(), 1208 SortRepeatedFields(new(testpb.TestAllTypes), "repeated_nested_enum"), 1209 }, 1210 want: true, 1211 }, { 1212 x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAR, testpb.TestAllTypes_BAZ}}, 1213 y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR, testpb.TestAllTypes_FOO, testpb.TestAllTypes_BAZ}}, 1214 opts: cmp.Options{ 1215 Transform(), 1216 SortRepeatedFields(new(testpb.TestAllTypes), "repeated_foreign_enum"), 1217 }, 1218 want: false, // wrong field: repeated_nested_enum != repeated_foreign_enum 1219 }, { 1220 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {C: proto.Int32(3)}, nil, {C: proto.Int32(3)}, {C: proto.Int32(5)}, {C: proto.Int32(4)}}}, 1221 y: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(3)}, {}, {C: proto.Int32(4)}, {C: proto.Int32(3)}, {C: proto.Int32(5)}}}, 1222 opts: cmp.Options{Transform()}, 1223 want: false, 1224 }, { 1225 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {C: proto.Int32(3)}, nil, {C: proto.Int32(3)}, {C: proto.Int32(5)}, {C: proto.Int32(4)}}}, 1226 y: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(3)}, {}, {C: proto.Int32(4)}, {C: proto.Int32(3)}, {C: proto.Int32(5)}}}, 1227 opts: cmp.Options{ 1228 Transform(), 1229 SortRepeatedFields(new(testpb.TestAllTypes), "repeated_foreign_message"), 1230 }, 1231 want: true, 1232 }, { 1233 x: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {C: proto.Int32(3)}, nil, {C: proto.Int32(3)}, {C: proto.Int32(5)}, {C: proto.Int32(4)}}}, 1234 y: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{nil, {C: proto.Int32(3)}, {}, {C: proto.Int32(4)}, {C: proto.Int32(3)}, {C: proto.Int32(5)}}}, 1235 opts: cmp.Options{ 1236 Transform(), 1237 SortRepeatedFields(new(testpb.TestAllTypes), "repeated_nested_message"), 1238 }, 1239 want: false, // wrong field: repeated_foreign_message != repeated_nested_message 1240 }, { 1241 x: &testpb.TestAllTypes{ 1242 RepeatedBool: []bool{false, true}, 1243 RepeatedInt32: []int32{-32, +32}, 1244 RepeatedInt64: []int64{-64, +64}, 1245 RepeatedUint32: []uint32{0, 32}, 1246 RepeatedUint64: []uint64{0, 64}, 1247 RepeatedFloat: []float32{-32.32, +32.32}, 1248 RepeatedDouble: []float64{-64.64, +64.64}, 1249 RepeatedString: []string{"hello", "world"}, 1250 RepeatedBytes: [][]byte{[]byte("hello"), []byte("world")}, 1251 RepeatedForeignEnum: []testpb.ForeignEnum{testpb.ForeignEnum_FOREIGN_FOO, testpb.ForeignEnum_FOREIGN_BAR}, 1252 RepeatedForeignMessage: []*testpb.ForeignMessage{{C: proto.Int32(-1)}, {C: proto.Int32(+1)}}, 1253 }, 1254 y: &testpb.TestAllTypes{ 1255 RepeatedBool: []bool{true, false}, 1256 RepeatedInt32: []int32{+32, -32}, 1257 RepeatedInt64: []int64{+64, -64}, 1258 RepeatedUint32: []uint32{32, 0}, 1259 RepeatedUint64: []uint64{64, 0}, 1260 RepeatedFloat: []float32{+32.32, -32.32}, 1261 RepeatedDouble: []float64{+64.64, -64.64}, 1262 RepeatedString: []string{"world", "hello"}, 1263 RepeatedBytes: [][]byte{[]byte("world"), []byte("hello")}, 1264 RepeatedForeignEnum: []testpb.ForeignEnum{testpb.ForeignEnum_FOREIGN_BAR, testpb.ForeignEnum_FOREIGN_FOO}, 1265 RepeatedForeignMessage: []*testpb.ForeignMessage{{C: proto.Int32(+1)}, {C: proto.Int32(-1)}}, 1266 }, 1267 opts: cmp.Options{ 1268 Transform(), 1269 SortRepeatedFields(new(testpb.TestAllTypes), 1270 "repeated_bool", 1271 "repeated_int32", 1272 "repeated_int64", 1273 "repeated_uint32", 1274 "repeated_uint64", 1275 "repeated_float", 1276 "repeated_double", 1277 "repeated_string", 1278 "repeated_bytes", 1279 "repeated_foreign_enum", 1280 "repeated_foreign_message", 1281 ), 1282 }, 1283 want: true, 1284 }}...) 1285 1286 for _, tt := range tests { 1287 t.Run("", func(t *testing.T) { 1288 got := cmp.Equal(tt.x, tt.y, tt.opts) 1289 if got != tt.want { 1290 if !got { 1291 t.Errorf("cmp.Equal = false, want true; diff:\n%v", cmp.Diff(tt.x, tt.y, tt.opts)) 1292 } else { 1293 t.Errorf("cmp.Equal = true, want false") 1294 } 1295 } 1296 }) 1297 } 1298} 1299 1300type setField struct { 1301 num protoreflect.FieldNumber 1302 val interface{} 1303} 1304type setUnknown struct { 1305 raw protoreflect.RawFields 1306} 1307type setExtension struct { 1308 typ protoreflect.ExtensionType 1309 val interface{} 1310} 1311 1312// apply applies a sequence of mutating operations to m. 1313func apply(m proto.Message, ops ...interface{}) proto.Message { 1314 mr := m.ProtoReflect() 1315 md := mr.Descriptor() 1316 for _, op := range ops { 1317 switch op := op.(type) { 1318 case setField: 1319 fd := md.Fields().ByNumber(op.num) 1320 mr.Set(fd, protoreflect.ValueOf(op.val)) 1321 case setUnknown: 1322 mr.SetUnknown(op.raw) 1323 case setExtension: 1324 mr.Set(op.typ.TypeDescriptor(), protoreflect.ValueOf(op.val)) 1325 } 1326 } 1327 return m 1328} 1329 1330func TestSort(t *testing.T) { 1331 t.Run("F32", func(t *testing.T) { 1332 want := []float32{ 1333 float32(math.Float32frombits(0xffc00000)), // -NaN 1334 float32(math.Inf(-1)), 1335 float32(-math.MaxFloat32), 1336 float32(-123.456), 1337 float32(-math.SmallestNonzeroFloat32), 1338 float32(math.Copysign(0, -1)), 1339 float32(math.Copysign(0, +1)), 1340 float32(+math.SmallestNonzeroFloat32), 1341 float32(+123.456), 1342 float32(+math.MaxFloat32), 1343 float32(math.Inf(+1)), 1344 float32(math.Float32frombits(0x7fc00000)), // +NaN 1345 } 1346 for i := 0; i < 10; i++ { 1347 t.Run("", func(t *testing.T) { 1348 got := append([]float32(nil), want...) 1349 rn := rand.New(rand.NewSource(int64(i))) 1350 for i, j := range rn.Perm(len(got)) { 1351 got[i], got[j] = got[j], got[i] 1352 } 1353 sort.Slice(got, func(i, j int) bool { 1354 return lessF32(got[i], got[j]) 1355 }) 1356 cmpF32s := cmp.Comparer(func(x, y float32) bool { 1357 return math.Float32bits(x) == math.Float32bits(y) 1358 }) 1359 if diff := cmp.Diff(want, got, cmpF32s); diff != "" { 1360 t.Errorf("Sort mismatch (-want +got):\n%s", diff) 1361 } 1362 }) 1363 } 1364 }) 1365 t.Run("F64", func(t *testing.T) { 1366 want := []float64{ 1367 float64(math.Float64frombits(0xfff8000000000001)), // -NaN 1368 float64(math.Inf(-1)), 1369 float64(-math.MaxFloat64), 1370 float64(-123.456), 1371 float64(-math.SmallestNonzeroFloat64), 1372 float64(math.Copysign(0, -1)), 1373 float64(math.Copysign(0, +1)), 1374 float64(+math.SmallestNonzeroFloat64), 1375 float64(+123.456), 1376 float64(+math.MaxFloat64), 1377 float64(math.Inf(+1)), 1378 float64(math.Float64frombits(0x7ff8000000000001)), // +NaN 1379 } 1380 for i := 0; i < 10; i++ { 1381 t.Run("", func(t *testing.T) { 1382 got := append([]float64(nil), want...) 1383 rn := rand.New(rand.NewSource(int64(i))) 1384 for i, j := range rn.Perm(len(got)) { 1385 got[i], got[j] = got[j], got[i] 1386 } 1387 sort.Slice(got, func(i, j int) bool { 1388 return lessF64(got[i], got[j]) 1389 }) 1390 cmpF64s := cmp.Comparer(func(x, y float64) bool { 1391 return math.Float64bits(x) == math.Float64bits(y) 1392 }) 1393 if diff := cmp.Diff(want, got, cmpF64s); diff != "" { 1394 t.Errorf("Sort mismatch (-want +got):\n%s", diff) 1395 } 1396 }) 1397 } 1398 }) 1399} 1400