use std::{fs, path::PathBuf, process, thread, time::Duration};
fn kill_subprocesses_recursively(pid: &str) {
let subprocesses = process::Command::new("pgrep")
.arg(format!("-P{pid}"))
.output()
.unwrap();
for subprocess in std::str::from_utf8(&subprocesses.stdout)
.unwrap()
.split('\n')
{
if subprocess.is_empty() {
continue;
}
kill_subprocesses_recursively(subprocess);
}
println!("Killing pid {pid}");
unsafe {
libc::kill(pid.parse::<i32>().unwrap(), libc::SIGTERM);
}
}
#[allow(clippy::zombie_processes)]
#[test]
fn integration() {
let temp_dir = tempfile::tempdir().unwrap();
let temp_dir_path = temp_dir.path();
let metadata = cargo_metadata::MetadataCommand::new().exec().unwrap();
let workspace_root: PathBuf = metadata.workspace_root.into();
let target_directory: PathBuf = metadata.target_directory.into();
let cargo_ziggy = target_directory.join("debug").join("cargo-ziggy");
let fuzzer_directory = workspace_root.join("examples").join("arbitrary");
let build_status = process::Command::new(cargo_ziggy.clone())
.arg("ziggy")
.arg("build")
.current_dir(fuzzer_directory.clone())
.status()
.expect("failed to run `cargo ziggy build`");
assert!(build_status.success(), "`cargo ziggy build` failed");
let fuzzer = process::Command::new(cargo_ziggy)
.arg("ziggy")
.arg("fuzz")
.arg("-j2")
.arg("-t5")
.arg("-G100")
.env("ZIGGY_OUTPUT", format!("{}", temp_dir_path.display()))
.env("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "1")
.env("AFL_SKIP_CPUFREQ", "1")
.current_dir(fuzzer_directory)
.spawn()
.expect("failed to run `cargo ziggy fuzz`");
thread::sleep(Duration::from_secs(30));
kill_subprocesses_recursively(&format!("{}", fuzzer.id()));
assert!(
temp_dir_path
.join("arbitrary-fuzz")
.join("afl")
.join("mainaflfuzzer")
.join("fuzzer_stats")
.is_file()
);
assert!(
fs::read_dir(
temp_dir_path
.join("arbitrary-fuzz")
.join("afl")
.join("mainaflfuzzer")
.join("crashes")
)
.unwrap()
.count()
!= 0
);
assert!(
temp_dir_path
.join("arbitrary-fuzz")
.join("honggfuzz")
.join("arbitrary-fuzz")
.join("input")
.is_dir()
);
}