Skip to content

Commit 5b1666a

Browse files
committed
Add option for generating coverage reports
Add a `--coverage` option in the `test` subcommand of the miri script. This option, when set, will generate a coverage report after running the tests. `cargo-binutils` is needed as a dependency to generate the reports.
1 parent 9045930 commit 5b1666a

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

miri-script/src/commands.rs

+40-2
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl Command {
172172
Command::Install { flags } => Self::install(flags),
173173
Command::Build { flags } => Self::build(flags),
174174
Command::Check { flags } => Self::check(flags),
175-
Command::Test { bless, flags, target } => Self::test(bless, flags, target),
175+
Command::Test { bless, flags, target, coverage } => Self::test(bless, flags, target, coverage),
176176
Command::Run { dep, verbose, many_seeds, target, edition, flags } =>
177177
Self::run(dep, verbose, many_seeds, target, edition, flags),
178178
Command::Doc { flags } => Self::doc(flags),
@@ -458,7 +458,7 @@ impl Command {
458458
Ok(())
459459
}
460460

461-
fn test(bless: bool, mut flags: Vec<String>, target: Option<String>) -> Result<()> {
461+
fn test(bless: bool, mut flags: Vec<String>, target: Option<String>, coverage: bool) -> Result<()> {
462462
let mut e = MiriEnv::new()?;
463463

464464
// Prepare a sysroot. (Also builds cargo-miri, which we need.)
@@ -468,6 +468,9 @@ impl Command {
468468
if bless {
469469
e.sh.set_var("RUSTC_BLESS", "Gesundheit");
470470
}
471+
if coverage {
472+
e.sh.set_var("RUSTFLAGS", "-C instrument-coverage");
473+
}
471474
if let Some(target) = target {
472475
// Tell the harness which target to test.
473476
e.sh.set_var("MIRI_TEST_TARGET", target);
@@ -479,6 +482,41 @@ impl Command {
479482
// Then test, and let caller control flags.
480483
// Only in root project as `cargo-miri` has no tests.
481484
e.test(".", &flags)?;
485+
486+
if coverage {
487+
Self::show_coverage_report(&e)?;
488+
}
489+
Ok(())
490+
}
491+
492+
fn show_coverage_report(e: &MiriEnv) -> Result<()> {
493+
let profraw_files: Vec<_> = std::fs::read_dir(".")?
494+
.filter_map(|r| r.ok())
495+
.map(|e| e.path())
496+
.filter(|p| p.extension().map(|e| e == "profraw").unwrap_or(false))
497+
.map(|p| p.as_os_str().to_os_string())
498+
.collect();
499+
500+
// Merge the profraw files
501+
let profraw_files_cloned= profraw_files.iter();
502+
cmd!(
503+
e.sh,
504+
"cargo-profdata -- merge -sparse {profraw_files_cloned...} -o merged.profdata"
505+
).quiet().run()?;
506+
507+
// Create the coverage report.
508+
let home = std::env::var("HOME")?;
509+
let ignored = format!("{home}/*|miri/target/*|target/debug/*|rust/deps/*");
510+
cmd!(
511+
e.sh,
512+
"cargo-cov -- report --instr-profile=merged.profdata --object target/debug/miri -ignore-filename-regex={ignored}"
513+
).run()?;
514+
515+
// Delete artifacts.
516+
cmd!(
517+
e.sh,
518+
"rm {profraw_files...} merged.profdata"
519+
).quiet().run()?;
482520
Ok(())
483521
}
484522

miri-script/src/main.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ pub enum Command {
3434
/// The cross-interpretation target.
3535
/// If none then the host is the target.
3636
target: Option<String>,
37+
/// Produce coverage report if set.
38+
coverage: bool,
3739
/// Flags that are passed through to the test harness.
3840
flags: Vec<String>,
3941
},
@@ -158,9 +160,12 @@ fn main() -> Result<()> {
158160
let mut target = None;
159161
let mut bless = false;
160162
let mut flags = Vec::new();
163+
let mut coverage = false;
161164
loop {
162165
if args.get_long_flag("bless")? {
163166
bless = true;
167+
} else if args.get_long_flag("coverage")? {
168+
coverage = true;
164169
} else if let Some(val) = args.get_long_opt("target")? {
165170
target = Some(val);
166171
} else if let Some(flag) = args.get_other() {
@@ -169,7 +174,7 @@ fn main() -> Result<()> {
169174
break;
170175
}
171176
}
172-
Command::Test { bless, flags, target }
177+
Command::Test { bless, flags, target, coverage }
173178
}
174179
Some("run") => {
175180
let mut dep = false;

0 commit comments

Comments
 (0)