From 6ce7b5b1694475d443585d0cf283094e2a4c9ac0 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 26 Aug 2021 20:33:31 +0900 Subject: [PATCH] Set cfg(coverage) to easily use #[no_coverage] --- CHANGELOG.md | 2 + README.md | 18 + src/main.rs | 6 +- tests/auxiliary/json.rs | 2 +- .../no_coverage/no_coverage.full.json | 625 ++++++++++++++++++ .../no_coverage.hide-instantiations.txt | 43 ++ .../no_coverage/no_coverage.json | 71 ++ .../no_coverage/no_coverage.lcov.info | 8 + .../no_coverage/no_coverage.summary.txt | 5 + .../no_coverage/no_coverage.txt | 43 ++ tests/fixtures/crates/no_coverage/Cargo.toml | 5 + tests/fixtures/crates/no_coverage/src/lib.rs | 43 ++ tests/test.rs | 5 + 13 files changed, 871 insertions(+), 5 deletions(-) create mode 100644 tests/fixtures/coverage-reports/no_coverage/no_coverage.full.json create mode 100644 tests/fixtures/coverage-reports/no_coverage/no_coverage.hide-instantiations.txt create mode 100644 tests/fixtures/coverage-reports/no_coverage/no_coverage.json create mode 100644 tests/fixtures/coverage-reports/no_coverage/no_coverage.lcov.info create mode 100644 tests/fixtures/coverage-reports/no_coverage/no_coverage.summary.txt create mode 100644 tests/fixtures/coverage-reports/no_coverage/no_coverage.txt create mode 100644 tests/fixtures/crates/no_coverage/Cargo.toml create mode 100644 tests/fixtures/crates/no_coverage/src/lib.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d996f58..2135e5ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com ## [Unreleased] +- Set `cfg(coverage)` to easily use `#[no_coverage]`. + - [Add `--quiet`, `--doc`, and `--jobs` options.](https://github.com/taiki-e/cargo-llvm-cov/pull/70) ## [0.1.1] - 2021-08-25 diff --git a/README.md b/README.md index a4aeb314..78a07303 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ This is a wrapper around rustc [`-Z instrument-coverage`][instrument-coverage] a - [Usage](#usage) - [Continuous Integration](#continuous-integration) + - [Exclude function from coverage](#exclude-function-from-coverage) - [Installation](#installation) - [Known limitations](#known-limitations) - [License](#license) @@ -269,6 +270,7 @@ cargo llvm-cov --no-report --features b cargo llvm-cov --no-run --lcov ``` + ### Continuous Integration Here is an example of GitHub Actions workflow that uploads coverage to [Codecov]. @@ -299,6 +301,21 @@ jobs: **NOTE:** Currently, only line coverage is available on Codecov. This is because `-Z instrument-coverage` does not support branch coverage and Codecov does not support region coverage. See also [#8], [#12], and [#20]. +### Exclude function from coverage + +To exclude the specific function from coverage, use the [`#[no_coverage]` attribute][rust-lang/rust#84605]. + +Since `#[no_coverage]` is unstable, it is recommended to use it together with `cfg(coverage)` set by cargo-llvm-cov. + +```rust +#![cfg_attr(coverage, feature(no_coverage))] + +#[cfg_attr(coverage, no_coverage)] +fn exclude_from_coverage() { + // ... +} +``` + ## Installation @@ -357,6 +374,7 @@ See also [the code-coverage-related issues reported in rust-lang/rust](https://g [instrument-coverage]: https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/instrument-coverage.html [rust-lang/rust#79417]: https://github.com/rust-lang/rust/issues/79417 [rust-lang/rust#79649]: https://github.com/rust-lang/rust/issues/79649 +[rust-lang/rust#84605]: https://github.com/rust-lang/rust/issues/84605 [rust-lang/rust#86177]: https://github.com/rust-lang/rust/issues/86177 ## License diff --git a/src/main.rs b/src/main.rs index 88885f43..20c9ccbe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -115,11 +115,9 @@ fn run_test(cx: &Context) -> Result<()> { let llvm_profile_file = cx.target_dir.join(format!("{}-%m.profraw", cx.package_name)); let rustflags = &mut cx.env.rustflags.clone().unwrap_or_default(); + rustflags.push(" -Z instrument-coverage --cfg coverage"); // --remap-path-prefix is needed because sometimes macros are displayed with absolute path - rustflags.push(format!( - " -Z instrument-coverage --remap-path-prefix {}/=", - cx.metadata.workspace_root - )); + rustflags.push(format!(" --remap-path-prefix {}/=", cx.metadata.workspace_root)); if cx.target.is_none() { rustflags.push(" --cfg trybuild_no_target"); } diff --git a/tests/auxiliary/json.rs b/tests/auxiliary/json.rs index eb2ecc3c..51e02ede 100644 --- a/tests/auxiliary/json.rs +++ b/tests/auxiliary/json.rs @@ -146,7 +146,7 @@ mod tests { .unwrap() .filter_map(Result::ok) .collect(); - assert_eq!(files.len(), 38); + assert_eq!(files.len(), 40); for file in files { let s = fs::read_to_string(file).unwrap(); diff --git a/tests/fixtures/coverage-reports/no_coverage/no_coverage.full.json b/tests/fixtures/coverage-reports/no_coverage/no_coverage.full.json new file mode 100644 index 00000000..67e9e69a --- /dev/null +++ b/tests/fixtures/coverage-reports/no_coverage/no_coverage.full.json @@ -0,0 +1,625 @@ +{ + "data": [ + { + "files": [ + { + "branches": [], + "expansions": [], + "filename": "src/lib.rs", + "segments": [ + [ + 1, + 0, + 1, + true, + true, + false + ], + [ + 1, + 1, + 0, + false, + false, + false + ], + [ + 3, + 1, + 1, + true, + true, + false + ], + [ + 4, + 12, + 0, + false, + false, + false + ], + [ + 5, + 14, + 1, + true, + true, + false + ], + [ + 5, + 16, + 0, + false, + false, + false + ], + [ + 6, + 14, + 0, + true, + true, + false + ], + [ + 6, + 16, + 0, + false, + false, + false + ], + [ + 7, + 14, + 0, + true, + true, + false + ], + [ + 7, + 16, + 0, + false, + false, + false + ], + [ + 8, + 14, + 0, + true, + true, + false + ], + [ + 8, + 16, + 0, + false, + false, + false + ], + [ + 9, + 14, + 0, + true, + true, + false + ], + [ + 9, + 16, + 0, + false, + false, + false + ], + [ + 11, + 1, + 1, + true, + true, + false + ], + [ + 11, + 2, + 0, + false, + false, + false + ], + [ + 14, + 1, + 1, + true, + true, + false + ], + [ + 14, + 8, + 0, + false, + false, + false + ], + [ + 24, + 1, + 1, + true, + true, + false + ], + [ + 24, + 8, + 0, + false, + false, + false + ], + [ + 25, + 1, + 1, + true, + true, + false + ], + [ + 26, + 13, + 0, + false, + false, + false + ], + [ + 26, + 14, + 0, + true, + true, + false + ], + [ + 29, + 6, + 1, + true, + true, + false + ], + [ + 29, + 7, + 0, + false, + false, + false + ], + [ + 30, + 1, + 1, + true, + true, + false + ], + [ + 30, + 2, + 0, + false, + false, + false + ], + [ + 37, + 5, + 1, + true, + true, + false + ], + [ + 37, + 12, + 0, + false, + false, + false + ], + [ + 38, + 5, + 1, + true, + true, + false + ], + [ + 39, + 17, + 0, + false, + false, + false + ], + [ + 39, + 18, + 0, + true, + true, + false + ], + [ + 41, + 10, + 1, + true, + true, + false + ], + [ + 41, + 11, + 0, + false, + false, + false + ], + [ + 42, + 5, + 1, + true, + true, + false + ], + [ + 42, + 6, + 0, + false, + false, + false + ] + ], + "summary": { + "branches": { + "count": 0, + "covered": 0, + "notcovered": 0, + "percent": 0.0 + }, + "functions": { + "count": 7, + "covered": 7, + "percent": 100.0 + }, + "instantiations": { + "count": 7, + "covered": 7, + "percent": 100.0 + }, + "lines": { + "count": 23, + "covered": 16, + "percent": 69.56521739130434 + }, + "regions": { + "count": 19, + "covered": 13, + "notcovered": 6, + "percent": 68.42105263157895 + } + } + } + ], + "functions": [ + { + "branches": [], + "count": 1, + "filenames": [ + "src/lib.rs" + ], + "name": "no_coverage::fn_level::{closure#0}", + "regions": [ + [ + 14, + 1, + 14, + 8, + 1, + 0, + 0, + 0 + ] + ] + }, + { + "branches": [], + "count": 1, + "filenames": [ + "src/lib.rs" + ], + "name": "no_coverage::expr_level", + "regions": [ + [ + 25, + 1, + 26, + 13, + 1, + 0, + 0, + 0 + ], + [ + 26, + 14, + 29, + 6, + 0, + 0, + 0, + 0 + ], + [ + 29, + 6, + 29, + 7, + 1, + 0, + 0, + 0 + ], + [ + 30, + 1, + 30, + 2, + 1, + 0, + 0, + 0 + ] + ] + }, + { + "branches": [], + "count": 1, + "filenames": [ + "src/lib.rs" + ], + "name": "no_coverage::func", + "regions": [ + [ + 3, + 1, + 4, + 12, + 1, + 0, + 0, + 0 + ], + [ + 5, + 14, + 5, + 16, + 1, + 0, + 0, + 0 + ], + [ + 6, + 14, + 6, + 16, + 0, + 0, + 0, + 0 + ], + [ + 7, + 14, + 7, + 16, + 0, + 0, + 0, + 0 + ], + [ + 8, + 14, + 8, + 16, + 0, + 0, + 0, + 0 + ], + [ + 9, + 14, + 9, + 16, + 0, + 0, + 0, + 0 + ], + [ + 11, + 1, + 11, + 2, + 1, + 0, + 0, + 0 + ] + ] + }, + { + "branches": [], + "count": 1, + "filenames": [ + "src/lib.rs" + ], + "name": "no_coverage::main", + "regions": [ + [ + 1, + 0, + 1, + 1, + 1, + 0, + 0, + 0 + ] + ] + }, + { + "branches": [], + "count": 1, + "filenames": [ + "src/lib.rs" + ], + "name": "no_coverage::expr_level::{closure#0}", + "regions": [ + [ + 24, + 1, + 24, + 8, + 1, + 0, + 0, + 0 + ] + ] + }, + { + "branches": [], + "count": 1, + "filenames": [ + "src/lib.rs" + ], + "name": "no_coverage::mod_level::mod_level::{closure#0}", + "regions": [ + [ + 37, + 5, + 37, + 12, + 1, + 0, + 0, + 0 + ] + ] + }, + { + "branches": [], + "count": 1, + "filenames": [ + "src/lib.rs" + ], + "name": "no_coverage::mod_level::mod_level", + "regions": [ + [ + 38, + 5, + 39, + 17, + 1, + 0, + 0, + 0 + ], + [ + 39, + 18, + 41, + 10, + 0, + 0, + 0, + 0 + ], + [ + 41, + 10, + 41, + 11, + 1, + 0, + 0, + 0 + ], + [ + 42, + 5, + 42, + 6, + 1, + 0, + 0, + 0 + ] + ] + } + ], + "totals": { + "branches": { + "count": 0, + "covered": 0, + "notcovered": 0, + "percent": 0 + }, + "functions": { + "count": 7, + "covered": 7, + "percent": 100 + }, + "instantiations": { + "count": 7, + "covered": 7, + "percent": 100 + }, + "lines": { + "count": 23, + "covered": 16, + "percent": 69.56521739130434 + }, + "regions": { + "count": 19, + "covered": 13, + "notcovered": 6, + "percent": 68.42105263157895 + } + } + } + ], + "type": "llvm.coverage.json.export", + "version": "2.0.1" +} \ No newline at end of file diff --git a/tests/fixtures/coverage-reports/no_coverage/no_coverage.hide-instantiations.txt b/tests/fixtures/coverage-reports/no_coverage/no_coverage.hide-instantiations.txt new file mode 100644 index 00000000..8f82bc06 --- /dev/null +++ b/tests/fixtures/coverage-reports/no_coverage/no_coverage.hide-instantiations.txt @@ -0,0 +1,43 @@ + 1| 1|#![cfg_attr(coverage, feature(no_coverage))]#![cfg_attr(coverage, feature(no_coverage))] + 2| | + 3| 1|fn func(x: i32) { + 4| 1| match x { + 5| 1| 0 => {} + 6| 0| 1 => {} + 7| 0| 2 => {} + 8| 0| 3 => {} + 9| 0| _ => {} + 10| | } + 11| 1|} + 12| | + 13| |#[cfg_attr(coverage, no_coverage)] + 14| 1|#[test] + 15| |fn fn_level() { + 16| | func(0); + 17| | + 18| | if false { + 19| | func(1); + 20| | } + 21| |} + 22| | + 23| |// #[no_coverage] has no effect on expressions. + 24| 1|#[test] + 25| 1|fn expr_level() { + 26| 1| if false { + 27| 0| #[cfg_attr(coverage, no_coverage)] + 28| 0| func(2); + 29| 1| } + 30| 1|} + 31| | + 32| |// #[no_coverage] has no effect on modules. + 33| |#[cfg_attr(coverage, no_coverage)] + 34| |mod mod_level { + 35| | use super::func; + 36| | + 37| 1| #[test] + 38| 1| fn mod_level() { + 39| 1| if false { + 40| 0| func(3); + 41| 1| } + 42| 1| } + 43| |} \ No newline at end of file diff --git a/tests/fixtures/coverage-reports/no_coverage/no_coverage.json b/tests/fixtures/coverage-reports/no_coverage/no_coverage.json new file mode 100644 index 00000000..a1e66381 --- /dev/null +++ b/tests/fixtures/coverage-reports/no_coverage/no_coverage.json @@ -0,0 +1,71 @@ +{ + "data": [ + { + "files": [ + { + "filename": "src/lib.rs", + "summary": { + "branches": { + "count": 0, + "covered": 0, + "notcovered": 0, + "percent": 0.0 + }, + "functions": { + "count": 7, + "covered": 7, + "percent": 100.0 + }, + "instantiations": { + "count": 7, + "covered": 7, + "percent": 100.0 + }, + "lines": { + "count": 23, + "covered": 16, + "percent": 69.56521739130434 + }, + "regions": { + "count": 19, + "covered": 13, + "notcovered": 6, + "percent": 68.42105263157895 + } + } + } + ], + "totals": { + "branches": { + "count": 0, + "covered": 0, + "notcovered": 0, + "percent": 0 + }, + "functions": { + "count": 7, + "covered": 7, + "percent": 100 + }, + "instantiations": { + "count": 7, + "covered": 7, + "percent": 100 + }, + "lines": { + "count": 23, + "covered": 16, + "percent": 69.56521739130434 + }, + "regions": { + "count": 19, + "covered": 13, + "notcovered": 6, + "percent": 68.42105263157895 + } + } + } + ], + "type": "llvm.coverage.json.export", + "version": "2.0.1" +} \ No newline at end of file diff --git a/tests/fixtures/coverage-reports/no_coverage/no_coverage.lcov.info b/tests/fixtures/coverage-reports/no_coverage/no_coverage.lcov.info new file mode 100644 index 00000000..806a7799 --- /dev/null +++ b/tests/fixtures/coverage-reports/no_coverage/no_coverage.lcov.info @@ -0,0 +1,8 @@ +SF:src/lib.rs +FNF:7 +FNH:7 +BRF:0 +BFH:0 +LF:23 +LH:16 +end_of_record \ No newline at end of file diff --git a/tests/fixtures/coverage-reports/no_coverage/no_coverage.summary.txt b/tests/fixtures/coverage-reports/no_coverage/no_coverage.summary.txt new file mode 100644 index 00000000..777d1505 --- /dev/null +++ b/tests/fixtures/coverage-reports/no_coverage/no_coverage.summary.txt @@ -0,0 +1,5 @@ +Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +src/lib.rs 19 6 68.42% 7 0 100.00% 23 7 69.57% 0 0 - +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +TOTAL 19 6 68.42% 7 0 100.00% 23 7 69.57% 0 0 - \ No newline at end of file diff --git a/tests/fixtures/coverage-reports/no_coverage/no_coverage.txt b/tests/fixtures/coverage-reports/no_coverage/no_coverage.txt new file mode 100644 index 00000000..8f82bc06 --- /dev/null +++ b/tests/fixtures/coverage-reports/no_coverage/no_coverage.txt @@ -0,0 +1,43 @@ + 1| 1|#![cfg_attr(coverage, feature(no_coverage))]#![cfg_attr(coverage, feature(no_coverage))] + 2| | + 3| 1|fn func(x: i32) { + 4| 1| match x { + 5| 1| 0 => {} + 6| 0| 1 => {} + 7| 0| 2 => {} + 8| 0| 3 => {} + 9| 0| _ => {} + 10| | } + 11| 1|} + 12| | + 13| |#[cfg_attr(coverage, no_coverage)] + 14| 1|#[test] + 15| |fn fn_level() { + 16| | func(0); + 17| | + 18| | if false { + 19| | func(1); + 20| | } + 21| |} + 22| | + 23| |// #[no_coverage] has no effect on expressions. + 24| 1|#[test] + 25| 1|fn expr_level() { + 26| 1| if false { + 27| 0| #[cfg_attr(coverage, no_coverage)] + 28| 0| func(2); + 29| 1| } + 30| 1|} + 31| | + 32| |// #[no_coverage] has no effect on modules. + 33| |#[cfg_attr(coverage, no_coverage)] + 34| |mod mod_level { + 35| | use super::func; + 36| | + 37| 1| #[test] + 38| 1| fn mod_level() { + 39| 1| if false { + 40| 0| func(3); + 41| 1| } + 42| 1| } + 43| |} \ No newline at end of file diff --git a/tests/fixtures/crates/no_coverage/Cargo.toml b/tests/fixtures/crates/no_coverage/Cargo.toml new file mode 100644 index 00000000..c1bd0451 --- /dev/null +++ b/tests/fixtures/crates/no_coverage/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "no_coverage" +version = "0.0.0" + +[workspace] diff --git a/tests/fixtures/crates/no_coverage/src/lib.rs b/tests/fixtures/crates/no_coverage/src/lib.rs new file mode 100644 index 00000000..e12b6095 --- /dev/null +++ b/tests/fixtures/crates/no_coverage/src/lib.rs @@ -0,0 +1,43 @@ +#![cfg_attr(coverage, feature(no_coverage))] + +fn func(x: i32) { + match x { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + _ => {} + } +} + +#[cfg_attr(coverage, no_coverage)] +#[test] +fn fn_level() { + func(0); + + if false { + func(1); + } +} + +// #[no_coverage] has no effect on expressions. +#[test] +fn expr_level() { + if false { + #[cfg_attr(coverage, no_coverage)] + func(2); + } +} + +// #[no_coverage] has no effect on modules. +#[cfg_attr(coverage, no_coverage)] +mod mod_level { + use super::func; + + #[test] + fn mod_level() { + if false { + func(3); + } + } +} diff --git a/tests/test.rs b/tests/test.rs index 6ba099e7..1f652e7c 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -73,6 +73,11 @@ fn cargo_config() { run("cargo_config_toml", "cargo_config_toml", &[]); } +#[test] +fn no_coverage() { + run("no_coverage", "no_coverage", &[]); +} + #[test] fn merge() { let model = "merge";