use std::path::{Path, PathBuf};
use std::time::Instant;
use ara_core::{LayoutOptions, parse_and_layout};
fn fixtures() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures")
}
fn read(rel: &str) -> String {
std::fs::read_to_string(fixtures().join(rel)).unwrap_or_else(|e| panic!("read {rel}: {e}"))
}
#[test]
fn parse_and_layout_ok_path() {
let yaml = read("official/minimal-artifact/trace/exploration_tree.yaml");
let claims = read("official/minimal-artifact/logic/claims.md");
let opts = LayoutOptions::default();
let (manifest, report) = parse_and_layout(&yaml, Some(&claims), &opts).expect("ok");
assert!(report.is_ok());
assert!(manifest.bounds.is_some());
for node in &manifest.nodes {
assert!(node.pos.is_some(), "node {} missing pos", node.id);
let pos = node.pos.unwrap();
assert!(pos.x.is_finite());
assert!(pos.y.is_finite());
}
}
#[test]
fn parse_and_layout_error_path() {
let yaml = read("broken/cycle.yaml");
let opts = LayoutOptions::default();
let err = parse_and_layout(&yaml, None, &opts).unwrap_err();
assert!(!err.is_ok());
assert!(err.errors().iter().any(|d| d.message.contains("cycle")));
}
#[test]
fn layout_determinism_in_process() {
let yaml = read("official/resnet-ara-example/trace/exploration_tree.yaml");
let claims = read("official/resnet-ara-example/logic/claims.md");
let opts = LayoutOptions::default();
let (a, _) = parse_and_layout(&yaml, Some(&claims), &opts).expect("ok");
let (b, _) = parse_and_layout(&yaml, Some(&claims), &opts).expect("ok");
let ja = serde_json::to_string_pretty(&a).unwrap();
let jb = serde_json::to_string_pretty(&b).unwrap();
assert_eq!(ja, jb);
}
#[test]
fn positioned_manifest_snapshot() {
let yaml = read("official/minimal-artifact/trace/exploration_tree.yaml");
let claims = read("official/minimal-artifact/logic/claims.md");
let opts = LayoutOptions::default();
let (manifest, _) = parse_and_layout(&yaml, Some(&claims), &opts).expect("ok");
insta::assert_json_snapshot!("positioned_minimal_manifest", manifest);
}
#[test]
#[cfg(feature = "native")]
fn stage1_snapshots_unperturbed_by_new_fields() {
let path = fixtures().join("official/minimal-artifact");
let (manifest, _) = ara_core::parse_dir(&path).expect("ok");
let json = serde_json::to_string_pretty(&manifest).unwrap();
assert!(!json.contains("\"pos\""), "pos should be absent");
assert!(!json.contains("\"bounds\""), "bounds should be absent");
}
#[test]
fn scale_probe_largest_corpus() {
let yaml = read("corpus/rebench/rebench-rust_codecontests/trace/exploration_tree.yaml");
let claims = read("corpus/rebench/rebench-rust_codecontests/logic/claims.md");
let opts = LayoutOptions::default();
let start = Instant::now();
let result = parse_and_layout(&yaml, Some(&claims), &opts);
let elapsed = start.elapsed();
match result {
Ok((manifest, _)) => {
let node_count = manifest.nodes.len();
println!("scale probe: {} nodes, layout in {:?}", node_count, elapsed);
assert!(
elapsed.as_secs() < 5,
"layout took {elapsed:?} — exceeds 5s budget"
);
assert!(node_count > 0);
}
Err(report) => {
println!("scale probe: parse error (expected for some corpus), {elapsed:?}: {report}");
}
}
}