use std::process::{Command, Stdio};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
const TIMEOUT_SECS: u64 = 120;
fn cargo_example(name: &str, features: &[&str]) -> (Command, String) {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let target_dir = format!("{manifest_dir}/target/examples_build_test");
let mut cmd = Command::new("cargo");
cmd.arg("build")
.arg("--example")
.arg(name)
.arg("-p")
.arg("weir")
.env("CARGO_TARGET_DIR", &target_dir)
.current_dir(manifest_dir)
.stdout(Stdio::piped())
.stderr(Stdio::piped());
for f in features {
cmd.arg("--features").arg(f);
}
(cmd, target_dir)
}
fn run_example(name: &str, features: &[&str]) {
let (mut cmd, _target_dir) = cargo_example(name, features);
let child = cmd.spawn().expect("cargo should spawn");
let pid = child.id();
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let result = child.wait_with_output();
let _ = tx.send(result);
});
let output = match rx.recv_timeout(Duration::from_secs(TIMEOUT_SECS)) {
Ok(Ok(output)) => output,
Ok(Err(e)) => panic!("cargo build --example {name} failed to execute: {e}"),
Err(_) => {
let _ = Command::new("kill").args(["-9", &pid.to_string()]).status();
panic!("cargo build --example {name} timed out after {TIMEOUT_SECS}s");
}
};
assert!(
output.status.success(),
"example {name} build failed:\nstdout: {}\nstderr: {}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
}
#[test]
fn example_ifds_to_witness_builds_and_runs() {
run_example("ifds_to_witness", &[]);
}
#[test]
fn example_serde_evidence_builds_and_runs() {
run_example("serde_evidence", &["serde"]);
}
#[test]
fn example_witness_many_builds_and_runs() {
run_example("witness_many", &[]);
}