-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
bug: expectEmit and expectCall don't only check the next call #1745
Comments
I don't think this is contradictory, but it might lead to some confusion that could be cleared up.
This is the overall usage for It then follows up:
This explains the call order: we call the cheatcode, we emit the event we expect, and then we perform a call that emits the event. It then also goes on in an info box:
This is essentially saying that if we call |
If this is not a bug, do you know what the rationale was for this behavior originally? It feels like this provides minimal UX benefits, makes tests harder to read, and introduces greater risk of testing bugs, especially for e.g. long integration tests where the event might be emitted many txs after you declared to expect it. It also deviates from other frameworks where you specify the exact call/receipt emitting the event (see waffle (used in hardhat) and brownie).
This is exactly the part of the docs that seem contradictory! 😅 Both "the next event emitted must match the one we expect" and "the second event must match the first" are not true. Ordering only matters in the sense that you must have contract MyContract {
event MyEvent();
event OtherEvent();
function noEvent() public {}
function otherEvent() public {
emit OtherEvent();
}
function myEvent() public {
emit OtherEvent();
emit MyEvent();
}
}
contract ExpectTest is Test {
event MyEvent();
MyContract myContract;
function setUp() public {
myContract = new MyContract();
}
function test_EventuallyMyEvent() public {
vm.expectEmit(true, true, true, true);
emit MyEvent();
myContract.otherEvent();
myContract.noEvent();
myContract.otherEvent();
myContract.myEvent();
}
} |
Perhaps the confusion is that it's the event data (topics + data) and not topic0 that needs to match? I.e. if I emit a
It's not a bug but I do not know the rationale, I believe |
From the description in the original PR (#329) it does sound like it was supposed to only work for the next call:
It's also possible it used to fail if not found in the next call, and a subsequent PR changed that. But yea we'll see what @brockelmore says 👍 |
Ye I believe things got switched around. I believe the reason it got changed was people seemed to like to just define a bunch of logs they expect at the beginning of the test then write the test like normal to improve readability. I.e.: function logs() internal {
vm.expectEmit(..);
emit event(..);
vm.expectEmit(..);
emit event(..);
}
function testA() public {
logs();
// do normal test stuff that likely includes multiple calls & static calls
} It may have also been because we were considering static calls in that group which was an even bigger footgun? I dont have strong preferences here, but we should filter out static calls if we change |
Component
Forge
Have you ensured that all of these are up to date?
What version of Foundry are you on?
forge 0.2.0 (4fcd7e0 2022-05-26T00:08:37.693306Z)
What command(s) is the bug in?
forge test
Operating System
No response
Describe the bug
My understanding is that the expected behavior of
expectEmit
is "look for event in the next call" but it seems to actually be "look for expected event before the end of the test". And the docs are contradictory here—one part says it must be the "next event" (which seems to imply it needs to be the first event in the next call), another part says "before the end of the current function". Similarly issue forexpectCall
behavior.To ensure tests are clear, I think
expectEmit
andexpectCall
should only look in the next call. Otherwise this can result in bugs where your event was emitted eventually in a later portion of your test, but not emitted at the time you expected it, and the test still passes.Reproduce with this test:
The text was updated successfully, but these errors were encountered: