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

feat: Support iter.Seqs in [Not]Contains and [Not]ElementsMatch #1685

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

misberner
Copy link

Summary

This PR adds support iter.Seq[...] sequences (introduced in Go 1.23, or earlier via rangefunc experiment) in the Contains and ElementsMatch (+ derived) asserters.

Changes

  • Introduced a seqToSlice helper that transparently converts an iter.Seq (which is a function of signature func(func(T) bool)) to a corresponding slice of type []T, if support for sequences is enabled. Otherwise, it does nothing. Note: this function is reflection-based and does not introduce any source dependencies on newer language features, thereby respecting the Go version constraint in the go.mod file.
  • Used the seqToSlice helper in the above-mentioned asserters to contain any inputs from sequence to slice form (this has to happen early on because of the empty check)
  • Added tests (conditional on the support for sequences) for these matchers on sequences

Motivation

Sequences are a new language feature that as of go1.23 has become standard for obtaining sequences of values w/o requiring to materialize the values into a slice (e.g., maps.Keys(...), maps.Values(...)). Currently, using these sequences in matchers requires materialization via slices.Collect. However, since ElementsMatch and Contains are conceptually applicable to sequences in addition to slices, arrays etc., this should be handled by the testify framework.

Example usage

requires go1.23

import "slices"
import "maps"
...
assert.ElementsMatch(slices.Values([]string{"hello", "world"}), []string{"world", "hello"})
assert.NotContains(maps.Values(map[int]string{1: "foo", 2: "bar"}), "baz")

## Related issues
N/A


// seqToSlice checks if x is a sequence, and converts it to a slice of the
// same element type. Otherwise, x is returned as-is.
func seqToSlice(x interface{}) interface{} {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use type assertion to check it's a sequence
Then use slices.Collect(x) ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, because:

  1. we don’t know the generic type parameter, and
  2. i don’t think we can use iter and slices or generics given the go1.18 version specifier in go.mod

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, you are not updating Contains signature, and yes the go.mod doesn't help

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 this pull request may close these issues.

3 participants