use brick::model::{EdgeKind, NodeKind}; use brick::scan; use std::fs; fn scan_files(files: &[(&str, &str)]) -> brick::Building { let root = tempfile::tempdir().unwrap(); for (path, content) in files { let file = root.path().join(path); fs::create_dir_all(file.parent().unwrap()).unwrap(); fs::write(file, content).unwrap(); } scan::scan(root.path()).unwrap() } fn target<'a>(model: &'a brick::Building, name: &str) -> &'a brick::model::Node { let source = model .nodes .iter() .find(|n| n.kind == NodeKind::Function && n.name == name) .unwrap(); let edge = model .edges .iter() .find(|e| e.kind == EdgeKind::Calls && e.source == source.id) .unwrap(); model.nodes.iter().find(|n| n.id == edge.target).unwrap() } #[test] fn nested_groups_aliases_and_module_self_bindings_resolve_exactly() { let model = scan_files(&[ ( "src/lib.rs", "use crate::service::{self as svc, run as execute, nested::{stop}};\nfn a() { execute(); }\nfn b() { stop(); }\nfn c() { svc::run(); }", ), ("src/service.rs", "pub fn run() {}"), ("src/service/nested.rs", "pub fn stop() {}"), ("other/run.rs", "pub fn execute() {}"), ]); for (source, path, name) in [ ("a", "src/service.rs", "run"), ("b", "src/service/nested.rs", "stop"), ("c", "src/service.rs", "run"), ] { let node = target(&model, source); assert_eq!(node.path.as_deref(), Some(path)); assert_eq!(node.name, name); } assert!(!model.nodes.iter().any(|n| n.kind == NodeKind::External)); assert_eq!( model .edges .iter() .filter(|e| e.kind == EdgeKind::Imports) .count(), 2 ); } #[test] fn absent_private_wildcard_and_underscore_imports_cannot_authorize_calls() { let model = scan_files(&[ ( "src/lib.rs", "use crate::service::{hidden, run as _, *};\nuse crate::missing::{run as missing};\nfn a() { hidden(); }\nfn b() { run(); }\nfn c() { missing(); }", ), ("src/service.rs", "fn hidden() {}\npub fn run() {}"), ]); for name in ["a", "b", "c"] { assert_eq!(target(&model, name).kind, NodeKind::External); } } #[test] fn block_imports_do_not_leak_to_other_functions() { let model = scan_files(&[ ( "src/lib.rs", "fn a() { use crate::service::run as execute; execute(); }\nfn b() { execute(); }", ), ("src/service.rs", "pub fn run() {}"), ]); assert_eq!(target(&model, "b").kind, NodeKind::External); }