diff --git a/gomock/matchers.go b/gomock/matchers.go index bac4623b..337ca11d 100644 --- a/gomock/matchers.go +++ b/gomock/matchers.go @@ -219,6 +219,27 @@ func (m lenMatcher) String() string { return fmt.Sprintf("has length %d", m.i) } +type oneOfMatcher struct { + matches []interface{} +} + +func oneOf(matches []interface{}) Matcher { + return oneOfMatcher{matches: matches} +} + +func (m oneOfMatcher) Matches(x interface{}) bool { + for _, u := range m.matches { + if u == x { + return true + } + } + return false +} + +func (m oneOfMatcher) String() string { + return fmt.Sprintf("is one of %+v", m.matches) +} + type inAnyOrderMatcher struct { x any } @@ -366,3 +387,14 @@ func AssignableToTypeOf(x any) Matcher { func InAnyOrder(x any) Matcher { return inAnyOrderMatcher{x} } + +// OneOf is a Matcher that returns true when the parameter of the mock is +// part of the set provided to the matcher +// +// Example Usage: +// +// OneOf([]any{100,200,300}) +// OneOf([]any{"Go", "Gopher"}) +func OneOf(x []any) Matcher { + return oneOfMatcher{x} +} diff --git a/gomock/matchers_test.go b/gomock/matchers_test.go index 0a85906f..7e39cd2f 100644 --- a/gomock/matchers_test.go +++ b/gomock/matchers_test.go @@ -54,6 +54,7 @@ func TestMatchers(t *testing.T) { []e{[]string{"a"}, A{"b"}}, }, {"test Cond", gomock.Cond(func(x any) bool { return x.(B).Name == "Dam" }), []e{B{Name: "Dam"}}, []e{B{Name: "Dave"}}}, + {"test OneOf", gomock.OneOf([]any{1, 2, 3}), []e{1, 2, 3}, []e{4, 5, 6}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -145,6 +146,54 @@ func TestAssignableToTypeOfMatcher(t *testing.T) { } } +func TestOneOf(t *testing.T) { + tests := []struct { + name string + wanted []any + given any + wantMatch bool + }{ + { + name: "match for one of many", + wanted: []any{1, 2, 3}, + given: 1, + wantMatch: true, + }, + { + name: "match for single", + wanted: []any{1}, + given: 1, + wantMatch: true, + }, + { + name: "match for mixed types", + wanted: []any{1, "5", 0x4}, + given: 0x4, + wantMatch: true, + }, + { + name: "not match for empty slice", + wanted: []any{}, + given: 1, + wantMatch: false, + }, + { + name: "not match for type mismatch", + wanted: []any{1, 2, 3}, + given: "a", + wantMatch: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := gomock.OneOf(tt.wanted).Matches(tt.given); got != tt.wantMatch { + t.Errorf("got = %v, wantMatch %v", got, tt.wantMatch) + } + }) + } +} + func TestInAnyOrder(t *testing.T) { tests := []struct { name string