use std::path::PathBuf;
use std::process::Command;
fn pounce_exe() -> PathBuf {
PathBuf::from(env!("CARGO_BIN_EXE_pounce"))
}
fn fixture_nl() -> PathBuf {
let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
p.push("tests");
p.push("fixtures");
p.push("parametric.nl");
p
}
fn tmp(suffix: &str) -> PathBuf {
let mut p = std::env::temp_dir();
p.push(format!("pounce_check_x0_{}_{suffix}", std::process::id()));
p
}
#[test]
fn healthy_nl_is_clean_and_emits_schema_json() {
let out = Command::new(pounce_exe())
.arg("check-x0")
.arg(fixture_nl())
.arg("--json")
.output()
.expect("spawn pounce check-x0");
assert_eq!(
out.status.code(),
Some(0),
"stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let v: serde_json::Value =
serde_json::from_slice(&out.stdout).expect("stdout is a JSON report");
assert_eq!(v["schema"], "pounce.check-x0/v1");
assert_eq!(v["fatal"], false);
assert_eq!(v["problem"]["n_vars"], 5);
assert_eq!(v["problem"]["n_cons"], 4);
assert!(v["evaluation"]["objective_finite"].as_bool().unwrap());
assert!(v["problem"]["sha256"].as_str().is_some());
}
#[test]
fn builtin_is_supported() {
let out = Command::new(pounce_exe())
.arg("check-x0")
.arg("--builtin")
.arg("rosenbrock")
.arg("--json")
.output()
.expect("spawn pounce check-x0 --builtin");
assert_eq!(
out.status.code(),
Some(0),
"stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let v: serde_json::Value = serde_json::from_slice(&out.stdout).expect("JSON");
assert_eq!(v["fatal"], false);
assert_eq!(v["problem"]["source"], "builtin:rosenbrock");
}
#[test]
fn x0_file_wrong_length_is_usage_error() {
let bad = tmp("short_x0.txt");
std::fs::write(&bad, "1.0 2.0").unwrap(); let code = Command::new(pounce_exe())
.arg("check-x0")
.arg(fixture_nl())
.arg("--x0-file")
.arg(&bad)
.status()
.expect("spawn")
.code();
assert_eq!(code, Some(2));
let _ = std::fs::remove_file(&bad);
}
#[test]
fn x0_file_overrides_start_and_infeasibility_is_not_fatal() {
let far = tmp("far_x0.txt");
std::fs::write(&far, "1e6 1e6 1e6 1e6 1e6").unwrap();
let report = tmp("far_report.json");
let code = Command::new(pounce_exe())
.arg("check-x0")
.arg(fixture_nl())
.arg("--x0-file")
.arg(&far)
.arg("--json-output")
.arg(&report)
.status()
.expect("spawn")
.code();
assert_eq!(
code,
Some(0),
"an infeasible-but-evaluable start is not fatal"
);
let v: serde_json::Value =
serde_json::from_slice(&std::fs::read(&report).unwrap()).expect("JSON");
assert_eq!(v["fatal"], false);
assert!(v["x0"]["source"].as_str().unwrap().contains("far_x0.txt"));
assert!(v["constraint_violation"]["max_violation"].as_f64().unwrap() > 1.0);
let _ = std::fs::remove_file(&far);
let _ = std::fs::remove_file(&report);
}