use std::{fs, process::Command};
use tempfile::TempDir;
#[tokio::test]
async fn test_commands_actually_execute() {
let original_dir = std::env::current_dir().unwrap_or_else(|_| {
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
});
struct DirGuard(std::path::PathBuf);
impl Drop for DirGuard {
fn drop(&mut self) {
let _ = std::env::set_current_dir(&self.0);
}
}
let _guard = DirGuard(original_dir.clone());
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let temp_path = temp_dir.path();
Command::new("git")
.args(["init"])
.current_dir(temp_path)
.output()
.expect("Failed to init git repo");
Command::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(temp_path)
.output()
.expect("Failed to set git user.name");
Command::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(temp_path)
.output()
.expect("Failed to set git user.email");
let output_file = temp_path.join("hook_executed.txt");
let config_content = format!(
r#"hooks:
pre-commit:
parallel: true
commands:
test-echo:
run: echo "HOOK EXECUTED" > {}
priority: 1
"#,
output_file.display()
);
let config_path = temp_path.join("guardy.yaml");
fs::write(&config_path, config_content).expect("Failed to write config");
let test_file = temp_path.join("test.txt");
fs::write(&test_file, "test content").expect("Failed to create test file");
Command::new("git")
.args(["add", "test.txt"])
.current_dir(temp_path)
.output()
.expect("Failed to stage test file");
let guardy_bin = if let Ok(cargo_bin_path) = std::env::var("CARGO_BIN_EXE_guardy") {
std::path::PathBuf::from(cargo_bin_path)
} else {
let potential_paths = vec![
original_dir
.join("target")
.join("llvm-cov-target")
.join("debug")
.join("guardy"),
original_dir.join("target").join("debug").join("guardy"),
original_dir
.parent()
.and_then(|p| p.parent())
.map(|p| p.join("target").join("debug").join("guardy"))
.unwrap_or_default(),
];
let mut found_bin = None;
for path in &potential_paths {
if path.exists() {
found_bin = Some(path.clone());
break;
}
}
if found_bin.is_none() {
let build_output = Command::new("cargo")
.args(["build", "--bin", "guardy"])
.current_dir(&original_dir)
.output()
.expect("Failed to build guardy binary");
if !build_output.status.success() {
panic!(
"Failed to build guardy binary. Stdout: {}\nStderr: {}",
String::from_utf8_lossy(&build_output.stdout),
String::from_utf8_lossy(&build_output.stderr)
);
}
for path in &potential_paths {
if path.exists() {
found_bin = Some(path.clone());
break;
}
}
}
found_bin.expect("Could not find or build guardy binary")
};
assert!(
guardy_bin.exists(),
"Guardy binary not found at: {}",
guardy_bin.display()
);
let output = Command::new(&guardy_bin)
.args([
"--config",
config_path.to_str().unwrap(),
"hooks",
"run",
"pre-commit",
])
.current_dir(temp_path)
.env("RUST_LOG", "trace")
.output()
.expect("Failed to run guardy hooks");
println!("Guardy output: {}", String::from_utf8_lossy(&output.stdout));
println!("Guardy stderr: {}", String::from_utf8_lossy(&output.stderr));
println!("Config file contents:");
println!("{}", fs::read_to_string(&config_path).unwrap());
assert!(
output.status.success(),
"Guardy hook execution should succeed"
);
assert!(
output_file.exists(),
"Hook command should have created output file at {}",
output_file.display()
);
let content = fs::read_to_string(&output_file).expect("Failed to read hook output file");
assert!(
content.trim() == "HOOK EXECUTED",
"Hook output file should contain expected content, got: '{}'",
content.trim()
);
println!("✅ Hook command actually executed and created expected file");
}