|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: Source-based code coverage in nightly |
| 4 | +author: Tyler Mandry |
| 5 | +team: The Compiler Team <https://www.rust-lang.org/governance/teams/compiler> |
| 6 | +--- |
| 7 | + |
| 8 | + |
| 9 | +Support has landed in the nightly compiler for source-based code coverage, |
| 10 | +and we want your help testing it! |
| 11 | + |
| 12 | + |
| 13 | +# What is _source-based_ code coverage, exactly? |
| 14 | + |
| 15 | +You may already be familiar with code coverage, which shows you which lines |
| 16 | +of code execute. Code coverage is usually applied to tests to find out which |
| 17 | +code is actually being tested and which code isn’t. |
| 18 | + |
| 19 | +Nightly Rust already supports another kind of source code coverage, commonly |
| 20 | +called gcov, which relies on debug info to map from LLVM IR to lines of |
| 21 | +source code. Instrumentation is then added in the LLVM backend during code |
| 22 | +generation to count how many times each line is run. |
| 23 | + |
| 24 | +However, since LLVM doesn’t know exactly how Rust code is structured, there’s |
| 25 | +a lot lost in the translation between Rust source and LLVM IR. Line-level |
| 26 | +granularity is sometimes too coarse, and debug info can be unreliable, |
| 27 | +especially when building in release mode. The result is coverage reports that |
| 28 | +only show an approximation of what code actually executed. |
| 29 | + |
| 30 | +Source-based code coverage instrumentation happens directly in the Rust |
| 31 | +compiler. The compiler knows how to handle things down to individual |
| 32 | +branches, even within the same line. That means that things like |
| 33 | +short-circuited conditionals, closures, and match guards are all precisely |
| 34 | +counted. Counters are injected as additional code statements, so the compiler |
| 35 | +can still optimize the program without affecting the coverage results. |
| 36 | + |
| 37 | +[![Comparison of gcov and source-based coverage results][comparison-img]][comparison-img] |
| 38 | + |
| 39 | +_Above: A comparison of the gcov (left) and source-based coverage (right) |
| 40 | +results. gcov highlights skipped lines, marked with #####, while source-based |
| 41 | +coverage highlights exact regions of code that were skipped. Note that on |
| 42 | +line 30, one boolean subexpression is short-circuited. This is surfaced by |
| 43 | +source-based coverage but not gcov._ |
| 44 | + |
| 45 | +What this means is that source-based code coverage is both efficient and |
| 46 | +accurate. LLVM’s existing coverage tools ([llvm-profdata] and [llvm-cov]) |
| 47 | +generate both coverage summaries and very fine-grained code regions, helping |
| 48 | +you find gaps in your testing coverage. What you do about that is up to you! |
| 49 | + |
| 50 | +[comparison-img]: /images/inside-rust/2020-11-11-source-based-code-coverage/comparison.png |
| 51 | +[llvm-profdata]: https://llvm.org/docs/CommandGuide/llvm-profdata.html |
| 52 | +[llvm-cov]: https://llvm.org/docs/CommandGuide/llvm-cov.html |
| 53 | + |
| 54 | +# Trying it out |
| 55 | + |
| 56 | +Work on the implementation [began back in April][MCP], and [many PRs |
| 57 | +later][PRs], it’s ready for you to try. All you need is a recent nightly and |
| 58 | +a tool to read the coverage reports. |
| 59 | + |
| 60 | +Take a look at [this guide] to get started. If you spot any issues, please |
| 61 | +[report them]. It’s a huge help! |
| 62 | + |
| 63 | +Finally, if you try it out and it works well, we’d also like to hear from |
| 64 | +you! Come by the [Zulip stream] for this change or comment on the [feature |
| 65 | +request]. |
| 66 | + |
| 67 | +[MCP]: https://github.com/rust-lang/compiler-team/issues/278 |
| 68 | +[PRs]: https://github.com/rust-lang/rust/pulls?q=is%3Apr+author%3Arichkadel+is%3Aclosed+closed%3A%3C2020-11-06 |
| 69 | +[this guide]: https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/source-based-code-coverage.html |
| 70 | +[report them]: https://github.com/rust-lang/rust/issues/new/choose |
| 71 | +[Zulip stream]: https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/Implement.20LLVM-compatible.20source-based.20cod.20compiler-team.23278 |
| 72 | +[feature request]: https://github.com/rust-lang/rust/issues/34701 |
| 73 | + |
| 74 | +# Acknowledgements |
| 75 | + |
| 76 | +The implementation work was all done by Rich Kadel; thanks to him for all the |
| 77 | +amazing work he’s done. Thanks also to Wesley Wiser for helping with reviews, |
| 78 | +to Bob Wilson for lending his experience with LLVM's InstrProf coverage APIs, |
| 79 | +and to eddyb for their guidance in choosing a MIR-based approach. |
0 commit comments