Skip to content

RFC: Matching a sequence of actuals, in no particular order #683

@thediveo

Description

@thediveo

Another one from the "odd stuff" department: from time to time I need to receive several things from a channel, but the order of them might be undefined. Such as events overtaking each other.

And to be honest, I ever wanted to give MakeMatcher a try! 👍🏼

My first attempt is an All(...) matcher to be used with Receive():

// All succeeds only after it has been shown a sequence of actual values that
// “ticked off” the specified matchers in no particular order. All will return
// an error in case it encounters an actual value not matching any of the
// specified matchers. If the same match should occur multiple times it needs to
// be specified as many times as required.
func All(matchers ...types.GomegaMatcher) types.GomegaMatcher {
	// Now that's fun to keep state not in a struct "object" but instead capture
	// state in a closure.
	remaining := slices.Clone(matchers)
	return MakeMatcher(func(actual any) (bool, error) {
		for idx, matcher := range remaining {
			succeeded, err := matcher.Match(actual)
			if err != nil {
				return false, err
			}
			if !succeeded {
				continue // ...maybe another one will match...?
			}
			remaining = slices.Delete(remaining, idx, idx+1)
			if len(remaining) > 0 {
				return false, nil
			}
			return true, nil
		}
		return false, errors.New("not in expected set")
	}).WithTemplate("Expected:\n{{.FormattedActual}}\n{{.To}} complete set")
}

However, the All matcher is a little bit off the beaten matcher path, as it does not keep silent when it doesn't match, but instead throws an error. It's like the temporal version of Contains(...) (on arrays, slices and maps), but this time on channel receives.

Any suggestion as to how to improve the error reporting in this case?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions