use std::path::Path;
use std::process::{Command, Stdio};
use std::time::{Duration, Instant};
const RSLEIGH_BIN: &str = env!("CARGO_BIN_EXE_rsleigh");
fn fixture() -> Option<String> {
for rel in [
"test-harness/fixtures/printer-hangs/tdpserver_0x1591c_arm32.bin",
"../test-harness/fixtures/printer-hangs/tdpserver_0x1591c_arm32.bin",
] {
if Path::new(rel).exists() {
return Some(rel.to_string());
}
}
eprintln!("[skip] hang fixture missing");
None
}
#[test]
fn printer_does_not_hang_on_crypto_round_dag() {
let Some(bin) = fixture() else { return };
let budget = Duration::from_secs(15);
let mut child = Command::new(RSLEIGH_BIN)
.args([&bin, "--raw", "arm32", "FUN_00000000"])
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.expect("spawn rsleigh");
let start = Instant::now();
loop {
match child.try_wait() {
Ok(Some(status)) => {
let elapsed = start.elapsed();
assert!(
status.success(),
"rsleigh exited non-zero in {:.1}s: {:?}",
elapsed.as_secs_f64(),
status
);
eprintln!(
"[ok] decompile finished in {:.2}s",
elapsed.as_secs_f64()
);
return;
}
Ok(None) => {
if start.elapsed() > budget {
let _ = child.kill();
let _ = child.wait();
panic!(
"rsleigh hung > {}s on tdpserver crypto-round fixture — \
expr_has_tracked_reg unmemoized recursion regressed",
budget.as_secs()
);
}
std::thread::sleep(Duration::from_millis(100));
}
Err(e) => panic!("waitpid error: {e}"),
}
}
}