Skip to content
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

A matcher that matches at least one of the given matchers #58

Closed
favonia opened this issue Aug 10, 2023 · 3 comments · Fixed by #63
Closed

A matcher that matches at least one of the given matchers #58

favonia opened this issue Aug 10, 2023 · 3 comments · Fixed by #63

Comments

@favonia
Copy link
Contributor

favonia commented Aug 10, 2023

Requested feature

A new matcher combinator like All but returns true when one of the matchers returns true.

Why the feature is needed

We currently have All that matches all the matchers, just like the universal quantifier in the logic. It would be great to have AnyOf that matches at least one of them, similar to the existential quantifier in the logic. This is helpful when an argument can be one of several values. For example, with the new AnyOf matcher, we may write the following:

gomock.InOrder(
	m.EXPECT().SetDirection(AnyOf("north", "south", "west", "east"), true),
	m.EXPECT().Run(),
)

This means we expect a method call SetDirection("north", true), SetDirection("south", true), SetDirection("west", true) or SetDirection("east", true), which is then followed by a method call Run().

(Optional) Proposed solution

Here is a sample implementation. It's trivial for me to make a PR if the maintainers feel positive about this feature.

type anyOfMatcher struct {
	matchers []Matcher
}

func (am anyOfMatcher) Matches(x any) bool {
	for _, m := range am.matchers {
		if m.Matches(x) {
			return true
		}
	}
	return false
}

func (am anyOfMatcher) String() string {
	ss := make([]string, 0, len(am.matchers))
	for _, matcher := range am.matchers {
		ss = append(ss, matcher.String())
	}
	return strings.Join(ss, " | ")
}

func AnyOf(xs ...any) Matcher {
	ms := make([]Matcher, 0, len(xs))
	for _, x := range xs {
		if m, ok := x.(Matcher); ok {
			ms = append(ms, m)
		} else {
			ms = append(ms, Eq(x))
		}
	}
	return anyOfMatcher{ms}
}

Related issues and PRs (from the original gomock)

@JacobOaks
Copy link
Collaborator

Hey @favonia, I think this makes sense as a nice addition to the library. I think AnyOf would be a better name than Some though, since Some leaves ambiguous how many would need to match.

@favonia favonia changed the title A Some matcher that matches at least one of the given matchers A matcher that matches at least one of the given matchers Aug 15, 2023
@favonia
Copy link
Contributor Author

favonia commented Aug 15, 2023

@JacobOaks Done. Any other suggestions before I make a PR?

@JacobOaks
Copy link
Collaborator

@favonia awesome, nope - go ahead and thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants