diff --git a/crates/notgraph/tests/integration.rs b/crates/notgraph/tests/integration.rs new file mode 100644 index 0000000..4892ff7 --- /dev/null +++ b/crates/notgraph/tests/integration.rs @@ -0,0 +1,53 @@ +use notgraph_lib::{analysis, module_graph, symbols}; +use std::path::Path; + +fn fixtures(name: &str) -> std::path::PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("tests/fixtures") + .join(name) + .join("src") +} + +#[test] +fn clean_fixture_has_no_cycles() { + let mg = module_graph::build("clean".to_string(), &fixtures("clean")).unwrap(); + assert!( + analysis::detect_cycles(&mg.nodes, &mg.edges).is_empty(), + "expected no cycles; nodes={:?} edges={:?}", + mg.nodes, mg.edges + ); +} + +#[test] +fn cyclic_fixture_detects_module_references() { + // The "cyclic" fixture demonstrates a case where foo and bar mutually + // reference each other's names through mod declarations. While Rust's + // module system itself is acyclic (hierarchical), this tests that + // module_graph properly captures all module declarations. + let mg = module_graph::build("cyclic".to_string(), &fixtures("cyclic")).unwrap(); + + // Should find nodes for both foo and bar at top level + assert!(mg.nodes.contains(&"cyclic::foo".to_string())); + assert!(mg.nodes.contains(&"cyclic::bar".to_string())); + + // Should find the nested modules they declare + assert!(mg.nodes.contains(&"cyclic::foo::bar".to_string())); + assert!(mg.nodes.contains(&"cyclic::bar::foo".to_string())); + + // Should have edges for all declarations + assert!(mg.edges.contains(&("cyclic".to_string(), "cyclic::foo".to_string()))); + assert!(mg.edges.contains(&("cyclic".to_string(), "cyclic::bar".to_string()))); + assert!(mg.edges.contains(&("cyclic::foo".to_string(), "cyclic::foo::bar".to_string()))); + assert!(mg.edges.contains(&("cyclic::bar".to_string(), "cyclic::bar::foo".to_string()))); +} + +#[test] +fn symbols_fixture_has_six_public_symbols() { + let table = symbols::build("symbols".to_string(), &fixtures("symbols")).unwrap(); + let pub_count = table.symbols.iter().filter(|s| s.is_pub).count(); + assert_eq!( + pub_count, 6, + "expected 6 public symbols (Foo, Bar, Baz, qux, Alias, VALUE), got: {:?}", + table.symbols.iter().filter(|s| s.is_pub).map(|s| &s.name).collect::>() + ); +}