Skip to content

Commit 3fdf471

Browse files
committed
Use an Ignore option instead of a Comparer
Comparer options cannot be used with other Comparer options or Transformer options. Unfortunatelly, go-cmp currently doesn't provide a nice way to compose several such options (see: google/go-cmp#36). An Ignore option seems to be more suitable semantically in this case and it does not conflict with other options.
1 parent 49a2e02 commit 3fdf471

3 files changed

Lines changed: 22 additions & 26 deletions

File tree

matchers/matchers.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ import (
77
"github.com/xosmig/placeholders"
88
)
99

10-
// DiffEq invokes cmpmock.DiffEq with an extra placeholders.Comparer() option.
11-
// Note that, if another cmp.Comparer or cmp.Transformer option is provided, it
12-
// will cause an ambiguity and gocmp will panic. Use a custom wrapper option in
13-
// this case.
10+
// DiffEq invokes cmpmock.DiffEq with an extra placeholders.Ignore() option.
1411
func DiffEq(x any, opts ...cmp.Option) gomock.Matcher {
15-
return cmpmock.DiffEq(x, placeholders.Comparer(), cmp.Options(opts))
12+
return cmpmock.DiffEq(x, placeholders.Ignore(), cmp.Options(opts))
1613
}

placeholders.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,18 @@ type TestingCleanup interface {
3939
// type TPtr that references the allocated object. TPtr is either *T or has *T
4040
// as its underlying type (i.e, defined as "type Foo *Bar", where TPtr = Foo
4141
// and T = Bar). The returned reference or any other reference to the allocated
42-
// object is considered a placeholder reference: when cmp.Equal is invoked
43-
// with the placeholders.Comparer option, a placeholder reference is considered
44-
// to be equal to any other object, regardless of types or values.
42+
// object is considered a placeholder reference: when cmp.Equal or cmp.Diff is
43+
// invoked with the placeholders.Ignore option, a placeholder reference is
44+
// considered to be equal to any other object, regardless of types or values.
4545
//
4646
// Only pointers to the allocated object are considered placeholders and not
4747
// the object itself (see examples below).
4848
//
4949
// The second type parameter (T) can always be inferred from the first one
5050
// (TPtr) and does not need to be explicitly specified.
5151
//
52-
// The only parameter (t) can of type *testing.T, *testing.B, or any other type
53-
// with a function Cleanup with a similar semantic and it ensures that the
52+
// The only parameter (t) can be of type *testing.T, *testing.B, or any other
53+
// type with a function Cleanup with a similar semantic. It ensures that the
5454
// resources allocated to keep track of the placeholders are eventually
5555
// reclaimed (e.g., when t is of type *testing.T, they are reclaimed upon the
5656
// completion of the test).
@@ -59,24 +59,24 @@ type TestingCleanup interface {
5959
// helloString := "hello"
6060
//
6161
// // true
62-
// cmp.Equal(placeholders.Make[*string](t), &helloString, placeholders.Comparer())
62+
// cmp.Equal(placeholders.Make[*string](t), &helloString, placeholders.Ignore())
6363
//
6464
// placeholder := placeholders.Make[*string](t)
6565
// anotherRef := &(*placeholder)
6666
//
6767
// // true, any reference to the allocated object is a placeholder
68-
// cmp.Equal(anotherRef, &helloString, placeholders.Comparer())
68+
// cmp.Equal(anotherRef, &helloString, placeholders.Ignore())
6969
//
7070
// // false, the allocated object itself is not a placeholder
71-
// cmp.Equal(*placeholder, "hello", placeholders.Comparer())
71+
// cmp.Equal(*placeholder, "hello", placeholders.Ignore())
7272
//
7373
// type Foo struct {SPtr *string; S string}
7474
//
7575
// // true, it works with struct fields and embedded types as well!
76-
// cmp.Equal(Foo{placeholders.Make[*string](t), "world"}, Foo{&helloString, "world"}, placeholders.Comparer())
76+
// cmp.Equal(Foo{placeholders.Make[*string](t), "world"}, Foo{&helloString, "world"}, placeholders.Ignore())
7777
//
7878
// // false, non-placeholder fields differ
79-
// cmp.Equal(Foo{placeholders.Make[*string](t), "earthlings"}, Foo{&helloString, "world"}, placeholders.Comparer())
79+
// cmp.Equal(Foo{placeholders.Make[*string](t), "earthlings"}, Foo{&helloString, "world"}, placeholders.Ignore())
8080
func Make[TPtr ~*T, T any](t TestingCleanup) TPtr {
8181
placeholderManagerInit.Do(func() {
8282
// placeholderManager.placeholdersMx doesn't need initialization.
@@ -138,12 +138,11 @@ func IsPlaceholder(obj any) bool {
138138

139139
func equateAlways(_, _ interface{}) bool { return true }
140140

141-
// Comparer returns a cmp.Comparer option that determines a placeholder to be
142-
// equal with any other object (regardless of types and values).
143-
func Comparer() cmp.Option {
141+
// Ignore returns a cmp.Ignore option that ignores all placeholders.
142+
func Ignore() cmp.Option {
144143
filter := func(a, b any) bool {
145144
return IsPlaceholder(a) || IsPlaceholder(b)
146145
}
147146

148-
return cmp.FilterValues(filter, cmp.Comparer(equateAlways))
147+
return cmp.FilterValues(filter, cmp.Ignore())
149148
}

placeholders_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,22 @@ func TestMake_Example(t *testing.T) {
2929
helloString := "hello"
3030

3131
// true
32-
assert.Assert(t, cmp.Equal(Make[*string](t), &helloString, Comparer()))
32+
assert.Assert(t, cmp.Equal(Make[*string](t), &helloString, Ignore()))
3333

3434
placeholder := Make[*string](t)
3535
anotherRef := &(*placeholder) // nolint
3636

3737
// true, any reference to the allocated object is a placeholder
38-
assert.Assert(t, cmp.Equal(anotherRef, &helloString, Comparer()))
38+
assert.Assert(t, cmp.Equal(anotherRef, &helloString, Ignore()))
3939

4040
// false, the allocated object itself is not a placeholder
41-
assert.Assert(t, !cmp.Equal(*placeholder, "hello", Comparer()))
41+
assert.Assert(t, !cmp.Equal(*placeholder, "hello", Ignore()))
4242

4343
// true, it works with struct fields and embedded types as well!
44-
assert.Assert(t, cmp.Equal(Foo{Make[*string](t), "world"}, Foo{&helloString, "world"}, Comparer()))
44+
assert.Assert(t, cmp.Equal(Foo{Make[*string](t), "world"}, Foo{&helloString, "world"}, Ignore()))
4545

4646
// false, non-placeholder fields differ
47-
assert.Assert(t, !cmp.Equal(Foo{Make[*string](t), "earthlings"}, Foo{&helloString, "world"}, Comparer()))
47+
assert.Assert(t, !cmp.Equal(Foo{Make[*string](t), "earthlings"}, Foo{&helloString, "world"}, Ignore()))
4848
}
4949

5050
func TestMake(tt *testing.T) {
@@ -159,10 +159,10 @@ func TestMake(tt *testing.T) {
159159
for testName, tc := range testCases {
160160
tt.Run(testName, func(t *testing.T) {
161161
arg1, arg2, expectedEqual := tc(t)
162-
equal := cmp.Equal(arg1, arg2, Comparer())
162+
equal := cmp.Equal(arg1, arg2, Ignore())
163163
if expectedEqual && !equal {
164164
t.Errorf("structs are supposed to be considered equal, but are considered differet. diff: %v",
165-
cmp.Diff(arg1, arg2, Comparer()))
165+
cmp.Diff(arg1, arg2, Ignore()))
166166
} else if !expectedEqual && equal {
167167
t.Error("structs are supposed to be considered different, but are considered equal")
168168
}

0 commit comments

Comments
 (0)