-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Improve precision of code coverage and add report to CI #954
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
base: master
Are you sure you want to change the base?
Improve precision of code coverage and add report to CI #954
Conversation
The coverage reports are linked in the Cirrus web interface, e.g., from https://cirrus-ci.com/task/4981579249352704. Here's a direct link for reference: https://api.cirrus-ci.com/v1/artifact/task/4981579249352704/coverage_report/index.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice, concept ACK.
this shows some unreachable verify_check branches as uncovered.
Good catch. This seems to be a consequence of the commit that silences the unused variable warnings. Not sure if there's a way to achieve both, but if not it would indeed be better to avoid false reporting.
Yes, this is just a bug in this commit, I'll update. |
9447601
to
0965b2f
Compare
Okay, updated. Now this suppresses the evaluation of the conditions in VERIFY_CHECK, which avoids the We can't do the same for CHECK because we have a lot of CHECKs with side-effects. That is the false positive rate for the branch coverage in Nevertheless, this exposes a minor bug in the tests, where the "then" branch here is never taken for |
/* Do nothing in coverage mode but try to stay syntactically correct. | ||
This suppresses a lot of implicit branches introduced by shortcutting | ||
operators at the cost of not being side-effect safe in coverage mode. | ||
We rely on the compiler to eliminate the if (0) statement entirely. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what GCC does. I can't really test with clang because the coverage report is empty, even though it should work with clang too when passing --gcov-executable="llvm-cov gcov"
to gcovr. No idea what's wrong or if this is a bug somewhere in the tools.
0965b2f
to
6b8dd8a
Compare
In case anyone is wondering (I was): gcovr correctly collects data from multiple binaries and merges the data, i.e., it's okay to run (But I pushed again to avoid exposing the raw gcov files in CI. I think those are just properly merged and anyway not very useful). Conceptually gcovr also supports merging results from multiple compilations with different options (e.g., WIDEMUL) using the |
#if defined(COVERAGE) | ||
/* Don't abort in coverage mode. | ||
This avoids branches which are not expected to be taken. | ||
We still use cond as usual to avoid unused variable warnings. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/unused variable/unused return values/
(or actually both, but the "unused variables" can be suppressed by casting to void
, which would the thing most people would expect.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps also note that this works because an if statement with an empty consequent is not treated as a branch.
#if defined(COVERAGE) | ||
/* Do nothing in COVERAGE mode. This will make the compiler optimize away the actual branch, | ||
and we get useful branch coverage within our test files. */ | ||
#define TEST_FAILURE(msg) | ||
#elif defined(DETERMINISTIC) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be unnecessary now that the definition of CHECK is changed.
#if defined(COVERAGE) | ||
/* Don't abort in coverage mode. | ||
This avoids branches which are not expected to be taken. | ||
We still use cond as usual to avoid unused variable warnings. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps also note that this works because an if statement with an empty consequent is not treated as a branch.
I still need to update this but let me note that #959 is a nice example of why we want to test branch coverage even in the tests. Although for this specific case and this broken line, the report here doesn't show a branch at all... I suspect the branch is optimized away with an optimization so "trivial" that is not even disabled at |
Further note: Having a separate report for the cttime tests is helpful for checking that all public branches are covered: Valgrind will complain on an executed branch on secret data but not if that secret branch is never reached due to an earlier branch on public data. |
There's a bug on current master which would have been caught by this PR, see https://gnusha.org/secp256k1/2021-09-22.log for details. 20abd52#diff-c2d5f1f7616875ab71cd41b053cfb428696988ff89642b931a0963d50f34f7e8R3438-R3439 |
I should rework this for GitHub Actions. https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/ will be useful. |
No description provided.