-
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
Support protobuf equality #758
Comments
we've been using a fork in case interested parties want to try it out: vsco@d23661d |
Until #535 is implemented, this would be a nice workaround to have. |
It'd be great to see a PR to resolve #535, but barring that, I'm not sure we want to introduce a protobuf dependency. A build constraint might be OK, though. @boyan-soubachov thoughts? |
@glesica , I would agree that this is a bit too use-case specific and would want to avoid having protobuf-specific checks & code. I am, however completely on-board with moving to |
OK cool, let's try to pull that into the next release then, even if it doesn't actually go out with the next release it will keep it from getting lost. |
(I'm the author of both Google heavily uses protobufs and I have been asked many times for BTW, for |
Fair point. I've had some more time to think about this one as well and it seems like makes more sense for Thank you for the input, @dsnet |
I'm using embedding type to "inherit" Define a new internal package called package expect
import (
"fmt"
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/proto"
)
// Expectation is a embedding type for assert.Assertions
type Expectation struct {
*assert.Assertions
}
// New makes a new Expectation object for the specified TestingT.
func New(t assert.TestingT) *Expectation {
assert := assert.New(t)
return &Expectation{assert}
}
// ProtoEqual asserts that the specified protobuf messages are equal.
func (a *Expectation) ProtoEqual(expected, actual proto.Message) bool {
return a.True(
proto.Equal(expected, actual),
fmt.Sprintf("These two protobuf messages are not equal:\nexpected: %v\nactual: %v", expected, actual),
)
} Then in the test files, I can use both the origin assert functions from github.com/stretchr/testify/assert as well as my custom assert function. func TestBaseWorkflow(t *testing.T) {
expect := expect.New(t)
expect.NotEqual(1, 2) //
expect.ProtoEqual(&pb.Pod{}, &pb.Pod{}) //
} |
@boyan-soubachov I think having a small extensibility to func Diff(x, y interface{}, opts ...Option) string
type Option interface {
// filter applies all filters and returns the option that remains.
// Each option may only read s.curPath and call s.callTTBFunc.
//
// An Options is returned only if multiple comparers or transformers
// can apply simultaneously and will only contain values of those types
// or sub-Options containing values of those types.
filter(s *state, t reflect.Type, vx, vy reflect.Value) applicableOption
} Maybe the interface will be different, similar to
assert.CustomEqual(t, want, got, MyCustomProtoEqualer) |
A solution to this would be to allow people to provide custom equality and serialization options. Could look like this: // applied to assert.New constructor
assert := assert.New(t, assert.WithEqualCheck(func(expected, actual interface{}) (result, ok bool) {
expectedProto, ok := expected.(proto.Message)
if !ok {
return false, false
}
actualProto, ok := actual.(proto.Message)
if !ok {
return false, false
}
return proto.Equal(expectedProto, actualProto), true
})
// with package level option, if not using the assert.New constructor
assert.AddEqualCheck(func(expected, actual interface{}) (result, ok bool) {
expectedProto, ok := expected.(proto.Message)
if !ok {
return false, false
}
actualProto, ok := actual.(proto.Message)
if !ok {
return false, false
}
return proto.Equal(expectedProto, actualProto), true
}) The first boolean result is the equality check, and the second is if it "should count", i.e. can we bail on comparisons or should we continue with other comparisons. This would let people pull in their own dependencies, while still leveraging this great library. |
Any updates to this? |
OSD-dev was failing for a few reason. First the test is expecting to use Go 1.16, so we updated the osd-dev image to use 1.16. Secondly, there is issue with mock comparing structs generated by protobuf. The new protobuf version has extra hidden fields that causes comparison to fail even if the values are the same. Similar issues in stretchr/testify#758. For the fix, we move all of the mock request using protobuf to use mock.Any() as the parameters to bypass the comparison. This should be discussed with other contributors if there are other possibilities. Testing: local testing passes this issue Signed-off-by: dahuang <dahuang@purestorage.com>
I believe by now |
Good point. Unfortunately, this doesn't work for pointers. Perhaps the feature request now is to make this function handle pointers? |
I just opened a pull request for this. Thanks for the suggestion :). |
Sorry just closed the PR. Let's wait for the PR to be merged |
I've merged that change and you should expect it in testify v1.8.5. Does EqaulExpertedValues fully resolve this Issue or are there some comparisons that protobuf users still can't make? |
Thanks for the change it's really useful! Something unrelated to protobuf is still missing: Let me know if I should create another issue. |
Yes, create a new issue. I'm going to mark this as completed. Please let me know if protobuf equality is still an issue. |
There's a subtle issue when using assertions with protobuf structs, because protobuf structs contain internal fields that should be ignored during assertions.
I think it'd be nice for testify to support this. Particularly, we can add this line in
ObjectsAreEqual
to check if both objects are protobuf messages, and if so,proto.Equal
as suggested.The problem would be introducing a dependency on golang/protobuf, which I'm not sure would be acceptable.
If not, one way to address this is using build constraints. We can split the
ObjectsAreEqual
method into a fileequal.go
that is compiled by default. And with a build constraint, we can toggle whether to include the protobuf support:equal.go:
// +build !protobuf
equal_protos.go:
// +build protobuf
This way, we can include support for protobuf without introducing the dependency for everyone.
The text was updated successfully, but these errors were encountered: