f3daded514
The compile core. resolve_tap_wire resolves a blueprint Tap's interior
{node, field} through the lowering table exactly as OutField re-exports and
edges resolve — a leaf to its remapped index (output-arity checked), a nested
composite through its output remap. Taps are terminal (not re-exported through
the boundary): a flat_taps accumulator threads through the lowering recursion,
so an interior composite's taps hoist to the root FlatGraph.taps with remapped
wires — the case the CLI single-run wrapper relies on. validate_wiring gains a
tap leg (threaded at all three call sites incl. GraphSession::finish) and
CompileError::TapWireOutOfRange names a bad wire. Root-resolve, out-of-arity,
and nested-hoist are pinned green.
refs #282
137 lines
6.6 KiB
Rust
137 lines
6.6 KiB
Rust
//! End-to-end coverage for the `FlatTap` / `FlatGraph.taps` plumbing (#282):
|
|
//! a `Composite` can declare a `Tap` (via `with_taps`), and `compile()` now
|
|
//! resolves it into the flat graph it hands to `Harness::bootstrap`. These
|
|
//! tests pin the two halves of that contract at the public `aura_engine`
|
|
//! boundary: `compile()` surfaces a declared `Tap` into `FlatGraph.taps`,
|
|
//! resolved to its flat producer `(node, field)`
|
|
//! (`compile_resolves_a_declared_tap_at_the_public_boundary`), and doing so
|
|
//! is otherwise transparent to compilation of the rest of the graph — the
|
|
//! same node/edge structure, just an added taps entry
|
|
//! (`tapped_composite_compiles_identically_to_untapped_besides_the_taps_list`).
|
|
|
|
use aura_core::ScalarKind;
|
|
use aura_engine::{BlueprintNode, CompileError, Composite, FlatTap, OutField, Role, Tap, TapWire, Target};
|
|
use aura_std::Sub;
|
|
|
|
/// A trivial one-node composite with a single declared output (`Sub`'s
|
|
/// difference), matching the `taps` argument requested by each test. Both of
|
|
/// `Sub`'s input slots are fed by one root-bound (source) role — enough to
|
|
/// satisfy `compile()`'s port-connectivity + root-binding checks.
|
|
fn leaf(taps: Vec<Tap>) -> Composite {
|
|
Composite::new(
|
|
"leaf",
|
|
vec![Sub::builder().into()],
|
|
vec![],
|
|
vec![Role {
|
|
name: "price".into(),
|
|
targets: vec![Target { node: 0, slot: 0 }, Target { node: 0, slot: 1 }],
|
|
source: Some(ScalarKind::F64),
|
|
}],
|
|
vec![OutField { node: 0, field: 0, name: "o".into() }],
|
|
)
|
|
.with_taps(taps)
|
|
}
|
|
|
|
/// Property: **`compile()` resolves a declared `Tap` at the public
|
|
/// boundary.** A composite declaring a valid `Tap` (naming a real interior
|
|
/// producer, `node: 0, field: 0`) compiles to a `FlatGraph` whose `taps` list
|
|
/// carries the resolved `FlatTap` — name preserved, wire resolved to the flat
|
|
/// producer index.
|
|
#[test]
|
|
fn compile_resolves_a_declared_tap_at_the_public_boundary() {
|
|
let tapped = leaf(vec![Tap { name: "spread".into(), from: TapWire { node: 0, field: 0 } }]);
|
|
let flat = tapped.compile().expect("a tap-bearing composite compiles");
|
|
assert_eq!(
|
|
flat.taps,
|
|
vec![FlatTap { name: "spread".into(), node: 0, field: 0 }],
|
|
"compile() must resolve the declared Tap into FlatGraph.taps: {:?}",
|
|
flat.taps
|
|
);
|
|
}
|
|
|
|
/// Property: **a declared `Tap` is otherwise inert at compile time** — it
|
|
/// changes nothing about the flattened node/edge structure. Compiling the
|
|
/// same composite with and without a `Tap` declaration must produce
|
|
/// structurally identical flat graphs (same node count, same edges); the
|
|
/// only difference tap-bearing scaffolding is allowed to make is the `taps`
|
|
/// list itself (empty vs. carrying the one resolved entry).
|
|
#[test]
|
|
fn tapped_composite_compiles_identically_to_untapped_besides_the_taps_list() {
|
|
let untapped = leaf(vec![]).compile().expect("untapped compiles");
|
|
let tapped = leaf(vec![Tap { name: "spread".into(), from: TapWire { node: 0, field: 0 } }])
|
|
.compile()
|
|
.expect("tapped compiles");
|
|
|
|
assert_eq!(untapped.nodes.len(), tapped.nodes.len(), "tap declaration must not add/remove flat nodes");
|
|
assert_eq!(untapped.edges, tapped.edges, "tap declaration must not perturb flat edges");
|
|
assert!(untapped.taps.is_empty(), "the untapped composite compiles to an empty taps list");
|
|
assert_eq!(
|
|
tapped.taps,
|
|
vec![FlatTap { name: "spread".into(), node: 0, field: 0 }],
|
|
"the tapped composite compiles to the one resolved entry"
|
|
);
|
|
}
|
|
|
|
/// Property: **the `validate_wiring` structural leg rejects a tap whose wire
|
|
/// names a node index beyond the composite's own node count**, before any
|
|
/// lowering or field-arity resolution ever runs — mirroring how the sibling
|
|
/// `output` leg raises `OutputPortOutOfRange` for the same shape of mistake.
|
|
/// This is the early, cheap structural gate (`tap.from.node >= nodes.len()`)
|
|
/// added alongside tap resolution in this iteration; without it, a
|
|
/// wildly-out-of-range tap wire would only be caught by luck at whichever
|
|
/// later stage happens to index into a lowering table, not deterministically
|
|
/// at compile's first validation pass.
|
|
#[test]
|
|
fn compile_rejects_a_tap_wire_node_out_of_range() {
|
|
let tapped = leaf(vec![Tap { name: "ghost".into(), from: TapWire { node: 1, field: 0 } }]);
|
|
match tapped.compile() {
|
|
Err(CompileError::TapWireOutOfRange { tap }) => assert_eq!(tap, "ghost"),
|
|
other => panic!("expected TapWireOutOfRange{{tap: \"ghost\"}}, got {:?}", other.map(|_| ())),
|
|
}
|
|
}
|
|
|
|
/// Property: **a `Tap` declared on a nested composite hoists all the way to
|
|
/// the root `FlatGraph.taps`, with its wire remapped through the inline
|
|
/// offset** accumulated by every flat node lowered ahead of it — not just
|
|
/// carried through unresolved, and not resolved to its interior-local index.
|
|
/// The root here lowers a plain leaf node first (flat index 0) followed by
|
|
/// the tapped composite (whose interior `Sub` therefore lands at flat index
|
|
/// 1, not 0), so a remap that silently stayed at the interior-local index —
|
|
/// or hoisted at all — is caught by asserting the hoisted `FlatTap` points at
|
|
/// index 1. This is the exact shape the by-name tap-binding CLI wrapper
|
|
/// needs: a tap declared arbitrarily deep in an authored blueprint must
|
|
/// surface as one flat, addressable measurement point at the root.
|
|
#[test]
|
|
fn compile_hoists_a_nested_composite_tap_to_the_root_with_remapped_index() {
|
|
let inner = Composite::new(
|
|
"inner",
|
|
vec![Sub::builder().into()],
|
|
vec![],
|
|
vec![Role { name: "x".into(), targets: vec![Target { node: 0, slot: 0 }, Target { node: 0, slot: 1 }], source: None }],
|
|
vec![OutField { node: 0, field: 0, name: "o".into() }],
|
|
)
|
|
.with_taps(vec![Tap { name: "inner_d".into(), from: TapWire { node: 0, field: 0 } }]);
|
|
|
|
let root = Composite::new(
|
|
"root",
|
|
vec![Sub::builder().into(), BlueprintNode::Composite(inner)],
|
|
vec![],
|
|
vec![
|
|
Role {
|
|
name: "lead".into(),
|
|
targets: vec![Target { node: 0, slot: 0 }, Target { node: 0, slot: 1 }],
|
|
source: Some(ScalarKind::F64),
|
|
},
|
|
Role { name: "a".into(), targets: vec![Target { node: 1, slot: 0 }], source: Some(ScalarKind::F64) },
|
|
],
|
|
vec![],
|
|
);
|
|
|
|
let flat = root.compile().expect("root with a nested tapped composite compiles");
|
|
assert_eq!(
|
|
flat.taps,
|
|
vec![FlatTap { name: "inner_d".into(), node: 1, field: 0 }],
|
|
"the inner tap must hoist to root FlatGraph.taps, remapped to the inline-offset flat node index"
|
|
);
|
|
}
|