-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Forge doesn't work with multiple "vm.expectRevert" when testing free functions #3723
Comments
Forge does work with multiple contract X {
function foo(bool shouldRevert) public {
if (shouldRevert) revert();
}
}
contract Test6 is Test {
function testMultipleReverts() public {
X x = new X();
vm.expectRevert();
x.foo(true);
vm.expectRevert();
x.foo(false);
}
} Though there may still be a problem in your example, not certain so deferring to @mattsse for these questions:
|
ContextYou're right @mds1, thanks for explaining. You have helped me get to the bottom of this issue. My problem situation is that I am using free functions that can revert, e.g. the function ceil(SD59x18 x) pure returns (SD59x18 result) {
if (x.gt(MAX_WHOLE_SD59x18)) {
revert PRBMathSD59x18__CeilOverflow(x);
}
// ...
} Sample TestsI played a little with Forge and I managed to identify two scenarios starting from the following free function: function doRevert(bool shouldRevert) pure {
if (shouldRevert) {
revert();
}
} Simple RevertWorks well ✅ function testExpectRevertPasses() external {
vm.expectRevert();
doRevert(true);
}
function testExpectRevertFails() external {
doRevert(false);
} Multiple RevertsDoesn't fail when it should fail ❌ // Doesn't fail!
function testExpectRevertFails() external {
vm.expectRevert();
doRevert(true);
// The test execution doesn't reach this
vm.expectRevert();
doRevert(false);
} WorkaroundsAs I see it, there are two immediate solutions to this:
I opted for the 2nd solution for the time being, since I do not have that many inputs for the revert cases. One input per revert suffices. However, I think that this is a big footgun when testing free functions with Forge. My expectation is that free functions will become more popular with time, thanks to the introduction of global binding of What was the rationale behind making Forge look only for reverts in external calls? |
Hooking into CALLs is much easier than hooking into JUMPs, so this applies to many cheatcodes, more info in #864 and #432 and probably some other issues. FWIW I think there are a few EOF-related EIPs in consideration that should make this easier in the future. But until then unfortunately you'll have to use one of those workarounds unless @mattsse has other ideas. Though I do agree the current handling is not ideal, we probably should:
@PaulRBerg @mattsse lmk your thoughts on that Maybe also related to #1745 |
Oh, I see.
A bit of infinite recursion referencing #3723 in #3723!
Yeah, looking forward to EOF. Seems like it's scheduled to be included in Shanghai.
This would be a breaking change for many Forge users.
Actually, it is. As I said, I am testing an external function. I want the test to pass when I expect a revert and the free function reverts.
This would be useful. |
Oops, just updated to #864
To clarify I mean at the forge-level it's (afaik) not intended behavior, as shown in #864: expectRevert should only be changing the result when there are CALLs, but the above example shows that |
Oh, I see. Whatever the case, if you do end up modifying the current behavior of |
related issue: #3437 |
This code: function testMultipleReverts() public {
vm.expectRevert();
revert();
vm.expectRevert();
console2.log("Do not revert");
} Makes no sense because the optimizer will always optimize anything out that it knows is unreachable fwiw |
@brockelmore with that code snippet I have tried to simulate a real-world scenario in which multiple reverts are needed, e.g. the case of table tests for tests that expect a revert. See this related issue in my PRBMath repository: PaulRBerg/prb-math#129. |
FWIW, technically most of the test pattern usage here was actually not suppose to be allowed (i.e. There is a non-zero chance we could eventually support multiple conditional reverts at the same call depth, but not promising anything as of now (I have an MVP but its not robust & is easily broken). |
Component
Forge
Have you ensured that all of these are up to date?
What version of Foundry are you on?
forge 0.2.0 (cb925b1 2022-11-21T00:09:19.970948Z)
What command(s) is the bug in?
forge test
Operating System
macOS (Apple Silicon)
Describe the bug
Given the following test:
Forge will consider the test to be passed, even if it should be failed, because there is no second revert.
The text was updated successfully, but these errors were encountered: