use std::path::PathBuf;
use std::process::Command;
use std::{env, fs};
const TRUNCATED_HEADER: [u8; 8] = [0x81, b'r', b'f', b'o', b'r', b'p', b'l', 0xff];
#[test]
fn a_truncated_profile_left_by_a_killed_child_does_not_fail_the_coverage_step() {
let Some(dir) = profile_directory() else {
return;
};
let planted = dir.join("truncated-by-a-killed-child_0.profraw");
fs::write(&planted, TRUNCATED_HEADER)
.unwrap_or_else(|e| panic!("could not plant {}: {e}", planted.display()));
let profdata = llvm_profdata().unwrap_or_else(|| {
panic!(
"coverage is instrumented but llvm-profdata is neither in $LLVM_PROFDATA \
nor beside the rustc target libdir — run `rustup component add llvm-tools`"
)
});
let shown = Command::new(&profdata)
.arg("show")
.arg(&planted)
.output()
.unwrap_or_else(|e| panic!("could not run {}: {e}", profdata.display()));
assert!(
!shown.status.success(),
"the planted profile is readable, so it is not the failure condition the \
coverage step has to survive: {}",
planted.display()
);
let complaint = String::from_utf8_lossy(&shown.stderr);
assert!(
complaint.contains("file header is corrupt"),
"the planted profile fails for the wrong reason — an empty profile is \
skipped silently and proves nothing. llvm-profdata said: {}",
complaint.trim()
);
}
fn profile_directory() -> Option<PathBuf> {
let pattern = PathBuf::from(env::var_os("LLVM_PROFILE_FILE")?);
let dir = pattern.parent()?;
dir.is_dir().then(|| dir.to_path_buf())
}
fn llvm_profdata() -> Option<PathBuf> {
if let Some(explicit) = env::var_os("LLVM_PROFDATA") {
return Some(PathBuf::from(explicit));
}
let printed = Command::new("rustc")
.args(["--print", "target-libdir"])
.output()
.ok()?;
if !printed.status.success() {
return None;
}
let libdir = String::from_utf8(printed.stdout).ok()?;
let bin = PathBuf::from(libdir.trim()).parent()?.join("bin");
["llvm-profdata", "llvm-profdata.exe"]
.into_iter()
.map(|name| bin.join(name))
.find(|candidate| candidate.is_file())
}