Conversation
Arguments.Is ranged over args but indexed objects, and compared with
!= on interface values:
for i, obj := range args {
if obj != objects[i] {
return false
}
}
Three things go wrong, all on master:
- Fewer objects than arguments panics with "index out of range".
- More objects than arguments is silently ignored, so
Arguments{"a", 1}.Is("a", 1, "extra") reports a match for a call
that could never have matched the expectation.
- An argument whose dynamic type is uncomparable (a slice, a map, a
func) panics with "comparing uncomparable type", so such arguments
could not be compared at all.
Get and Diff in the same file already handle both halves of this.
Get checks the index and panics with a message that reports the
arity. Diff has a missingArgument sentinel whose comment spells out
"either because the call passed fewer arguments than the expectation
declares or because it passed more", and it counts that as a
difference. Diff also compares through assert.ObjectsAreEqual, which
is reflect.DeepEqual-based and never panics on an uncomparable type.
Is was the only comparison helper on the type doing neither. Guard the
length and compare with ObjectsAreEqual, which is already imported.
Signed-off-by: feiiiiii5 <feiiiiii5@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mock.Arguments.Ispanics when fewer objects than arguments are supplied, silently reports a match when more are supplied, and panics on arguments whose type is uncomparable.GetandDiffin the same file already handle all three cases.Changes
len(objects) != len(args)and returnfalseinstead of indexing past the end or ignoring the extras.assert.ObjectsAreEqual(already imported in this file) instead of!=oninterface{}values, so a slice, map, or func argument compares instead of panicking.mock/mock_test.go, next to the existingTest_Arguments_Is.Motivation
The loop is bounded by
len(args)but indexesobjects[i], and!=on twointerface{}values compares dynamic types. Onmasterat87a7b9d57689f6579db2da795ab8deeab29cb724:The middle one is a logic error rather than a style question: supplying more objects than arguments reports a match, for a call the expectation can never have produced.
The rest of the type already handles both halves of this:
How
GetandDiffalready do itGetguards the index and reports the arity:Diffhas a sentinel whose comment spells out that arity is a difference in both directions:And
Diffcompares throughassert.ObjectsAreEqual, which isreflect.DeepEqual-based and does not panic on an uncomparable type.So "arity mismatch is a difference, not a crash" and "compare elements with
ObjectsAreEqual" are already this package's contract —Isis the one comparison helper on the type doing neither.Example usage
This changes behaviour in those three cases.
Isis not called anywhere inside the library outside its own test, so nothing internal moves; the effect is on external callers who relied on a panic, or on the extra-objects case that was silently wrong. I added the arity note to the doc comment so the new return value is documented rather than implied.Test plan
Go 1.24.3, macOS. Two tests added to
mock/mock_test.go, same package, same idioms. One covers both arity directions and assertsNotPanics; one covers a slice and a map argument and checks both the equal and unequal cases.Command output
Before the fix, with only the tests added:
After:
The gates from
.github/workflows/main.yml, both empty:go generate ./...fails on this checkout with a panic inside_codegen/main.goatparsePackageSource. It fails identically on the unmodifiedmaster, so it is a pre-existing Go 1.24 incompatibility in that tool. The generated forwarders only cover exported assertion APIs andIskeeps its signature, so no regeneration is needed either way.Related issues
None found. I searched open and closed issues and PRs for
Arguments.Is,mock Is arity,Is index out of range, andmock Arguments uncomparable; #393 (diffArguments panics with index out of range) and #587 (mock does not enforce arity if parameter is Anything) are both aboutDiff/Anythingand neither coversIs.