testing/protocmp: add Filter options
This CL adds the following helper options:
func FilterEnum(protoreflect.Enum, cmp.Option) cmp.Option
func FilterMessage(proto.Message, cmp.Option) cmp.Option
func FilterField(proto.Message, protoreflect.Name, cmp.Option) cmp.Option
func FilterOneof(proto.Message, protoreflect.Name, cmp.Option) cmp.Option
func FilterDescriptor(protoreflect.Descriptor, cmp.Option) cmp.Option
There is primarily exposing pre-existing functionality that the Ignore options
were already depending on to operate.
Change-Id: I44edf2ffa07de980a9ad3284525bfe3b45428d74
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/207177
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/testing/protocmp/util.go b/testing/protocmp/util.go
index 7a0b49b..b9ccae4 100644
--- a/testing/protocmp/util.go
+++ b/testing/protocmp/util.go
@@ -22,8 +22,90 @@
messageReflectType = reflect.TypeOf(Message{})
)
+// FilterEnum filters opt to only be applicable on standalone Enums,
+// singular fields of enums, list fields of enums, or map fields of enum values,
+// where the enum is the same type as the specified enum.
+//
+// The Go type of the last path step may be an:
+// • Enum for singular fields, elements of a repeated field,
+// values of a map field, or standalone Enums
+// • []Enum for list fields
+// • map[K]Enum for map fields
+// • interface{} for a Message map entry value
+//
+// This must be used in conjunction with Transform.
+func FilterEnum(enum protoreflect.Enum, opt cmp.Option) cmp.Option {
+ return FilterDescriptor(enum.Descriptor(), opt)
+}
+
+// FilterMessage filters opt to only be applicable on standalone Messages,
+// singular fields of messages, list fields of messages, or map fields of
+// message values, where the message is the same type as the specified message.
+//
+// The Go type of the last path step may be an:
+// • Message for singular fields, elements of a repeated field,
+// values of a map field, or standalone Messages
+// • []Message for list fields
+// • map[K]Message for map fields
+// • interface{} for a Message map entry value
+//
+// This must be used in conjunction with Transform.
+func FilterMessage(message proto.Message, opt cmp.Option) cmp.Option {
+ return FilterDescriptor(message.ProtoReflect().Descriptor(), opt)
+}
+
+// FilterField filters opt to only be applicable on the specified field
+// in the message. It panics if a field of the given name does not exist.
+//
+// The Go type of the last path step may be an:
+// • T for singular fields
+// • []T for list fields
+// • map[K]T for map fields
+// • interface{} for a Message map entry value
+//
+// This must be used in conjunction with Transform.
+func FilterField(message proto.Message, name protoreflect.Name, opt cmp.Option) cmp.Option {
+ md := message.ProtoReflect().Descriptor()
+ return FilterDescriptor(mustFindFieldDescriptor(md, name), opt)
+}
+
+// FilterOneof filters opt to only be applicable on all fields within the
+// specified oneof in the message. It panics if a oneof of the given name
+// does not exist.
+//
+// The Go type of the last path step may be an:
+// • T for singular fields
+// • []T for list fields
+// • map[K]T for map fields
+// • interface{} for a Message map entry value
+//
+// This must be used in conjunction with Transform.
+func FilterOneof(message proto.Message, name protoreflect.Name, opt cmp.Option) cmp.Option {
+ md := message.ProtoReflect().Descriptor()
+ return FilterDescriptor(mustFindOneofDescriptor(md, name), opt)
+}
+
+// FilterDescriptor ignores the specified descriptor.
+//
+// The following descriptor types may be specified:
+// • protoreflect.EnumDescriptor
+// • protoreflect.MessageDescriptor
+// • protoreflect.FieldDescriptor
+// • protoreflect.OneofDescriptor
+//
+// For the behavior of each, see the corresponding filter function.
+// Since this filter accepts a protoreflect.FieldDescriptor, it can be used
+// to also filter for extension fields as a protoreflect.ExtensionDescriptor
+// is just an alias to protoreflect.FieldDescriptor.
+//
+// This must be used in conjunction with Transform.
+func FilterDescriptor(desc protoreflect.Descriptor, opt cmp.Option) cmp.Option {
+ f := newNameFilters(desc)
+ return cmp.FilterPath(f.Filter, opt)
+}
+
// IgnoreEnums ignores all enums of the specified types.
-// See IgnoreDescriptors with regard to EnumDescriptors for more information.
+// It is equivalent to FilterEnum(enum, cmp.Ignore()) for each enum.
//
// This must be used in conjunction with Transform.
func IgnoreEnums(enums ...protoreflect.Enum) cmp.Option {
@@ -35,7 +117,7 @@
}
// IgnoreMessages ignores all messages of the specified types.
-// See IgnoreDescriptors with regard to MessageDescriptors for more information.
+// It is equivalent to FilterMessage(message, cmp.Ignore()) for each message.
//
// This must be used in conjunction with Transform.
func IgnoreMessages(messages ...proto.Message) cmp.Option {
@@ -46,9 +128,9 @@
return IgnoreDescriptors(ds...)
}
-// IgnoreFields ignores the specified fields in messages of type m.
-// This panics if a field of the given name does not exist.
-// See IgnoreDescriptors with regard to FieldDescriptors for more information.
+// IgnoreFields ignores the specified fields in the specified message.
+// It is equivalent to FilterField(message, name, cmp.Ignore()) for each field
+// in the message.
//
// This must be used in conjunction with Transform.
func IgnoreFields(message proto.Message, names ...protoreflect.Name) cmp.Option {
@@ -60,9 +142,9 @@
return IgnoreDescriptors(ds...)
}
-// IgnoreOneofs ignores fields in the specified oneofs in messages of type m.
-// This panics if a oneof of the given name does not exist.
-// See IgnoreDescriptors with regard to OneofDescriptors for more information.
+// IgnoreOneofs ignores fields of the specified oneofs in the specified message.
+// It is equivalent to FilterOneof(message, name, cmp.Ignore()) for each oneof
+// in the message.
//
// This must be used in conjunction with Transform.
func IgnoreOneofs(message proto.Message, names ...protoreflect.Name) cmp.Option {
@@ -75,24 +157,7 @@
}
// IgnoreDescriptors ignores the specified set of descriptors.
-// The following descriptor types may be specified:
-//
-// • EnumDescriptor: Enums of this type or messages containing singular fields,
-// list fields, or map fields with enum values of this type are ignored.
-// Enums are matched based on their full name.
-//
-// • MessageDescriptor: Messages of this type or messages containing
-// singular fields, list fields, or map fields with message values of this type
-// are ignored. Messages are matched based on their full name.
-//
-// • ExtensionDescriptor: Extensions fields that match the given descriptor
-// by full name are ignored.
-//
-// • FieldDescriptor: Message fields that match the given descriptor
-// by full name are ignored.
-//
-// • OneofDescriptor: Message fields that match the set of fields in the given
-// oneof descriptor by full name are ignored.
+// It is equivalent to FilterDescriptor(desc, cmp.Ignore()) for each descriptor.
//
// This must be used in conjunction with Transform.
func IgnoreDescriptors(descs ...protoreflect.Descriptor) cmp.Option {
@@ -192,6 +257,12 @@
}
func (f *nameFilters) filterFields(p cmp.Path) bool {
+ // Trim off trailing type-assertions so that the filter can match on the
+ // concrete value held within an interface value.
+ if _, ok := p.Last().(cmp.TypeAssertion); ok {
+ p = p[:len(p)-1]
+ }
+
// Filter for Message maps.
mi, ok := p.Index(-1).(cmp.MapIndex)
if !ok {
diff --git a/testing/protocmp/util_test.go b/testing/protocmp/util_test.go
index 1206592..04e0d1a 100644
--- a/testing/protocmp/util_test.go
+++ b/testing/protocmp/util_test.go
@@ -368,8 +368,6 @@
y: &testpb.TestAllTypes{RepeatedForeignMessage: []*testpb.ForeignMessage{{}, {}, nil, {}, {C: proto.Int32(5)}, {}}},
opts: cmp.Options{Transform(), IgnoreEmptyMessages()},
want: true,
-
- // TODO
}, {
x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{}},
y: &testpb.TestAllTypes{MapStringNestedMessage: nil},
@@ -531,6 +529,436 @@
want: false,
}}...)
+ // Test FilterEnum.
+ tests = append(tests, []test{{
+ x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+ y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+ y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.ForeignEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter type
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+ y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y int) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+ y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y testpb.TestAllTypes_NestedEnum) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+ y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_FOO.Enum()},
+ y: &testpb.TestAllTypes{OptionalNestedEnum: testpb.TestAllTypes_BAR.Enum()},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y Enum) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.ForeignEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter type
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y int) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y []testpb.TestAllTypes_NestedEnum) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{RepeatedNestedEnum: []testpb.TestAllTypes_NestedEnum{testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y []Enum) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.ForeignEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter type
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y int) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y map[string]testpb.TestAllTypes_NestedEnum) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_FOO}},
+ y: &testpb.TestAllTypes{MapStringNestedEnum: map[string]testpb.TestAllTypes_NestedEnum{"k": testpb.TestAllTypes_BAR}},
+ opts: cmp.Options{
+ Transform(),
+ FilterEnum(testpb.TestAllTypes_NestedEnum(0), cmp.Comparer(func(x, y map[string]Enum) bool { return true })),
+ },
+ want: true,
+ }}...)
+
+ // Test FilterMessage.
+ tests = append(tests, []test{{
+ x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}},
+ y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}},
+ y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllExtensions), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter type
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}},
+ y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y int) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}},
+ y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y *testpb.TestAllTypes_NestedMessage) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}},
+ y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(1)}},
+ y: &testpb.TestAllTypes{OptionalNestedMessage: &testpb.TestAllTypes_NestedMessage{A: proto.Int32(2)}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y Message) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllExtensions), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter type
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y int) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y []*testpb.TestAllTypes_NestedMessage) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{RepeatedNestedMessage: []*testpb.TestAllTypes_NestedMessage{{A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y []Message) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllExtensions), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter type
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y int) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y map[string]*testpb.TestAllTypes_NestedMessage) bool { return true })),
+ },
+ want: false, // matching filter type, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(1)}}},
+ y: &testpb.TestAllTypes{MapStringNestedMessage: map[string]*testpb.TestAllTypes_NestedMessage{"k": {A: proto.Int32(2)}}},
+ opts: cmp.Options{
+ Transform(),
+ FilterMessage(new(testpb.TestAllTypes_NestedMessage), cmp.Comparer(func(x, y map[string]Message) bool { return true })),
+ },
+ want: true,
+ }}...)
+
+ // Test FilterField.
+ tests = append(tests, []test{{
+ x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)},
+ y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)},
+ y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "optional_int64", cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter name
+ }, {
+ x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)},
+ y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "optional_int32", cmp.Comparer(func(x, y int64) bool { return true })),
+ },
+ want: false, // matching filter name, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)},
+ y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "optional_int32", cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{OptionalInt32: proto.Int32(1)},
+ y: &testpb.TestAllTypes{OptionalInt32: proto.Int32(2)},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "optional_int32", cmp.Comparer(func(x, y int32) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}},
+ y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}},
+ y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "repeated_int64", cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter name
+ }, {
+ x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}},
+ y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "repeated_int32", cmp.Comparer(func(x, y []int64) bool { return true })),
+ },
+ want: false, // matching filter name, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}},
+ y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "repeated_int32", cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{RepeatedInt32: []int32{1}},
+ y: &testpb.TestAllTypes{RepeatedInt32: []int32{2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "repeated_int32", cmp.Comparer(func(x, y []int32) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}},
+ y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}},
+ y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "map_int64_int64", cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter name
+ }, {
+ x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}},
+ y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "map_int32_int32", cmp.Comparer(func(x, y map[int64]int64) bool { return true })),
+ },
+ want: false, // matching filter name, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}},
+ y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "map_int32_int32", cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{1: 1}},
+ y: &testpb.TestAllTypes{MapInt32Int32: map[int32]int32{2: 2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterField(new(testpb.TestAllTypes), "map_int32_int32", cmp.Comparer(func(x, y map[int32]int32) bool { return true })),
+ },
+ want: true,
+ }}...)
+
+ // Test FilterOneof
+ tests = append(tests, []test{{
+ x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}},
+ y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}},
+ opts: cmp.Options{Transform()},
+ want: false,
+ }, {
+ x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}},
+ y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterOneof(new(testpb.TestAllTypes), "oneof_optional", cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: false, // mismatching filter name
+ }, {
+ x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}},
+ y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterOneof(new(testpb.TestAllTypes), "oneof_field", cmp.Comparer(func(x, y string) bool { return true })),
+ },
+ want: false, // matching filter name, but mismatching comparer type
+ }, {
+ x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}},
+ y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterOneof(new(testpb.TestAllTypes), "oneof_field", cmp.Comparer(func(x, y uint32) bool { return true })),
+ },
+ want: true,
+ }, {
+ x: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{1}},
+ y: &testpb.TestAllTypes{OneofField: &testpb.TestAllTypes_OneofUint32{2}},
+ opts: cmp.Options{
+ Transform(),
+ FilterOneof(new(testpb.TestAllTypes), "oneof_field", cmp.Comparer(func(x, y interface{}) bool { return true })),
+ },
+ want: true,
+ }}...)
+
for _, tt := range tests {
t.Run("", func(t *testing.T) {
got := cmp.Equal(tt.x, tt.y, tt.opts)