use std::path::Path;
use std::process::{Command, Output};
const VERSION_MISMATCH_FIXTURE: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../dispatcher/conformance-fixtures/ir-version-mismatch.json"
);
fn run_warble(args: &[&str]) -> Output {
Command::new(env!("CARGO_BIN_EXE_warble"))
.args(args)
.output()
.expect("warble runs")
}
fn write_minimal_trace(dir: &Path) -> std::path::PathBuf {
let path = dir.join("trace.json");
std::fs::write(&path, r#"{"component":"answer_query","events":[]}"#)
.expect("write trace fixture");
path
}
#[test]
fn eval_compliance_rejects_the_shared_cross_back_end_version_mismatch_fixture() {
let raw = std::fs::read_to_string(VERSION_MISMATCH_FIXTURE)
.unwrap_or_else(|e| panic!("read {VERSION_MISMATCH_FIXTURE}: {e}"));
let fixture: serde_json::Value = serde_json::from_str(&raw).expect("fixture is valid JSON");
let expected: Vec<&str> = fixture["expected_error_contains"]
.as_array()
.expect("expected_error_contains is an array")
.iter()
.map(|v| {
v.as_str()
.expect("expected_error_contains entries are strings")
})
.collect();
let tmp = tempfile::tempdir().expect("tempdir");
let ir_path = tmp.path().join("ir.json");
std::fs::write(
&ir_path,
serde_json::to_string(&fixture["ir"]).expect("fixture ir serializes"),
)
.expect("write ir fixture");
let trace_path = write_minimal_trace(tmp.path());
let output = run_warble(&[
"eval",
"compliance",
"--trace",
trace_path.to_str().unwrap(),
"--ir",
ir_path.to_str().unwrap(),
]);
assert!(
!output.status.success(),
"an out-of-range IR version must not exit success; stdout: {}",
String::from_utf8_lossy(&output.stdout)
);
let stderr = String::from_utf8_lossy(&output.stderr);
for substring in &expected {
assert!(
stderr.contains(substring),
"expected stderr to contain '{substring}', got: {stderr}"
);
}
}
#[test]
fn eval_compliance_rejects_an_ir_with_no_warble_ir_version_field_at_all() {
let tmp = tempfile::tempdir().expect("tempdir");
let ir_path = tmp.path().join("ir.json");
std::fs::write(&ir_path, r#"{"components": []}"#).expect("write ir fixture");
let trace_path = write_minimal_trace(tmp.path());
let output = run_warble(&[
"eval",
"compliance",
"--trace",
trace_path.to_str().unwrap(),
"--ir",
ir_path.to_str().unwrap(),
]);
assert!(
!output.status.success(),
"an IR with no warble_ir_version must not exit success; stdout: {}",
String::from_utf8_lossy(&output.stdout)
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("warble_ir_version"),
"error should name the missing field, got: {stderr}"
);
}
#[test]
fn eval_compliance_accepts_a_current_version_ir() {
let ir_path =
Path::new(env!("CARGO_MANIFEST_DIR")).join("../examples/analysis-agent/ir.golden.json");
let tmp = tempfile::tempdir().expect("tempdir");
let trace_path = write_minimal_trace(tmp.path());
let output = run_warble(&[
"eval",
"compliance",
"--trace",
trace_path.to_str().unwrap(),
"--ir",
ir_path.to_str().unwrap(),
]);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
!stderr.contains("warble_ir_version"),
"a current-version IR must clear the version gate cleanly, got stderr: {stderr}"
);
}