Files

121 lines
5.3 KiB
Rust

//! Standalone actual-core falsifier. Not compiled or executed by its author.
//! Root must select a matching oa_core rlib and serialize compilation with gates.
use oa_core::{projection::*, validation, *};
fn pos(x: f32, y: f32) -> Position { Position { x, y } }
fn size(width: f32, height: f32) -> Size { Size { width, height } }
fn valid(label: &str, p: &Project) {
let issues = validation::validate(p);
for issue in &issues { println!("{label}: {issue:?}"); }
assert!(!issues.iter().any(|i| i.severity == validation::Severity::Error),
"Fixture/candidate must be model-valid: {label}");
}
fn standard(p: &mut Project, owner: Id, name: &str) -> Id {
let id = Id::new_v4();
let port = make_port(p, id, owner, name, PortContract::Component {
kind: ComponentPortKind::Standard,
orientation: ComponentPortOrientation::Unset,
}).unwrap();
p.elements.insert(id, port);
id
}
fn fixture(manual: bool) -> (Project, Id, Id) {
let mut p = Project::empty();
let a = p.add_element(Kind::System, Layer::Sa, "Owner", None).unwrap();
let b = p.add_element(Kind::SystemActor, Layer::Sa, "Above", None).unwrap();
let c = p.add_element(Kind::SystemActor, Layer::Sa, "Below", None).unwrap();
let pb = standard(&mut p, b, "Above interface");
let pc = standard(&mut p, c, "Below interface");
let mut ports = Vec::new();
for i in 0..8 {
let pa = standard(&mut p, a, &format!("Owner interface {i}"));
p.relate(RelationKind::BoundaryExchange, &format!("Above exchange {i}"), pa, pb);
p.relate(RelationKind::BoundaryExchange, &format!("Below exchange {i}"), pa, pc);
ports.push(pa);
}
let d = p.ensure_diagram(Layer::Sa);
let na = p.place(d, a, pos(0., 0.));
// Normal-sized separated peers have centers (130,-930) and (130,1070).
// Each Owner port sees the same average peer center (130,70).
let nb = p.place(d, b, pos(38., -996.));
let nc = p.place(d, c, pos(38., 1004.));
let diagram = p.diagrams.get_mut(&d).unwrap();
diagram.nodes.get_mut(&na).unwrap().size = size(224., 160.);
for n in [nb, nc] { diagram.nodes.get_mut(&n).unwrap().size = size(184., 132.); }
if manual {
diagram.nodes.get_mut(&na).unwrap().port_anchors = ports.into_iter()
.enumerate().map(|(i, port)| PortAnchor {
port, side: PortAnchorSide::Right, offset: (i + 1) as f32 / 9.,
}).collect();
}
valid("baseline", &p);
(p, d, na)
}
fn projected(p: &Project, d: Id, n: Id) -> ProjectedNode {
project_diagram(p, &p.diagrams[&d]).nodes.into_iter().find(|v| v.id == n).unwrap()
}
fn edit(p: &Project, d: Id, n: Id, dimensions: Size) -> Project {
let mut node = p.diagrams[&d].nodes[&n].clone();
node.size = dimensions;
let next = prepare_command(p, &Command::EditNode { diagram: d, original: n, node }).unwrap().project;
valid("candidate", &next);
next
}
fn normalization_falsifier(manual: bool) {
let (p, d, n) = fixture(manual);
let baseline = projected(&p, d, n);
println!("manual={manual}, baseline {baseline:?}");
assert_eq!(baseline.position, pos(0., 0.));
assert_eq!(baseline.size, size(224., 232.));
let normalized = edit(&p, d, n, baseline.size);
let normalized_view = projected(&normalized, d, n);
println!("normalized {normalized_view:?}");
assert_eq!(normalized_view.size, size(232., 232.), "Visible-size normalization changes projection");
// Same East edge target x214, same fixed x0/y0/bottom232.
// Preserve the authored inactive dimension versus normalize it.
let minimal = edit(&p, d, n, size(214., 160.));
let minimal_view = projected(&minimal, d, n);
let normalized_shrink = edit(&p, d, n, size(214., 232.));
let normalized_shrink_view = projected(&normalized_shrink, d, n);
println!("minimal shrink {minimal_view:?}");
println!("normalized shrink {normalized_shrink_view:?}");
assert_eq!(minimal_view.size, size(214., 232.));
assert_eq!(normalized_shrink_view.size, size(232., 232.));
assert_eq!(minimal_view.position, baseline.position);
let mut restored = minimal.clone();
restored.diagrams.get_mut(&d).unwrap().nodes.insert(n, p.diagrams[&d].nodes[&n].clone());
assert_eq!(restored, p, "Only selected placement changed");
for view in [project_diagram(&p, &p.diagrams[&d]), project_diagram(&minimal, &minimal.diagrams[&d])] {
for port in view.ports.iter().filter(|v| v.owner == n) {
assert_eq!(port.side, PortAnchorSide::Right);
}
}
}
fn grandfather_floor_falsifier() {
let mut p = Project::empty();
let a = p.add_element(Kind::Entity, Layer::Oa, "Small valid card", None).unwrap();
let d = p.ensure_diagram(Layer::Oa);
let n = p.place(d, a, pos(0., 0.));
p.diagrams.get_mut(&d).unwrap().nodes.get_mut(&n).unwrap().size = size(100., 50.);
valid("small baseline", &p);
assert_eq!(projected(&p, d, n).size, size(100., 50.));
let grown = edit(&p, d, n, size(110., 50.));
assert_eq!(projected(&grown, d, n).size, size(110., 50.));
println!("Valid E enlargement 100x50 -> 110x50 exists; global 184x94 pointer floor plus fixed inactive height rejects it.");
}
fn main() {
normalization_falsifier(false);
normalization_falsifier(true);
grandfather_floor_falsifier();
println!("PASS: actual-core normalization and minimum-policy falsifiers");
}