use std::path::Path;
use std::process::{Command, Output};
use crate::{combined_output, init_git_with_initial_commit};
fn write_lib_bin_collision(dir: &Path) {
std::fs::write(
dir.join("Cargo.toml"),
r#"[package]
name = "wt_perf_collide"
version = "0.1.0"
edition = "2021"
[lib]
name = "wt_perf"
path = "src/lib.rs"
[[bin]]
name = "wt-perf"
path = "src/main.rs"
"#,
)
.unwrap();
std::fs::write(dir.join(".gitignore"), "/target\n/Cargo.lock\n").unwrap();
let src = dir.join("src");
std::fs::create_dir_all(&src).unwrap();
std::fs::write(
src.join("lib.rs"),
r#"pub fn double(x: i32) -> i32 { x * 2 }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lib_test_double() {
assert_eq!(double(3), 6);
}
}
"#,
)
.unwrap();
std::fs::write(
src.join("main.rs"),
r#"fn main() {
println!("{}", wt_perf::double(21));
}
#[cfg(test)]
mod tests {
#[test]
fn bin_test_invokes_lib() {
assert_eq!(wt_perf::double(7), 14);
}
}
"#,
)
.unwrap();
}
fn cargo_affected_stripped(dir: &Path, args: &[&str]) -> Output {
let bin = env!("CARGO_BIN_EXE_cargo-affected");
Command::new(bin)
.args(args)
.current_dir(dir)
.env("RUSTFLAGS", "-C debuginfo=0")
.output()
.unwrap_or_else(|e| panic!("failed to run cargo-affected: {e}"))
}
#[test]
fn lib_bin_same_basename_resolves_via_nextest_binary_id() {
let tmp = tempfile::tempdir().unwrap();
let dir = tmp.path();
write_lib_bin_collision(dir);
init_git_with_initial_commit(dir);
let collect = cargo_affected_stripped(dir, &["affected", "collect"]);
let stderr = String::from_utf8_lossy(&collect.stderr);
assert!(
collect.status.success(),
"collect failed: stderr=\n{stderr}\nstdout=\n{}",
String::from_utf8_lossy(&collect.stdout)
);
assert!(
!stderr.contains("failed to resolve binary_id"),
"shim must not bail on lib+bin same-basename: stderr=\n{stderr}",
);
assert!(
!stderr.contains("basename fallback ambiguous"),
"marker probe must disambiguate lib+bin: stderr=\n{stderr}",
);
let db = dir.join("target/affected/coverage.db");
let conn = rusqlite::Connection::open(&db).unwrap();
let ids: Vec<String> = conn
.prepare("SELECT DISTINCT binary_id FROM test_regions")
.unwrap()
.query_map([], |r| r.get(0))
.unwrap()
.map(|r| r.unwrap())
.collect();
assert!(
ids.iter().any(|id| id == "wt_perf_collide"),
"expected lib binary_id in {ids:?}",
);
assert!(
ids.iter().any(|id| id == "wt_perf_collide::bin/wt-perf"),
"expected bin binary_id in {ids:?}",
);
let recollect = cargo_affected_stripped(dir, &["affected", "collect"]);
let combined = combined_output(&recollect);
assert!(
recollect.status.success(),
"second collect failed: {combined}"
);
assert!(
!combined.contains("failed to resolve binary_id"),
"second collect must not regress: {combined}",
);
}