-
Notifications
You must be signed in to change notification settings - Fork 264
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
Improve modifer coverage report #286
Comments
Leaving some implementation notes for a possible approach... Things to resolve:
Representation
The codechecks diff should highlight whether or not a modifier has been removed, e.g if I remove Instrumentation // pseudo-code instrumentation
modifier onlyOwner {
// Remember to exclude single branch modifier hits if there's no matching fn coverage
modifierAssertPre("contractA:methodA");
modifierAssertPre("contractB:methodC");
assertPre("ownable:onlyOwner");
require(condition);
assertPost("ownable:onlyOwner");
_;
}
function methodA() onlyOwner {
modifierAssertPost("contractA:methodA:onlyOwner");
...
}
function methodC() onlyOwner {
modifierAssertPost("contractB:methodC:onlyOwner");
} Resources |
Question: is anyone using modifiers for 'non-branch' purposes - e.g as gates which do common preparatory work or to normalize params? |
I wouldn't be surprised if anyone using modifiers for increasing certain counters? |
I thought a simple way we can implement this that plays very nicely with We can look for all instances where a modifier is applied, and then create a new modifier for each of these functions, identical to the original one.
The same logic that is used to instrument modifiers today is then applied: the only new element to add is something to map coverage of each new modifier to their callsite. We could also combine the coverage reports for all modifiers to compute the original modifier's coverage, but that might not be critical. A glaring issue of this solution is that it doesn't address modifiers being overidden. I have however never seen that feature be used, and think we might get away with only instrumenting non-virtual modifiers. |
It could be argued that the approach I just described can also be extended to regular I haven't thought about this in great detail, but think starting with just modifiers is a good idea. They are often used only for input or state validation (as opposed to functions), and providing feedback on whether a test suite exercises these checks is very useful. We'd need to figure out the issues with overrides if we intend to extend this to functions as well, however. |
Cleaning up the issues ... this is all in v0.8.x |
As of 0.5, modifers report being hit on their definition, but not at the call site. This is an issue because modifiers are mostly used to check preconditions e.g.
onlyOwner
, so not knowing if both branches of therequire
statements inside the modifiers were taken prevents developers from knowing if their test suite is thorough. For example, OpenZeppelin's Pausable isOwnable
, but its tests fail to account for this (all transactions come from theowner
account), and yet coverage is reported to be 100%.Something we'd need to solve in order to implement this is deciding which line we should assign the coverage report to. If we can't indicate a range (e.g. line 4 columns 20 to 26), I think just pointing to the function declaration would be fine for now (though some extra logic would be needed for contracts with multiple modifiers).
Regarding instrumentation, I'm not completely sure. The main difficulty lies in that modifiers can be overridden and inherited, so we can't simply inline their body at the call site. Transforming them into
internal
functions would work, but that wouldn't solve the problem of not knowing if bothrequire
branches were taken (since all we'd see is the function call, not what happened inside of it). Ideas are welcome!The text was updated successfully, but these errors were encountered: