use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::process::Command;
use octl_core::plan;
use super::git;
use super::parse::{
self, count_assert_macros, parse_cargo_stream, parse_libtest_report, reconcile_single_binary,
};
use super::snapshot::{CheckRun, ClippySnapshot, TestSnapshot};
use super::FloorError;
const ENV_ALLOWLIST: &[&str] = &[
"PATH",
"HOME",
"USER",
"LOGNAME",
"SHELL",
"TMPDIR",
"LANG",
"TERM",
"CARGO",
"CARGO_HOME",
"RUSTUP_HOME",
"RUSTUP_TOOLCHAIN",
"XDG_CACHE_HOME",
"GIT_BIN",
"LD_LIBRARY_PATH",
"DYLD_LIBRARY_PATH",
"DYLD_FALLBACK_LIBRARY_PATH",
];
pub(crate) fn isolated_command(program: &str, target_dir: Option<&Path>) -> Command {
let mut cmd = Command::new(program);
cmd.env_clear();
for key in ENV_ALLOWLIST {
if let Ok(val) = std::env::var(key) {
cmd.env(key, val);
}
}
cmd.env("LC_ALL", "C");
cmd.env("CARGO_TERM_COLOR", "never");
cmd.env("CARGO_INCREMENTAL", "0");
cmd.env("RUSTFLAGS", "");
cmd.env("RUSTDOCFLAGS", "");
cmd.env("RUSTC_WRAPPER", "");
cmd.env("RUSTC_WORKSPACE_WRAPPER", "");
if let Some(dir) = target_dir {
cmd.env("CARGO_TARGET_DIR", dir);
}
cmd
}
pub(crate) fn cargo_bin() -> String {
std::env::var("CARGO")
.ok()
.filter(|s| !s.is_empty())
.unwrap_or_else(|| "cargo".to_string())
}
fn is_cargo_token(first: &str) -> bool {
first == "cargo"
|| Path::new(first)
.file_name()
.and_then(|n| n.to_str())
.is_some_and(|n| n == "cargo")
}
const SANITIZING_CONFIG: &[&str] = &["build.rustflags=[]", "build.rustdocflags=[]"];
fn sanitizing_config_args() -> Vec<String> {
SANITIZING_CONFIG
.iter()
.flat_map(|kv| ["--config".to_string(), (*kv).to_string()])
.collect()
}
struct CargoInvocation {
program: String,
args: Vec<String>,
}
impl CargoInvocation {
fn display(&self) -> String {
let mut s = self.program.clone();
for a in &self.args {
s.push(' ');
s.push_str(a);
}
s
}
}
enum CaptureExec {
Cargo(CargoInvocation),
Shell(String),
}
impl CaptureExec {
fn display(&self) -> String {
match self {
CaptureExec::Cargo(inv) => inv.display(),
CaptureExec::Shell(s) => s.clone(),
}
}
fn command(&self, target_dir: &Path) -> Command {
match self {
CaptureExec::Cargo(inv) => {
let mut cmd = isolated_command(&inv.program, Some(target_dir));
cmd.args(&inv.args);
cmd
}
CaptureExec::Shell(s) => {
let mut cmd = isolated_command("sh", Some(target_dir));
cmd.arg("-c").arg(s);
cmd
}
}
}
}
fn build_capture_exec(base_cmd: &str, target_dir: &Path, floor_flags: &[&str]) -> CaptureExec {
if base_cmd
.split_whitespace()
.next()
.is_some_and(is_cargo_token)
{
CaptureExec::Cargo(build_cargo_invocation(base_cmd, target_dir, floor_flags))
} else {
let mut parts = vec![base_cmd.to_string()];
parts.extend(floor_flags.iter().map(ToString::to_string));
CaptureExec::Shell(parts.join(" "))
}
}
fn build_cargo_invocation(
base_cmd: &str,
target_dir: &Path,
floor_flags: &[&str],
) -> CargoInvocation {
const DROP_WITH_VALUE: &[&str] = &[
"--message-format",
"--target-dir",
"--config",
"--manifest-path",
];
let mut tokens = base_cmd.split_whitespace();
let first = tokens.next().unwrap_or("cargo");
let is_real_cargo = is_cargo_token(first);
let mut program = if is_real_cargo {
cargo_bin()
} else {
first.to_string()
};
let rest: Vec<&str> = tokens.collect();
let sep = rest.iter().position(|t| *t == "--");
let (cargo_side_raw, after_sep): (&[&str], &[&str]) = match sep {
Some(i) => (&rest[..i], &rest[i..]),
None => (&rest[..], &[]),
};
let mut cargo_side: Vec<&str> = cargo_side_raw.to_vec();
if is_real_cargo && cargo_side.first() == Some(&"clippy") {
program = Path::new(&program)
.with_file_name("cargo-clippy")
.to_string_lossy()
.into_owned();
cargo_side.remove(0);
}
let mut kept: Vec<String> = Vec::new();
let mut skip_next = false;
for tok in cargo_side {
if skip_next {
skip_next = false;
continue;
}
if DROP_WITH_VALUE.contains(&tok) {
skip_next = true;
continue;
}
if DROP_WITH_VALUE
.iter()
.any(|f| tok.strip_prefix(f).is_some_and(|r| r.starts_with('=')))
{
continue;
}
kept.push(tok.to_string());
}
let mut args: Vec<String> = Vec::new();
if is_real_cargo {
args.extend(sanitizing_config_args());
}
args.extend(kept);
args.push("--target-dir".to_string());
args.push(target_dir.to_string_lossy().into_owned());
args.extend(floor_flags.iter().map(ToString::to_string));
args.extend(after_sep.iter().map(ToString::to_string));
CargoInvocation { program, args }
}
#[must_use]
pub fn rustc_version(cwd: &Path) -> String {
isolated_command("rustc", None)
.arg("-V")
.current_dir(cwd)
.output()
.ok()
.filter(|o| o.status.success())
.map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
.filter(|s| !s.is_empty())
.unwrap_or_else(|| "unknown".to_string())
}
#[must_use]
pub fn run_check(check: &plan::Check, cwd: &Path) -> CheckRun {
let run_dir = match &check.cwd {
Some(rel) => cwd.join(rel),
None => cwd.to_path_buf(),
};
let expected = check.expect_exit.unwrap_or(0);
let output = Command::new("sh")
.arg("-c")
.arg(&check.run)
.current_dir(&run_dir)
.output();
match output {
Ok(out) => CheckRun {
desc: check.desc.clone(),
run: check.run.clone(),
cwd: check.cwd.clone(),
passed: out.status.code() == Some(expected),
exit_code: out.status.code(),
stdout: String::from_utf8_lossy(&out.stdout).into_owned(),
stderr: String::from_utf8_lossy(&out.stderr).into_owned(),
},
Err(e) => CheckRun {
desc: check.desc.clone(),
run: check.run.clone(),
cwd: check.cwd.clone(),
passed: false,
exit_code: None,
stdout: String::new(),
stderr: format!("failed to spawn check in {}: {e}", run_dir.display()),
},
}
}
#[must_use]
pub fn run_checks(checks: &[plan::Check], cwd: &Path) -> Vec<CheckRun> {
checks.iter().map(|c| run_check(c, cwd)).collect()
}
pub fn capture_test_snapshot(
test_cmd: &str,
cwd: &Path,
target_dir: &Path,
) -> Result<TestSnapshot, FloorError> {
let exec = build_capture_exec(test_cmd, target_dir, &["--no-run", "--message-format=json"]);
let enumerate_cmd = exec.display();
let out = exec
.command(target_dir)
.current_dir(cwd)
.output()
.map_err(|e| FloorError::Capture {
what: "tests",
message: format!("could not run `{enumerate_cmd}`: {e}"),
})?;
let stdout = String::from_utf8_lossy(&out.stdout);
let messages = parse_cargo_stream(&stdout).map_err(|e| FloorError::Capture {
what: "tests",
message: format!("test enumeration produced unparseable cargo output: {e}"),
})?;
if parse::has_compile_error(&messages) {
return Err(FloorError::Capture {
what: "tests",
message: "test build reported a compile error; refusing an empty/partial snapshot"
.into(),
});
}
match parse::build_finished(&messages) {
Some(true) => {}
Some(false) => {
return Err(FloorError::Capture {
what: "tests",
message: format!(
"`{enumerate_cmd}` reported build failure (exit {:?}); failing closed",
out.status.code()
),
});
}
None => {
return Err(FloorError::Capture {
what: "tests",
message: format!(
"`{enumerate_cmd}` produced no build-finished record (truncated?); failing closed. stderr: {}",
String::from_utf8_lossy(&out.stderr).trim()
),
});
}
}
if !out.status.success() {
return Err(FloorError::Capture {
what: "tests",
message: format!(
"`{enumerate_cmd}` exited {:?} despite a build-finished record (killed/truncated?); failing closed",
out.status.code()
),
});
}
let binaries = parse::test_binaries(&messages);
let mut snap = TestSnapshot {
targets: binaries
.iter()
.map(|b| format!("{}/{}/{}", b.package, b.target_kind, b.target))
.collect(),
..Default::default()
};
for bin in &binaries {
run_one_test_binary(bin, cwd, target_dir, &mut snap)?;
}
Ok(snap)
}
fn run_one_test_binary(
bin: &parse::TestBinary,
cwd: &Path,
target_dir: &Path,
snap: &mut TestSnapshot,
) -> Result<(), FloorError> {
let out = isolated_command(&bin.executable, Some(target_dir))
.current_dir(cwd)
.output()
.map_err(|e| FloorError::Capture {
what: "tests",
message: format!("could not run test binary {}: {e}", bin.executable),
})?;
let combined = join_streams(&out.stdout, &out.stderr);
let report = parse_libtest_report(&combined);
let summary = reconcile_single_binary(&report).map_err(|d| FloorError::Capture {
what: "tests",
message: format!(
"test binary {} ({}/{}): untrustworthy output: {d}",
bin.executable, bin.target_kind, bin.target
),
})?;
let exit_ok = out.status.code() == Some(0);
if exit_ok != (summary.failed == 0) {
return Err(FloorError::Capture {
what: "tests",
message: format!(
"test binary {} exit code {:?} inconsistent with summary ({} failed); failing closed",
bin.executable,
out.status.code(),
summary.failed
),
});
}
snap.passed.extend(parse::qualify(
&bin.package,
&bin.target_kind,
&bin.target,
&report.passed,
));
snap.failed.extend(parse::qualify(
&bin.package,
&bin.target_kind,
&bin.target,
&report.failed,
));
snap.ignored.extend(parse::qualify(
&bin.package,
&bin.target_kind,
&bin.target,
&report.ignored,
));
Ok(())
}
pub fn capture_doctests(
cwd: &Path,
target_dir: &Path,
meta: &super::metadata::WorkspaceMetadata,
snap: &mut TestSnapshot,
) -> Result<(), FloorError> {
for pkg in &meta.packages {
let Some(lib) = super::metadata::lib_target_name(pkg) else {
continue; };
let exec = build_capture_exec(
&format!("cargo test -p {} --doc", pkg.name),
target_dir,
&[],
);
let cmd = exec.display();
let out = exec
.command(target_dir)
.current_dir(cwd)
.output()
.map_err(|e| FloorError::Capture {
what: "tests",
message: format!("could not run doctests via `{cmd}`: {e}"),
})?;
let combined = join_streams(&out.stdout, &out.stderr);
let report = parse_libtest_report(&combined);
let summary = reconcile_single_binary(&report).map_err(|d| FloorError::Capture {
what: "tests",
message: format!(
"doctests for package {} ({}): untrustworthy output: {d}. stderr: {}",
pkg.name,
lib,
String::from_utf8_lossy(&out.stderr).trim()
),
})?;
let exit_ok = out.status.code() == Some(0);
if exit_ok != (summary.failed == 0) {
return Err(FloorError::Capture {
what: "tests",
message: format!(
"doctests for package {} exit code {:?} inconsistent with summary ({} failed); failing closed",
pkg.name,
out.status.code(),
summary.failed
),
});
}
snap.targets.insert(format!("{}/doctest/{}", pkg.name, lib));
snap.passed
.extend(parse::qualify(&pkg.name, "doctest", &lib, &report.passed));
snap.failed
.extend(parse::qualify(&pkg.name, "doctest", &lib, &report.failed));
snap.ignored
.extend(parse::qualify(&pkg.name, "doctest", &lib, &report.ignored));
}
Ok(())
}
pub fn capture_clippy_snapshot(
clippy_cmd: &str,
cwd: &Path,
target_dir: &Path,
) -> Result<ClippySnapshot, FloorError> {
let exec = build_capture_exec(clippy_cmd, target_dir, &["--message-format=json"]);
let cmd = exec.display();
let out = exec
.command(target_dir)
.current_dir(cwd)
.output()
.map_err(|e| FloorError::Capture {
what: "clippy",
message: format!("could not run `{cmd}`: {e}"),
})?;
let stdout = String::from_utf8_lossy(&out.stdout);
let messages = parse_cargo_stream(&stdout).map_err(|e| FloorError::Capture {
what: "clippy",
message: format!("clippy produced unparseable cargo output: {e}"),
})?;
if parse::has_compile_error(&messages) {
return Err(FloorError::Capture {
what: "clippy",
message: "clippy reported an error-level diagnostic; refusing a partial warning set"
.into(),
});
}
if parse::build_finished(&messages).is_none() {
return Err(FloorError::Capture {
what: "clippy",
message: format!(
"`{cmd}` produced no build-finished record (truncated?); failing closed. stderr: {}",
String::from_utf8_lossy(&out.stderr).trim()
),
});
}
if !out.status.success() {
return Err(FloorError::Capture {
what: "clippy",
message: format!(
"`{cmd}` exited {:?} despite a build-finished record (killed/failed?); failing closed",
out.status.code()
),
});
}
Ok(ClippySnapshot {
warnings: parse::clippy_warnings(&messages),
})
}
fn join_streams(first: &[u8], second: &[u8]) -> String {
let mut combined = String::from_utf8_lossy(first).into_owned();
if !combined.is_empty() && !combined.ends_with('\n') {
combined.push('\n');
}
combined.push_str(&String::from_utf8_lossy(second));
combined
}
#[must_use]
pub fn assertion_counts_on_disk(cwd: &Path, files: &[PathBuf]) -> BTreeMap<PathBuf, usize> {
files
.iter()
.map(|f| {
let count = std::fs::read_to_string(cwd.join(f)).map_or(0, |s| count_assert_macros(&s));
(f.clone(), count)
})
.collect()
}
pub fn assertion_counts_at_ref(
repo: &Path,
r#ref: &str,
files: &[PathBuf],
) -> Result<BTreeMap<PathBuf, usize>, FloorError> {
let commit = git::resolve_commit(repo, r#ref)?;
let mut counts = BTreeMap::new();
for f in files {
if let Some(content) = git::file_at_ref(repo, &commit, f)? {
counts.insert(f.clone(), count_assert_macros(&content));
}
}
Ok(counts)
}
#[cfg(test)]
mod tests {
use super::*;
use std::os::unix::fs::PermissionsExt;
use tempfile::TempDir;
fn check(desc: &str, run: &str) -> plan::Check {
plan::Check {
desc: desc.to_string(),
run: run.to_string(),
cwd: None,
expect_exit: None,
extra: serde_json::Map::new(),
}
}
fn write_script(dir: &Path, name: &str, body: &str) -> String {
let path = dir.join(name);
std::fs::write(&path, body).unwrap();
let mut perms = std::fs::metadata(&path).unwrap().permissions();
perms.set_mode(0o755);
std::fs::set_permissions(&path, perms).unwrap();
path.to_string_lossy().into_owned()
}
#[test]
fn run_check_captures_pass_and_fail() {
let dir = TempDir::new().unwrap();
let pass = run_check(&check("ok", "exit 0"), dir.path());
assert!(pass.passed);
assert_eq!(pass.exit_code, Some(0));
let fail = run_check(&check("bad", "exit 3"), dir.path());
assert!(!fail.passed);
assert_eq!(fail.exit_code, Some(3));
}
#[test]
fn run_check_honors_expect_exit_and_cwd() {
let dir = TempDir::new().unwrap();
std::fs::create_dir(dir.path().join("sub")).unwrap();
let mut c = check("runs in sub, exits 2", "exit 2");
c.cwd = Some("sub".to_string());
c.expect_exit = Some(2);
let r = run_check(&c, dir.path());
assert!(r.passed);
assert_eq!(r.cwd.as_deref(), Some("sub"));
}
#[test]
fn run_checks_preserves_order() {
let dir = TempDir::new().unwrap();
let rs = run_checks(&[check("a", "exit 0"), check("b", "exit 1")], dir.path());
assert_eq!(rs.len(), 2);
assert!(rs[0].passed);
assert!(!rs[1].passed);
}
#[test]
fn isolated_command_clears_rustflags_but_keeps_path() {
std::env::set_var("RUSTFLAGS", "--cfg poisoned");
let dir = TempDir::new().unwrap();
let out = isolated_command("sh", None)
.arg("-c")
.arg("echo \"RUSTFLAGS=[${RUSTFLAGS:-}] PATH_SET=${PATH:+yes}\"")
.current_dir(dir.path())
.output()
.unwrap();
std::env::remove_var("RUSTFLAGS");
let s = String::from_utf8_lossy(&out.stdout);
assert!(s.contains("RUSTFLAGS=[]"), "RUSTFLAGS leaked: {s}");
assert!(s.contains("PATH_SET=yes"), "PATH missing: {s}");
}
#[test]
fn build_cargo_invocation_resolves_cargo_and_injects_sanitizing_config() {
let inv = build_cargo_invocation(
"cargo test --workspace",
Path::new("/tmp/floor-td"),
&["--no-run", "--message-format=json"],
);
assert_eq!(inv.program, cargo_bin());
for kv in SANITIZING_CONFIG {
let i = inv
.args
.iter()
.position(|a| a == kv)
.expect("config present");
assert_eq!(inv.args[i - 1], "--config");
}
let sub = inv.args.iter().position(|a| a == "test").unwrap();
let td = inv.args.iter().position(|a| a == "--target-dir").unwrap();
let ws = inv.args.iter().position(|a| a == "--workspace").unwrap();
assert!(sub < ws && ws < td, "{:?}", inv.args);
assert_eq!(inv.args[td + 1], "/tmp/floor-td");
assert!(inv
.args
.ends_with(&["--no-run".to_string(), "--message-format=json".to_string()]));
}
#[test]
fn build_cargo_invocation_bypasses_clippy_alias() {
let inv = build_cargo_invocation(
"cargo clippy --workspace",
Path::new("/tmp/td"),
&["--message-format=json"],
);
assert_eq!(
Path::new(&inv.program)
.file_name()
.unwrap()
.to_str()
.unwrap(),
"cargo-clippy"
);
assert!(!inv.args.iter().any(|a| a == "clippy"), "{:?}", inv.args);
assert!(inv.args.iter().any(|a| a == "--workspace"));
assert!(inv.args.iter().any(|a| a == "build.rustflags=[]"));
}
#[test]
fn build_cargo_invocation_strips_repo_config_and_manifest_path() {
let inv = build_cargo_invocation(
"cargo test --config build.rustflags=[\"-Awarnings\"] --manifest-path /evil/Cargo.toml --workspace",
Path::new("/tmp/td"),
&["--no-run"],
);
assert!(
!inv.args.iter().any(|a| a == "/evil/Cargo.toml"),
"{:?}",
inv.args
);
for (i, a) in inv.args.iter().enumerate() {
if a == "--config" {
assert!(
SANITIZING_CONFIG.contains(&inv.args[i + 1].as_str()),
"unexpected --config {}",
inv.args[i + 1]
);
}
}
assert!(inv.args.iter().any(|a| a == "--workspace"));
}
#[test]
fn build_cargo_invocation_dangling_value_flag_before_separator() {
let inv = build_cargo_invocation(
"cargo test --message-format -- --nocapture",
Path::new("/tmp/td"),
&["--no-run"],
);
assert!(inv
.args
.ends_with(&["--".to_string(), "--nocapture".to_string()]));
}
#[test]
fn is_cargo_token_matches_bare_and_pathed_cargo() {
assert!(is_cargo_token("cargo"));
assert!(is_cargo_token("/usr/bin/cargo"));
assert!(!is_cargo_token("printf"));
assert!(!is_cargo_token("/tmp/x/fakecargo"));
}
#[test]
fn build_cargo_invocation_strips_repo_target_dir_and_message_format() {
let inv = build_cargo_invocation(
"cargo test --target-dir /evil --message-format=short --workspace -- --nocapture",
Path::new("/tmp/floor-td"),
&["--no-run", "--message-format=json"],
);
assert!(!inv.args.iter().any(|a| a == "/evil"), "{:?}", inv.args);
assert!(!inv.args.iter().any(|a| a == "--message-format=short"));
let tds: Vec<usize> = inv
.args
.iter()
.enumerate()
.filter(|(_, a)| *a == "--target-dir")
.map(|(i, _)| i)
.collect();
assert_eq!(tds.len(), 1);
assert_eq!(inv.args[tds[0] + 1], "/tmp/floor-td");
assert!(inv
.args
.ends_with(&["--".to_string(), "--nocapture".to_string()]));
let sep = inv.args.iter().position(|a| a == "--").unwrap();
let nr = inv.args.iter().position(|a| a == "--no-run").unwrap();
assert!(nr < sep, "floor flags must precede `--`: {:?}", inv.args);
}
#[test]
fn build_cargo_invocation_honours_non_cargo_program_verbatim() {
let inv = build_cargo_invocation(
"/tmp/fake-cargo clippy",
Path::new("/tmp/td"),
&["--message-format=json"],
);
assert_eq!(inv.program, "/tmp/fake-cargo");
assert!(inv.args.iter().any(|a| a == "clippy"), "{:?}", inv.args);
}
#[test]
fn clippy_capture_parses_json_and_strips_span() {
let dir = TempDir::new().unwrap();
let json = concat!(
r#"{"reason":"compiler-message","package_id":"p#pkg@0.1.0","target":{"name":"pkg","kind":["lib"]},"message":{"level":"warning","message":"unused variable: `x`","code":{"code":"unused_variables"},"spans":[{"file_name":"src/a.rs","line_start":3,"is_primary":true}]}}"#,
"\n",
r#"{"reason":"build-finished","success":true}"#,
"\n"
);
let script = write_script(
dir.path(),
"fakeclippy",
&format!("#!/bin/sh\nprintf '%s' '{json}'\n"),
);
let snap = capture_clippy_snapshot(&script, dir.path(), dir.path()).unwrap();
assert_eq!(snap.warnings.len(), 1);
let w = snap.warnings.iter().next().unwrap();
assert_eq!(w.lint, "unused_variables");
assert_eq!(w.file, "src/a.rs");
}
#[test]
fn clippy_capture_fails_closed_on_compile_error() {
let dir = TempDir::new().unwrap();
let json = concat!(
r#"{"reason":"compiler-message","package_id":"p#pkg@0.1.0","target":{"name":"pkg","kind":["lib"]},"message":{"level":"error","message":"mismatched types","code":{"code":"E0308"},"spans":[]}}"#,
"\n",
r#"{"reason":"build-finished","success":false}"#,
"\n"
);
let script = write_script(
dir.path(),
"fakeclippy",
&format!("#!/bin/sh\nprintf '%s' '{json}'\nexit 101\n"),
);
let err = capture_clippy_snapshot(&script, dir.path(), dir.path()).unwrap_err();
assert!(format!("{err}").contains("error-level diagnostic"), "{err}");
}
#[test]
fn clippy_capture_fails_closed_on_unparseable_output() {
let dir = TempDir::new().unwrap();
let script = write_script(
dir.path(),
"fakeclippy",
"#!/bin/sh\necho 'error: unknown flag'\n",
);
assert!(capture_clippy_snapshot(&script, dir.path(), dir.path()).is_err());
}
#[test]
fn test_capture_enumerates_runs_and_qualifies() {
let dir = TempDir::new().unwrap();
let libtest = write_script(
dir.path(),
"faketest",
"#!/bin/sh\nprintf 'test mymod::works ... ok\\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\\n'\n",
);
let artifact = format!(
r#"{{"reason":"compiler-artifact","package_id":"p#octl-cli@0.1.0","target":{{"name":"octl-cli","kind":["lib"]}},"profile":{{"test":true}},"executable":"{libtest}"}}"#
);
let stream = format!("{artifact}\n{{\"reason\":\"build-finished\",\"success\":true}}\n");
let cargo = write_script(
dir.path(),
"fakecargo",
&format!("#!/bin/sh\nprintf '%s' '{stream}'\n"),
);
let snap = capture_test_snapshot(&cargo, dir.path(), dir.path()).unwrap();
assert_eq!(snap.passed.len(), 1);
let id = snap.passed.iter().next().unwrap();
assert_eq!(id.package, "octl-cli");
assert_eq!(id.target_kind, "lib");
assert_eq!(id.name, "mymod::works");
assert_eq!(
snap.targets.iter().cloned().collect::<Vec<_>>(),
vec!["octl-cli/lib/octl-cli".to_string()]
);
}
#[test]
fn test_capture_rejects_forged_ok_line() {
let dir = TempDir::new().unwrap();
let libtest = write_script(
dir.path(),
"faketest",
"#!/bin/sh\nprintf 'test real::actual ... ok\\ntest forged::injected ... ok\\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\\n'\n",
);
let artifact = format!(
r#"{{"reason":"compiler-artifact","package_id":"p#pkg@0.1.0","target":{{"name":"pkg","kind":["lib"]}},"profile":{{"test":true}},"executable":"{libtest}"}}"#
);
let stream = format!("{artifact}\n{{\"reason\":\"build-finished\",\"success\":true}}\n");
let cargo = write_script(
dir.path(),
"fakecargo",
&format!("#!/bin/sh\nprintf '%s' '{stream}'\n"),
);
let err = capture_test_snapshot(&cargo, dir.path(), dir.path()).unwrap_err();
assert!(format!("{err}").contains("untrustworthy"), "{err}");
}
#[test]
fn test_capture_fails_closed_on_injected_build_finished_then_nonzero_exit() {
let dir = TempDir::new().unwrap();
let cargo = write_script(
dir.path(),
"fakecargo",
"#!/bin/sh\nprintf '%s\\n' '{\"reason\":\"build-finished\",\"success\":true}'\nexit 137\n",
);
let err = capture_test_snapshot(&cargo, dir.path(), dir.path()).unwrap_err();
assert!(format!("{err}").contains("killed/truncated"), "{err}");
}
#[test]
fn test_capture_fails_closed_on_build_failure() {
let dir = TempDir::new().unwrap();
let stream = concat!(
r#"{"reason":"compiler-message","package_id":"p#pkg@0.1.0","target":{"name":"pkg","kind":["lib"]},"message":{"level":"error","message":"boom","code":{"code":"E0308"},"spans":[]}}"#,
"\n",
r#"{"reason":"build-finished","success":false}"#,
"\n"
);
let cargo = write_script(
dir.path(),
"fakecargo",
&format!("#!/bin/sh\nprintf '%s' '{stream}'\nexit 101\n"),
);
assert!(capture_test_snapshot(&cargo, dir.path(), dir.path()).is_err());
}
#[test]
fn test_capture_fails_closed_on_no_build_finished() {
let dir = TempDir::new().unwrap();
let cargo = write_script(
dir.path(),
"fakecargo",
r#"#!/bin/sh
printf '%s\n' '{"reason":"compiler-artifact","package_id":"p#pkg@0.1.0","target":{"name":"pkg","kind":["lib"]},"profile":{"test":false},"executable":null}'
"#,
);
assert!(capture_test_snapshot(&cargo, dir.path(), dir.path()).is_err());
}
#[test]
fn assertion_counts_on_disk_reads_files() {
let dir = TempDir::new().unwrap();
std::fs::write(dir.path().join("a.rs"), "assert!(x); assert_eq!(a,b);").unwrap();
let counts = assertion_counts_on_disk(
dir.path(),
&[PathBuf::from("a.rs"), PathBuf::from("missing.rs")],
);
assert_eq!(counts[&PathBuf::from("a.rs")], 2);
assert_eq!(counts[&PathBuf::from("missing.rs")], 0);
}
#[test]
fn capture_pins_caller_target_dir_via_env() {
let dir = TempDir::new().unwrap();
let td = dir.path().join("floor-target");
std::fs::create_dir_all(&td).unwrap();
let sentinel = dir.path().join("seen-target-dir");
let script = write_script(
dir.path(),
"fakeclippy",
&format!(
"#!/bin/sh\nprintf '%s' \"$CARGO_TARGET_DIR\" > '{}'\nprintf '{{\"reason\":\"build-finished\",\"success\":true}}\\n'\n",
sentinel.display()
),
);
let snap = capture_clippy_snapshot(&script, dir.path(), &td).unwrap();
assert!(snap.warnings.is_empty());
let seen = std::fs::read_to_string(&sentinel).unwrap();
assert_eq!(
seen,
td.to_string_lossy(),
"capture must pin CARGO_TARGET_DIR to the floor's dir"
);
}
#[test]
fn distinct_target_dirs_defeat_warm_cache_sharing() {
let dir = TempDir::new().unwrap();
let sentinel = dir.path().join("targets.log");
let script = write_script(
dir.path(),
"fakeclippy",
&format!(
"#!/bin/sh\nprintf '%s\\n' \"$CARGO_TARGET_DIR\" >> '{}'\nprintf '{{\"reason\":\"build-finished\",\"success\":true}}\\n'\n",
sentinel.display()
),
);
let base_td = dir.path().join("base-target");
let tip_td = dir.path().join("tip-target");
capture_clippy_snapshot(&script, dir.path(), &base_td).unwrap();
capture_clippy_snapshot(&script, dir.path(), &tip_td).unwrap();
let log = std::fs::read_to_string(&sentinel).unwrap();
let lines: Vec<&str> = log.lines().collect();
assert_eq!(lines.len(), 2);
assert_ne!(lines[0], lines[1], "baseline and tip shared a target dir");
}
#[test]
fn build_cargo_invocation_emits_whitespace_target_dir_verbatim() {
let inv = build_cargo_invocation(
"cargo test",
Path::new("/tmp/has space/floor-td"),
&["--no-run"],
);
let td = inv.args.iter().position(|a| a == "--target-dir").unwrap();
assert_eq!(inv.args[td + 1], "/tmp/has space/floor-td");
}
}