-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
testing/protocmp: add IgnoreUnsetFields #1578
Comments
Implementing an IgnoreUnsetFields function in protocmp seems straight-forward: func IgnoreUnsetFields(want proto.Message) cmp.Option {
msg := want.ProtoReflect()
md := msg.Descriptor()
fields := md.Fields()
var names []protoreflect.Name
for i := 0; i < fields.Len(); i++ {
fd := fields.Get(i)
if msg.Has(fd) {
continue // field is set, do not ignore
}
names = append(names, fd.Name())
}
return protocmp.IgnoreFields(want, names...)
} …but I’m curious to hear what others think about this addition. |
What's the expected behavior with field extensions? |
Good question. Can you spell out what the concerns and options are? It sounds like maybe we’ll need to use Thanks |
I don't have any specific concerns, but just trying to remember things that would often bite us later on. Overall this feature sounds fine. It reminds me of @neild's "messagediff" package, which IIRC had an asymmetrical comparison that did something similar. |
For extensions, I'd expect The I wonder if the
And perhaps a
|
I was curious about the The way I see it, the biggest value of having an In the table below all 'yes' values are positive, all 'no' values are negative.
I couldn't find a downside with the proposed approach, but there might be something I'm not considering and I should. I share the concern with @dsnet that there might be some unforeseen complications that will come to bite us later on. The way I'll proceed is by creating this function in my team/org and popularizing it there. |
Are you referring to https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/util/message_differencer.h perhaps? It is a C++ message diffing library with partial comparison support.
I don’t think your “yes”es in this row are correct. The cmp library certainly uses reflection, and so does protoreflect.
Perhaps! Though it might be prudent to start with a protocmp option that knows about protobuf messages, and later replace it with a call to the general-purpose IgnoreUnsetFields() if that is indeed a drop-in replacement. @MasterMedo filed google/go-cmp#345 and retracted it with this comment:
…but that’s not inherent to structs. proto3 does not have presence either (except for fields explicitly marked as “optional”), so it does not distinguish between an unset field and a default-valued field either. So, we’ll face the same issue with a protocmp option. Returning to my original implementation:
This function signature is different from the other protocmp signatures: the currently existing ones take a parameter to work with the type, whereas mine takes a parameter to work with the specific message. My signature is problematic because it requires an odd structure for table-driven tests: instead of preparing I think we should try to come up with an implementation that matches the semantics of the existing options better. I had a quick look at it, but diving into cmp’s bowels requires more time than I can spend on this right now. Suggestions and contributions welcome. |
Yes, that's the one. The Google-internal |
Is your feature request related to a problem? Please describe.
Comparing protobuf types in full with the
cmp.Diff
orcmp.Equal
makes for a change detector test. This is because every time a new field is added to the protobuf all old tests need to be updated to have this field as well. This doesn't improve the confidence that the code is correct and introduces operational load on the engineers. Additionally, the lack of this feature causes many side values of the return type to be mocked. The problem with that is that often the mocked values don't contribute to the validity of the test and when they change in the implementation all tests need to be changed as well.Describe the solution you'd like
I'd like an option like
protocmp.IngoreUnsetFields(m protobufMessage)
to exist. It would be used by passing in thewant
protobuf message as the argument. E.g.Describe alternatives you've considered
Alternatively, one has to manually implement the function by using the
cmp.FilterField
function.Additional context
This started as a document created internally in Google because often when a field was added to a protobuf old tests needed to be changed. The addition of this function only partially solves the issues in that document, but it's a great first step!
The text was updated successfully, but these errors were encountered: