//! 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"); }