Uh oh!
There was an error while loading. Please reload this page.
Delete the longhand copy of assertRejected - #97
Conversation
testRequireContractNameErrorCarriesTheName was assertRejected("sub/Foo")
written out statement for statement, on a name
testRequireContractNameRejectsPathCharacters already puts through the
helper. The name-carrying claim moves to the assertRejected docstring,
where the assertion lives and where every rejection in the suite reaches
it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>Warning Review limit reached
Next review available in:7 minutes Limit details: You’ve used all 1 included review currently available under your plan. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Uh oh!
There was an error while loading. Please reload this page.
Closes#65
What changed
testRequireContractNameErrorCarriesTheNamewasassertRejected("sub/Foo")written out longhand. Its two statements were byte-identical to the helper's
body with
namesubstituted, andtestRequireContractNameRejectsPathCharactersalready puts that exact string through the helper on its first line. Deleted.
The claim it carried — that the revert carries the rejected name — is a property
of
assertRejected, so it now sits in that helper's docstring, where the checkactually lives. Every one of the suite's rejections goes through the helper, so
the claim is now stated once and asserted everywhere instead of stated once and
asserted twice in the same place.
Nothing in
src/changed.The issue's proposed fix
Followed as written (delete the test, move the claim to the
assertRejecteddocstring). One correction to the issue's framing: it locates the file at
test/src/lib/LibCodeGen.requireContractName.t.sol, which is where PR #56 willput it. #56 is still open, so this branch edits
test/lib/— the path onmaintoday. Whichever of the two lands second takes a rename-vs-edit merge, which is
a merge git resolves.
Evidence: a deletion needs the opposite of a failing test
There is no test that reproduces "this test is redundant" — redundancy is a
property of the suite, not of the code under test. The check that actually
settles it is the mutation run: if the deleted test killed a mutant nothing else
kills, the mutant survives after the deletion. So the mutation matrix below is
the whole proof, run before and after the change, and the failing-before /
passing-after shape is inverted: the mutants fail before and after, and what
must not change is which tests catch them.
Baseline, unmutated
M1 —
revert InvalidContractName(name)→revert InvalidContractName("")(src/lib/LibCodeGen.sol:52)This is the mutant the deleted test existed to catch: the rejection stops
carrying the name.
Before the change, 15 tests in the suite, 10 kill it:
The two
sub/Foolines are the finding, printed by the compiler: the deletedtest and
testRequireContractNameRejectsPathCharactersfail on the same inputwith the same message.
After the change, 14 tests, 9 kill it — the same set minus the deleted one:
10 killers → 9 killers, count of tests 15 → 14. No mutant moved from killed to
survived, and
sub/Foois still caught.M2 —
revert InvalidContractName(name)→revert CodelessInstance(address(0))(same line)The deleted test also asserted the selector, so the selector axis gets its own
mutant. After the change, 9 of 14 kill it, the same 9:
Why the matrix is exhaustive, not just two samples
The deleted body was
and
assertRejected's body is the same two statements withnamein place ofthe literal.
testRequireContractNameRejectsPathCharacters:100callsassertRejected("sub/Foo"). Same call, same assertion, same argument, so theset of mutants the deleted test could kill is equal by construction to a
subset of what line 100 kills — there is no mutant to search for. M1 and M2
exercise the two axes the assertion has (error argument, selector) and confirm
the construction empirically.
The three
runs: 0fuzz entries are fuzzers failing on their first case, notzero-match filters: the suite compiled (
Compiling 3 files with Solc 0.8.25,Compiler run successful), ran 14/15 tests, and reported 5 passing alongsidethe failures. A harness error would have reported neither.
QA
testRequireContractNameRejectsPathCharacters— the surviving owner of the deleted test's claim. It fails on base under both mutants below, on the same"sub/Foo"input and with the same message the deleted test produced ([FAIL: Error != expected error: InvalidContractName("") != InvalidContractName("sub/Foo")]), verified by editingsrc/lib/LibCodeGen.sol:52and re-runningnix develop -c forge test --match-contract LibCodeGenRequireContractNameTest. No test was added: this diff deletes a duplicate, so the discriminating test it needs is the one that already existed.src/lib/LibCodeGen.sol:52revert InvalidContractName(name)->revert InvalidContractName("")-> killed by 10 of 15 tests before the change and 9 of 14 after (Suite result: FAILED. 5 passed; 10 failed->Suite result: FAILED. 5 passed; 9 failed), the same killers minus the deleted test.src/lib/LibCodeGen.sol:52revert InvalidContractName(name)->revert CodelessInstance(address(0))-> killed by 9 of 14 after the change (Suite result: FAILED. 5 passed; 9 failed), same killer set, covering the selector half of the assertion. Nothing moved from killed to survived. Both mutants restored withgit checkout -- src/lib/LibCodeGen.sol; the diff touches nosrc/file.assertRejected's body with"sub/Foo"substituted forname, andtestRequireContractNameRejectsPathCharacters:100callsassertRejected("sub/Foo")— identical call, assertion and argument, so the mutants the deleted test can kill are equal by construction to a subset of what line 100 kills. Empirically, the killer counts above went 15 tests / 10 killers -> 14 tests / 9 killers with no survivor appearing.testRequireContractNameErrorCarriesTheNamehand-rolls theassertRejectedhelper next to it #65 asks for two things — deletetestRequireContractNameErrorCarriesTheName, and put the name-carrying claim in theassertRejecteddocstring where the check lives. Covered both; there is no third item, and nothing insrc/or in the sibling audit issues' files was touched.nix develop -c forge testis134 tests passed, 0 failed, 0 skippedon unmutated base and133 tests passed, 0 failed, 0 skippedafter — exactly the one deleted test fewer, no other result moved.nix develop -c forge fmt --checkexits 0 with no diff.