use super::*;
#[test]
fn fixed_point_analysis_plan_retains_graph_and_program() {
let graph = FixedPointForwardGraph::new(
"fixed_point_analysis_plan_test",
2,
&[0, 1, 1],
&[1],
&[vyre_primitives::predicate::edge_kind::CONTROL],
)
.expect("valid graph must pack");
let program = vyre_primitives::graph::csr_forward_traverse::csr_forward_traverse(
vyre_primitives::graph::program_graph::ProgramGraphShape::new(2, 1),
"fin",
"fout",
u32::MAX,
);
let plan = FixedPointAnalysisPlan::new(graph, program);
assert_eq!(plan.graph().node_count(), 2);
assert_eq!(plan.kind(), FixedPointAnalysisKind::Generic);
assert!(!plan.program().entry().is_empty());
assert!(plan.retained_graph_bytes() >= 28);
}
#[test]
fn fixed_point_analysis_plan_rejects_wrong_analysis_family() {
let graph = FixedPointForwardGraph::new_for_kind(
FixedPointAnalysisKind::Live,
"fixed_point_analysis_plan_kind_test",
2,
&[0, 1, 1],
&[1],
&[vyre_primitives::predicate::edge_kind::CONTROL],
)
.expect("valid graph must pack");
let program = vyre_primitives::graph::csr_forward_traverse::csr_forward_traverse(
vyre_primitives::graph::program_graph::ProgramGraphShape::new(2, 1),
"fin",
"fout",
u32::MAX,
);
let plan = FixedPointAnalysisPlan::new_for_kind(FixedPointAnalysisKind::Live, graph, program);
let err = plan
.require_kind(FixedPointAnalysisKind::Reaching, "reaching_plan")
.expect_err("wrong analysis-family plan must be rejected");
assert!(
err.contains("expected Reaching"),
"unexpected diagnostic: {err}"
);
assert!(plan
.require_kind(FixedPointAnalysisKind::Live, "live_plan")
.is_ok());
}
#[test]
fn fixed_point_forward_graph_rejects_wrong_analysis_family() {
let graph = FixedPointForwardGraph::new_for_kind(
FixedPointAnalysisKind::Live,
"fixed_point_graph_kind_test",
2,
&[0, 1, 1],
&[1],
&[vyre_primitives::predicate::edge_kind::CONTROL],
)
.expect("valid graph must pack");
let err = graph
.require_kind(FixedPointAnalysisKind::Reaching, "reaching_prepared")
.expect_err("wrong analysis-family graph must be rejected");
assert!(
err.contains("expected Reaching"),
"unexpected diagnostic: {err}"
);
assert_eq!(graph.kind(), FixedPointAnalysisKind::Live);
}
#[test]
fn fixed_point_analysis_plan_rejects_mismatched_graph_family() {
let graph = FixedPointForwardGraph::new_for_kind(
FixedPointAnalysisKind::Live,
"fixed_point_plan_graph_kind_test",
2,
&[0, 1, 1],
&[1],
&[vyre_primitives::predicate::edge_kind::CONTROL],
)
.expect("valid graph must pack");
let program = vyre_primitives::graph::csr_forward_traverse::csr_forward_traverse(
vyre_primitives::graph::program_graph::ProgramGraphShape::new(2, 1),
"fin",
"fout",
u32::MAX,
);
let plan =
FixedPointAnalysisPlan::new_for_kind(FixedPointAnalysisKind::Reaching, graph, program);
let err = plan
.require_kind(FixedPointAnalysisKind::Reaching, "reaching_plan")
.expect_err("plan with mismatched graph family must be rejected");
assert!(
err.contains("fixed-point graph"),
"unexpected diagnostic: {err}"
);
}
#[test]
fn fixed_point_analysis_plan_exposes_stable_graph_layout_hash() {
let graph = FixedPointForwardGraph::new(
"fixed_point_analysis_plan_hash_test",
2,
&[0, 1, 1],
&[1],
&[vyre_primitives::predicate::edge_kind::CONTROL],
)
.expect("valid graph must pack");
let expected_hash = graph.stable_layout_hash();
let program = vyre_primitives::graph::csr_forward_traverse::csr_forward_traverse(
vyre_primitives::graph::program_graph::ProgramGraphShape::new(2, 1),
"fin",
"fout",
u32::MAX,
);
let plan = FixedPointAnalysisPlan::new(graph, program);
assert_eq!(plan.stable_layout_hash(), expected_hash);
assert_ne!(plan.stable_layout_hash(), 0);
}
#[test]
fn production_fixed_point_paths_do_not_construct_generic_graphs_or_plans() {
fn scan_rs_files(
dir: &std::path::Path,
findings: &mut Vec<String>,
) -> Result<(), std::io::Error> {
for entry in std::fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
scan_rs_files(&path, findings)?;
continue;
}
if path.extension().and_then(std::ffi::OsStr::to_str) != Some("rs") {
continue;
}
let Some(name) = path.file_name().and_then(std::ffi::OsStr::to_str) else {
continue;
};
if name == "tests.rs" || name == "lib.rs" {
continue;
}
let source = std::fs::read_to_string(&path)?;
let production_source = source.split("#[cfg(test)]").next().unwrap_or(&source);
if production_source.contains("FixedPointForwardGraph::new(")
|| production_source.contains("FixedPointAnalysisPlan::new(")
{
findings.push(path.display().to_string());
}
}
Ok(())
}
let mut findings = Vec::new();
let src = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
scan_rs_files(&src, &mut findings).expect("source tree scan must succeed");
assert!(
findings.is_empty(),
"production fixed-point paths must use analysis-typed constructors, not Generic compatibility constructors: {findings:?}"
);
}