test(0092): run-from-blueprint E2E + bit-identical keystone + demo fixtures
Closes the cycle-1 test coverage for #165. The `aura run <blueprint.json>` CLI arm itself (the .json dispatch + parse_blueprint_run_args + BlueprintRunArgs) shipped in ff4a1b3; this adds the coverage that proves it and the in-repo demo blueprint: - crates/aura-cli/tests/fixtures/stage1_signal.json — the canonical SMA-cross signal (blueprint_to_json of stage1_signal(2,4)); emit_demo_signal_fixture (#[ignore]) regenerates it. - crates/aura-cli/tests/fixtures/unknown_node.json — one type set to "Nope" for the fail-clean guard. - loaded_signal_runs_bit_identical_to_rust_built (the keystone, C1): a signal serialized -> loaded via blueprint_from_json -> run is bit-identical to its Rust-built twin, incl. topology_hash (64-hex). - topology_hash_is_stable_and_distinguishes (#158 anchor property). - cli_run.rs E2E: `aura run <demo>` exits 0 with topology_hash in the manifest; an unknown-node blueprint fails clean with UnknownNodeType (the #160 closed-set guard at the data-plane face, invariant 9). Verified end-to-end by actually running the binary: `aura run stage1_signal.json` -> RunReport with a 64-hex topology_hash, sim-optimal+risk-executor broker, R metrics; `aura run unknown_node.json` -> UnknownNodeType("Nope"), exit 2. Full workspace suite green; clippy --all-targets -D warnings clean. refs #165
This commit is contained in:
@@ -4945,6 +4945,37 @@ mod tests {
|
||||
assert!(parse_blueprint_run_args(&["--params", "[{\"I64\":1}]", "--params", "[]"]).is_err()); // repeated
|
||||
}
|
||||
|
||||
/// Regenerates the committed demo signal blueprint the `aura run <file.json>`
|
||||
/// E2E loads. Ignored by default; run with `--ignored` after a signal change.
|
||||
#[test]
|
||||
#[ignore = "regenerates the committed demo signal blueprint fixture"]
|
||||
fn emit_demo_signal_fixture() {
|
||||
let json = blueprint_to_json(&stage1_signal(Some(2), Some(4))).expect("serializes");
|
||||
std::fs::write("tests/fixtures/stage1_signal.json", json).expect("write fixture");
|
||||
}
|
||||
|
||||
/// The cycle-1 keystone (C1): a signal serialized → loaded back through the
|
||||
/// public `blueprint_from_json` path runs bit-identically to its Rust-built
|
||||
/// twin — same metrics, same traces, same topology_hash.
|
||||
#[test]
|
||||
fn loaded_signal_runs_bit_identical_to_rust_built() {
|
||||
let json = blueprint_to_json(&stage1_signal(Some(2), Some(4))).expect("serializes");
|
||||
let loaded = blueprint_from_json(&json, &|t| std_vocabulary(t)).expect("loads");
|
||||
let a = run_signal_stage1r(stage1_signal(Some(2), Some(4)), &[], RunData::Synthetic, 0);
|
||||
let b = run_signal_stage1r(loaded, &[], RunData::Synthetic, 0);
|
||||
assert_eq!(a.to_json(), b.to_json(), "loaded run is bit-identical incl. topology_hash");
|
||||
assert_eq!(a.manifest.topology_hash.as_deref().map(str::len), Some(64), "64-hex sha256 present");
|
||||
}
|
||||
|
||||
/// `topology_hash` is deterministic per signal and distinguishes topologies —
|
||||
/// the #158 reproducibility-anchor property.
|
||||
#[test]
|
||||
fn topology_hash_is_stable_and_distinguishes() {
|
||||
let h = topology_hash(&stage1_signal(Some(2), Some(4)));
|
||||
assert_eq!(h, topology_hash(&stage1_signal(Some(2), Some(4))), "same signal -> same hash");
|
||||
assert_ne!(h, topology_hash(&stage1_signal(Some(3), Some(4))), "different topology -> different hash");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_mc_args_bare_and_name_route_to_synthetic() {
|
||||
assert_eq!(parse_mc_args(&[]), Ok(McArgs::Synthetic { name: "mc".to_string(), persist: false }));
|
||||
|
||||
@@ -317,6 +317,38 @@ fn run_real_nonvetted_symbol_resolves_pip_from_sidecar() {
|
||||
);
|
||||
}
|
||||
|
||||
/// `aura run <blueprint.json>` loads a serialized signal blueprint and runs it
|
||||
/// end-to-end (#165): exit 0, a RunReport whose manifest carries the topology_hash.
|
||||
#[test]
|
||||
fn aura_run_loads_and_runs_a_blueprint_file() {
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["run", "tests/fixtures/stage1_signal.json"])
|
||||
.output()
|
||||
.expect("spawn aura run blueprint");
|
||||
assert_eq!(
|
||||
out.status.code(),
|
||||
Some(0),
|
||||
"exit: {:?} stderr={}",
|
||||
out.status,
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let stdout = String::from_utf8(out.stdout).expect("utf-8");
|
||||
assert!(stdout.contains("\"topology_hash\":\""), "manifest carries the topology hash: {stdout}");
|
||||
}
|
||||
|
||||
/// A blueprint referencing a node type outside the closed vocabulary fails clean
|
||||
/// at load (the #160 closed-set guard at the data-plane face; invariant 9).
|
||||
#[test]
|
||||
fn aura_run_rejects_an_unknown_node_blueprint() {
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["run", "tests/fixtures/unknown_node.json"])
|
||||
.output()
|
||||
.expect("spawn aura run unknown");
|
||||
assert_ne!(out.status.code(), Some(0), "an unknown node type must fail the run");
|
||||
let stderr = String::from_utf8(out.stderr).expect("utf-8");
|
||||
assert!(stderr.contains("UnknownNodeType"), "names the cause: {stderr}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_trace_persists_taps_and_plain_run_writes_no_traces() {
|
||||
let cwd = temp_cwd("run-trace");
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"format_version":1,"blueprint":{"name":"stage1_signal","nodes":[{"primitive":{"type":"SMA","name":"fast","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":2}}]}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":4}}]}},{"primitive":{"type":"Sub"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":0.5}}]}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":3,"field":0,"name":"bias"}]}}
|
||||
@@ -0,0 +1 @@
|
||||
{"format_version":1,"blueprint":{"name":"stage1_signal","nodes":[{"primitive":{"type":"Nope","name":"fast","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":2}}]}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":4}}]}},{"primitive":{"type":"Sub"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":0.5}}]}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":3,"field":0,"name":"bias"}]}}
|
||||
Reference in New Issue
Block a user