diff --git a/aac/aac-rs/crates/aac-conformance/tests/pack.rs b/aac/aac-rs/crates/aac-conformance/tests/pack.rs new file mode 100644 index 000000000..903bf8e54 --- /dev/null +++ b/aac/aac-rs/crates/aac-conformance/tests/pack.rs @@ -0,0 +1,116 @@ +//! Read the published `aac/conformance/v1/cascade.json` and hold the +//! implementation to it. +//! +//! The in-crate suite (`aac_conformance::run`) checks the same properties, but +//! against a table written **in code**. The published pack — the bytes a third +//! party downloads — was written by `gen_vectors` and read back by nothing, so +//! the two could drift apart and only the code side would be checked. +//! +//! These tests invert that: the pack is the authority, and every assertion is +//! driven from its contents. Nothing here duplicates the level table; the +//! routing entries supply the operations and the level rows supply what each +//! level must cost and whether it may run offline. + +use std::path::PathBuf; + +use aac_core::{AacCascade, AacOperation}; +use serde_json::Value; + +fn pack() -> Value { + let p = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../../../conformance/v1/cascade.json") + .canonicalize() + .expect("published pack must exist beside the spec"); + serde_json::from_slice(&std::fs::read(&p).unwrap_or_else(|e| panic!("read {}: {e}", p.display()))) + .expect("cascade.json parses") +} + +fn level_row<'a>(pk: &'a Value, tag: &str) -> &'a Value { + pk["levels"] + .as_array() + .expect("levels array") + .iter() + .find(|l| l["tag"] == tag) + .unwrap_or_else(|| panic!("pack names level {tag} in routing but has no row for it")) +} + +/// Every routed operation lands on the level the pack publishes, and that level +/// costs and behaves exactly as the pack says. +#[test] +fn routing_energy_and_offline_match_the_published_pack() { + let pk = pack(); + let routing = pk["routing"].as_array().expect("routing array"); + assert!( + routing.len() >= 10, + "expected at least 10 routing vectors, saw {} — a wrong pack path must fail loudly", + routing.len() + ); + + for entry in routing { + let op_name = entry["operation"].as_str().expect("operation"); + let tag = entry["level"].as_str().expect("level"); + + let op: AacOperation = serde_json::from_value(entry["operation"].clone()) + .unwrap_or_else(|e| panic!("pack names operation {op_name} the crate cannot parse: {e}")); + let got = AacCascade::level_for_operation(op); + let row = level_row(&pk, tag); + + assert_eq!( + got.label(), + row["name"].as_str().expect("level name"), + "{op_name}: routed to {got:?} but the pack routes it to {tag} ({})", + row["name"] + ); + assert_eq!( + got.estimated_energy_uj(), + row["energy_uj"].as_u64().expect("energy_uj"), + "{op_name} -> {tag}: energy disagrees with the published pack" + ); + assert_eq!( + got.is_offline(), + row["offline"].as_bool().expect("offline"), + "{op_name} -> {tag}: offline capability disagrees with the published pack" + ); + } +} + +/// The pack's own declared invariants must hold over the pack's own rows. +/// +/// A pack that states `energy_strictly_monotonic` while publishing two tiers at +/// the same cost is internally inconsistent, and no amount of checking the +/// implementation would catch it. +#[test] +fn the_pack_satisfies_the_invariants_it_declares() { + let pk = pack(); + let mut levels: Vec<&Value> = pk["levels"].as_array().expect("levels").iter().collect(); + levels.sort_by_key(|l| l["index"].as_u64().expect("index")); + + if pk["invariants"]["energy_strictly_monotonic"] == true { + let mut prev = 0u64; + for l in &levels { + let e = l["energy_uj"].as_u64().expect("energy_uj"); + assert!( + e > prev, + "level {} costs {e} µJ, not more than the previous {prev} µJ, but the pack declares energy strictly monotonic", + l["tag"] + ); + prev = e; + } + } + + let declared: Vec<&str> = pk["invariants"]["offline_levels"] + .as_array() + .expect("offline_levels") + .iter() + .map(|v| v.as_str().expect("tag")) + .collect(); + let actual: Vec<&str> = levels + .iter() + .filter(|l| l["offline"] == true) + .map(|l| l["tag"].as_str().expect("tag")) + .collect(); + assert_eq!( + actual, declared, + "the levels marked offline in the pack do not match the offline_levels it declares" + ); +}