brick/tests/rust_imports.rs
trvon 01836ba3f5
Some checks failed
build / build-linux (push) Successful in 1m9s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
feat: resolve Rust grouped imports and module aliases
Expand module-scoped use trees into exact import paths and bindings. Resolve renamed public symbols and module aliases without global-name fallback; keep unknown and block-local bindings conservative.

Add positive and negative integration tests and an exact three-repeat import benchmark to the quality gate.
2026-09-04 23:11:19 -06:00

84 lines
2.6 KiB
Rust

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);
}