use std::{
env,
ffi::OsString,
fs, io,
os::unix::prelude::OsStringExt,
path::PathBuf,
process::{self, Command},
};
use ansi_term::Colour;
const OUT_PATH: &str = "target/coverage";
const DEPS_PATH: &str = "target/debug/deps/";
fn main() -> io::Result<()> {
let current_dir = env::current_dir().unwrap();
let mut root = find_package_dir(&None).unwrap();
let mut deps = root.clone();
deps.push(DEPS_PATH);
root.push(OUT_PATH);
match Command::new("grcov").arg("-h").output() {
Ok(_) => {}
Err(_) => {
eprintln!(
"🚧 {0} is not installed Please install {0} to continue. See {1}.",
Colour::Yellow.italic().paint("grcov"),
Colour::Blue
.italic()
.paint("https://github.com/mozilla/grcov")
);
std::process::exit(1);
}
};
for entry in fs::read_dir(&root)? {
let entry = entry?;
let path = entry.path();
if let Some(extension) = path.extension() {
if extension == "profraw" {
fs::remove_file(&path)?;
}
}
}
let child = Command::new("cargo")
.arg("test")
.env("CARGO_INCREMENTAL", "0")
.env("RUSTFLAGS", "-Cinstrument-coverage")
.env(
"LLVM_PROFILE_FILE",
format!("{}/cargo-test-%p-%m.profraw", OUT_PATH),
)
.spawn()?;
let _ = child.wait_with_output().expect("failed to wait on child");
env::set_current_dir(root)?;
let child = Command::new("grcov")
.arg(".")
.arg("--binary-path")
.arg(&deps)
.arg("-s")
.arg(".")
.arg("-t")
.arg("html")
.arg("--branch")
.arg("--ignore-not-existing")
.arg("--ignore")
.arg("'../*'")
.arg("--ignore")
.arg("'/*'")
.arg("-o")
.arg("./output/html/")
.spawn()?;
let _ = child.wait_with_output()?;
let child = Command::new("grcov")
.arg(".")
.arg("--binary-path")
.arg(deps)
.arg("-s")
.arg(".")
.arg("-t")
.arg("lcov")
.arg("--branch")
.arg("--ignore-not-existing")
.arg("--ignore")
.arg("'../*'")
.arg("--ignore")
.arg("'/*'")
.arg("-o")
.arg("./output/coverage.lcov")
.spawn()?;
let _ = child.wait_with_output()?;
env::set_current_dir(current_dir)
}
fn find_package_dir(start_dir: &Option<PathBuf>) -> Result<PathBuf, std::io::Error> {
if let Some(dir) = start_dir {
std::env::set_current_dir(dir)?;
}
let output = process::Command::new("cargo")
.arg("locate-project")
.arg("--message-format")
.arg("plain")
.output()?;
let mut stdout = output.stdout;
stdout.pop();
let os_string = OsString::from_vec(stdout);
let mut package_root = PathBuf::from(os_string);
package_root.pop();
Ok(package_root)
}