You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A mock assertion placed before the call under test passes for any implementation:
// vacuous: the mock has recorded nothing yetmockSP.AssertNotCalled(t, "DescribeSavingsPlansOfferings", mock.Anything, mock.Anything)
id, err:=client.findOfferingID(ctx, rec, "test-exec")
Why TestNoUnfailableMockAssertions does not catch it
The guard compares matcher count against the method's m.Called arity. It has no notion of "the call under test", and inferring one is the hard part — any call in the test could be it, or none could.
A prototype detector was written and run: for each assertion, report any later call in the same scope that is not itself an assertion or test scaffolding. Refinements applied: innermost-scope resolution so sibling t.Run subtests do not count, and skipping t.Cleanup bodies since they execute after the test returns.
Result across the files PR LeanerCloud/cloud-commitments-cli#1750 touched: 10 findings, 1 true positive, 9 false positives. The false positives are calls appearing as arguments to other assertions (assert.False(t, scheduler.collecting.Load())) and assertions inside subtests whose enclosing scope contains later unrelated calls.
A check at that ratio is worse than no check — it trains readers to ignore it, and a guard that is ignored gets deleted. That is the same failure direction the whole LeanerCloud/cloud-commitments-cli#1595/#1740 line of work exists to avoid, so it was not merged into the guard.
What would make it tractable
Some combination of:
Requiring the assertion's mock to be passed into something called later in the same scope, rather than treating any later call as the call under test.
Restricting to AssertNotCalled on a mock with no recorded interaction anywhere earlier in the scope — narrower, far fewer false positives, and it would have caught the live instance.
Treating it as a go vet-style analyzer with errors.As-grade type information rather than a syntactic pass.
The second option looks most promising and may be cheap. It is not attempted here because LeanerCloud/cloud-commitments-cli#1750 was already blocked on three other findings.
Meanwhile
Reviewers should check ordering by eye on any AssertNotCalled. The rule is simply: the assertion belongs after the code under test, and a negative assertion sitting above the call is always wrong.
Added by an automated audit of 3c0f8ac94048a2c36fce5ccddee54e6c4849a5cd (tip of origin/main). Each item below was reported by one reviewer and independently confirmed by a second that did not write it. Full report: docs/audits/codebase-audit-2026-09-02.md.
A15-004 (medium)
A second gap in the same guard, structural rather than a new vacuity mode. TestNoUnfailableMockAssertions walks the repo and then per directory does mocks := collectMocks(files); if len(mocks) == 0 { continue } (internal/mocks/vacuous_assertion_guard_test.go:137). A package that uses a mock imported from elsewhere but declares none locally is dropped before its assertion sites are collected, and it is not added to the skipped slice the test errors on -- which contradicts the guard's own contract that a silent skip is the defect it exists to catch. Replaying the walk over the pinned tree, four packages with 15 assertion sites are invisible: internal/server (6), providers/azure/services/compute (4), managedredis (3), synapse (2), while the run logs "checked 162 mock assertion site(s)" and passes with zero skips reported. None of the 15 is vacuous today (each passes a matcher count equal to the real m.Called arity), so this is a hole rather than a live unfailable assertion. Collecting assertion sites before the len(mocks) == 0 test and resolving them through the existing repo-wide global index, routing anything unresolved into skipped, closes it. (audit finding A15-004)
A16-012 (low)
Another shape for this catalogue, and it has live instances. In internal/auth/account_scope_fail_closed_test.go:74, assert.False(t, IsUnrestrictedAccess(got) && err == nil, ...) sits after require.Error(t, err) at :69, which aborts the subtest when err == nil. By line 74 err != nil holds unconditionally, so the && err == nil conjunct is constant false and the assertion cannot fire for any value of IsUnrestrictedAccess(got). The comment above it claims it restates the security property independently of the preceding assertions, which is the risk: a reader auditing the file sees the invariant explicitly asserted and stops looking, when the real protection is assert.Nil(t, got) on the line above. The construction repeats verbatim at :192 (with its require.Error at :187). Dropping the && err == nil conjunct makes both assertions say what their comment claims. The general shape -- a boolean conjunct that a preceding require has already fixed -- looks statically detectable in the same way the other modes are. (audit finding A16-012)
Found by CodeRabbit on PR LeanerCloud/cloud-commitments-cli#1750, which fixed the one live instance. Filed because the detection is not cheap and PR LeanerCloud/cloud-commitments-cli#1750's claim has been narrowed to match.
The mode
A mock assertion placed before the call under test passes for any implementation:
This is independent of matcher arity, so it survives every repair LeanerCloud/cloud-commitments-cli#1595 and LeanerCloud/cloud-commitments-cli#1740 made. It is a fourth structural cause alongside:
mock.Called(fix(test): MockConfigStore isExpected short-circuit makes 20 AssertNotCalled assertions unfailable cloud-commitments-cli#1595,MockConfigStoreonly)Demonstrated on the one live instance, with the call tolerated so the assertion rather than testify's panic decides:
ok— passes silentlyWhy
TestNoUnfailableMockAssertionsdoes not catch itThe guard compares matcher count against the method's
m.Calledarity. It has no notion of "the call under test", and inferring one is the hard part — any call in the test could be it, or none could.A prototype detector was written and run: for each assertion, report any later call in the same scope that is not itself an assertion or test scaffolding. Refinements applied: innermost-scope resolution so sibling
t.Runsubtests do not count, and skippingt.Cleanupbodies since they execute after the test returns.Result across the files PR LeanerCloud/cloud-commitments-cli#1750 touched: 10 findings, 1 true positive, 9 false positives. The false positives are calls appearing as arguments to other assertions (
assert.False(t, scheduler.collecting.Load())) and assertions inside subtests whose enclosing scope contains later unrelated calls.A check at that ratio is worse than no check — it trains readers to ignore it, and a guard that is ignored gets deleted. That is the same failure direction the whole LeanerCloud/cloud-commitments-cli#1595/#1740 line of work exists to avoid, so it was not merged into the guard.
What would make it tractable
Some combination of:
AssertNotCalledon a mock with no recorded interaction anywhere earlier in the scope — narrower, far fewer false positives, and it would have caught the live instance.go vet-style analyzer witherrors.As-grade type information rather than a syntactic pass.The second option looks most promising and may be cheap. It is not attempted here because LeanerCloud/cloud-commitments-cli#1750 was already blocked on three other findings.
Meanwhile
Reviewers should check ordering by eye on any
AssertNotCalled. The rule is simply: the assertion belongs after the code under test, and a negative assertion sitting above the call is always wrong.Related
Findings from the 2026-09-02 codebase audit
Added by an automated audit of
3c0f8ac94048a2c36fce5ccddee54e6c4849a5cd(tip oforigin/main). Each item below was reported by one reviewer and independently confirmed by a second that did not write it. Full report:docs/audits/codebase-audit-2026-09-02.md.A15-004 (medium)
A second gap in the same guard, structural rather than a new vacuity mode.
TestNoUnfailableMockAssertionswalks the repo and then per directory doesmocks := collectMocks(files); if len(mocks) == 0 { continue }(internal/mocks/vacuous_assertion_guard_test.go:137). A package that uses a mock imported from elsewhere but declares none locally is dropped before its assertion sites are collected, and it is not added to theskippedslice the test errors on -- which contradicts the guard's own contract that a silent skip is the defect it exists to catch. Replaying the walk over the pinned tree, four packages with 15 assertion sites are invisible: internal/server (6), providers/azure/services/compute (4), managedredis (3), synapse (2), while the run logs "checked 162 mock assertion site(s)" and passes with zero skips reported. None of the 15 is vacuous today (each passes a matcher count equal to the realm.Calledarity), so this is a hole rather than a live unfailable assertion. Collecting assertion sites before thelen(mocks) == 0test and resolving them through the existing repo-wideglobalindex, routing anything unresolved intoskipped, closes it. (audit finding A15-004)A16-012 (low)
Another shape for this catalogue, and it has live instances. In
internal/auth/account_scope_fail_closed_test.go:74,assert.False(t, IsUnrestrictedAccess(got) && err == nil, ...)sits afterrequire.Error(t, err)at :69, which aborts the subtest whenerr == nil. By line 74err != nilholds unconditionally, so the&& err == nilconjunct is constant false and the assertion cannot fire for any value ofIsUnrestrictedAccess(got). The comment above it claims it restates the security property independently of the preceding assertions, which is the risk: a reader auditing the file sees the invariant explicitly asserted and stops looking, when the real protection isassert.Nil(t, got)on the line above. The construction repeats verbatim at :192 (with itsrequire.Errorat :187). Dropping the&& err == nilconjunct makes both assertions say what their comment claims. The general shape -- a boolean conjunct that a precedingrequirehas already fixed -- looks statically detectable in the same way the other modes are. (audit finding A16-012)