-
Notifications
You must be signed in to change notification settings - Fork 209
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
Any way to do value-predicated filtering (rather than type) #270
Comments
Technically, yes. The entire Assuming that function were exported, you could do something like: cmpIPs := cmpopts.FilterField(T{}, "IPs", cmp.Comparer(func(x, y []string) bool {
return reflect.DeepEqual(x, y) || len(x) == 0 || len(y) == 0
}))
cmpPort := cmpopts.FilterField(T{}, "Port", cmp.Comparer(func(x, y int) bool {
return x == y || x == 0 || y == 0
}))
cmp.Equal(input, output, cmpIPs, cmpPort) I modified the checks against 0 to be symmetric. The requirement that
Regarding why |
For the composibility problems with
|
Interesting. The symmetric bit is a trick for this case though - the comparison I need is not symmetric. (nil, "value") is allowed while ("value", nil) is an error. For the moment I just pre-process the object and do |
I recently had the same question and ended up essentially did the same as @thockin with github.com/imdario/mergo: // Make a copy of want so we can merge ignored fields into it for diff without
// modifying the original object.
want = want.DeepCopyObject()
wantVal := reflect.ValueOf(want)
gotVal := reflect.New(reflect.Indirect(wantVal).Type())
got := gotVal.Interface()
... // populate got
// Merge all non-empty ignored fields from got to want.
if err := mergo.Merge(want, reflect.Indirect(gotVal).Interface()); err != nil {
return fmt.Errorf("unable to merge ignored fields: %w", err)
}
if diff := cmp.Diff(want, got); diff != "" {
return fmt.Errorf("unexpected diff (-want +got):\n%s", diff)
} Specifically, |
I have the exact same use case: diffing K8s API objects and not wanting symmetry. i.e. I'd like a rule like: "when diffing O1 and O2, ignore all fields of O1 that are nil, no matter their type or path" |
The symmetric nature of cmp.Diff(want, got, cmpopts.IgnoreUnpopulated(want)) where The exact semantics of |
Another snippet to use in combination with the time transformer to correctly compare KRM object statuses (before darccio/mergo#222 is merged): // The following function allows deep-merging slices (e.g., []metav1.Condition).
return func(dst, src reflect.Value) error {
if dst.CanSet() {
for i := 0; i < src.Len() && i < dst.Len(); i++ {
srcElem := src.Index(i)
dstPtr := dst.Index(i).Addr() // an element of a slice is always addressable
if !srcElem.CanInterface() || !dstPtr.CanInterface() {
continue
}
if err := mergo.Merge(dstPtr.Interface(), srcElem.Interface(), mergo.WithTransformers(self)); err != nil {
return err
}
}
if dst.Len() < src.Len() {
dst.Set(reflect.AppendSlice(dst, src.Slice(dst.Len(), src.Len())))
}
}
return nil
} |
@dsnet I see that a non-symmetric equal would be confusing. OTOH, it might make sense because having |
I have a function like this:
I'm trying to use cmp.Equal and cmp.Diff to test. I specifically want to test permutations where the input specifies and doesn't specify input IPs and ports. The real logic is significantly more complicated than this reductive example, obviously.
What I am looking for is a
cmp.Option
similar toIgnoreFields
(since the type is[]string
) crossed withComparer()
, but without the symmetric requirement. For example:Is this possible to express?
The text was updated successfully, but these errors were encountered: