test: red executable-spec for #247 — sweep-boundary bind errors render as prose
Both blueprint-sweep bind faults (wrong-kind axis value; an open param
no axis covers) must print prose in the unknown-axis sibling's register
— axis name, kind/knob specifics, a --list-axes pointer — never the raw
Debug structs KindMismatch{..}/MissingKnob(..). Exit stays 2. Fails on
the Debug leakage present today, not on scaffolding.
refs #247
This commit is contained in:
@@ -2181,6 +2181,84 @@ fn aura_sweep_real_blueprint_refuses_a_raw_form_axis_name_before_data_access() {
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// Property (#247): every sweep-verb boundary `BindError` renders as prose in
|
||||
/// the same register as its unknown-axis sibling
|
||||
/// (`aura: axis <name>: names no param of this blueprint … — see `aura sweep
|
||||
/// <bp> --list-axes``) — never a raw Rust Debug struct. A wrong-kind axis value
|
||||
/// and an uncovered open knob are the two variants that today leak
|
||||
/// `KindMismatch { knob: …, expected: …, got: … }` and
|
||||
/// `MissingKnob("…")` verbatim to stderr; both must instead name the axis, carry
|
||||
/// the specifics (expected vs supplied kind / the unbound knob), and point at
|
||||
/// `--list-axes`, with the exit code staying 2. Data-free: both faults are
|
||||
/// caught at the axis-resolution boundary before any member runs, so the test
|
||||
/// needs no archive and no project (hostless synthetic sweep).
|
||||
#[test]
|
||||
fn sweep_boundary_bind_errors_render_as_prose_not_debug_structs() {
|
||||
let dir = temp_cwd("sweep-bind-error-prose");
|
||||
|
||||
// (a) KindMismatch — an axis re-opens the bound I64 `fast.length` (#246) but
|
||||
// supplies F64 values: the specifics are the expected vs supplied kind.
|
||||
let closed = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let km = Command::new(BIN)
|
||||
.args(["sweep", &closed, "--axis", "sma_signal.fast.length=2.5,3.5"])
|
||||
.current_dir(&dir)
|
||||
.output()
|
||||
.expect("spawn aura sweep (kind-mismatched axis)");
|
||||
assert_eq!(
|
||||
km.status.code(),
|
||||
Some(2),
|
||||
"a kind-mismatched axis value stays a usage refusal: status={:?}",
|
||||
km.status
|
||||
);
|
||||
let km_err = String::from_utf8_lossy(&km.stderr).into_owned();
|
||||
assert!(
|
||||
!km_err.contains("KindMismatch"),
|
||||
"must not leak the raw Rust Debug struct name: {km_err}"
|
||||
);
|
||||
assert!(
|
||||
km_err.contains("sma_signal.fast.length"),
|
||||
"the prose names the offending axis exactly as typed: {km_err}"
|
||||
);
|
||||
assert!(
|
||||
km_err.contains("I64") && km_err.contains("F64"),
|
||||
"the prose carries the expected vs supplied kind specifics: {km_err}"
|
||||
);
|
||||
assert!(
|
||||
km_err.contains("--list-axes"),
|
||||
"the prose points at the discovery surface, like the unknown-axis sibling: {km_err}"
|
||||
);
|
||||
|
||||
// (b) MissingKnob — the open fixture leaves `slow.length` unbound when only
|
||||
// `fast.length` is swept: the specific is the uncovered open knob.
|
||||
let open = format!("{}/tests/fixtures/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let mk = Command::new(BIN)
|
||||
.args(["sweep", &open, "--axis", "sma_signal.fast.length=2,4"])
|
||||
.current_dir(&dir)
|
||||
.output()
|
||||
.expect("spawn aura sweep (uncovered open knob)");
|
||||
assert_eq!(
|
||||
mk.status.code(),
|
||||
Some(2),
|
||||
"an uncovered open knob stays a usage refusal: status={:?}",
|
||||
mk.status
|
||||
);
|
||||
let mk_err = String::from_utf8_lossy(&mk.stderr).into_owned();
|
||||
assert!(
|
||||
!mk_err.contains("MissingKnob"),
|
||||
"must not leak the raw Rust Debug struct name: {mk_err}"
|
||||
);
|
||||
assert!(
|
||||
mk_err.contains("sma_signal.slow.length"),
|
||||
"the prose names the unbound knob no axis supplies: {mk_err}"
|
||||
);
|
||||
assert!(
|
||||
mk_err.contains("--list-axes"),
|
||||
"the prose points at the discovery surface, like the unknown-axis sibling: {mk_err}"
|
||||
);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// Property (#210 c0110 fieldtest, "refused dissolved sweeps still register
|
||||
/// their generated campaign document" — store litter, probe P3): binding only
|
||||
/// a SUBSET of the blueprint's open axes (here: `fast.length`, leaving
|
||||
|
||||
Reference in New Issue
Block a user