refactor: modularize codebase and add 404 unit tests (#13)
All checks were successful
CI / Format (push) Successful in 4s
CI / Clippy (push) Successful in 4m19s
CI / Security Audit (push) Successful in 1m44s
CI / Detect Changes (push) Successful in 5s
CI / Tests (push) Successful in 5m15s
CI / Deploy Agent (push) Successful in 2s
CI / Deploy Dashboard (push) Successful in 2s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 2s

This commit was merged in pull request #13.
This commit is contained in:
2026-03-13 08:03:45 +00:00
parent acc5b86aa4
commit 3bb690e5bb
89 changed files with 11884 additions and 6046 deletions

View File

@@ -128,3 +128,186 @@ impl SymbolIndex {
Ok(results)
}
}
#[cfg(test)]
mod tests {
use super::*;
use compliance_core::models::graph::CodeNodeKind;
fn make_node(
qualified_name: &str,
name: &str,
kind: CodeNodeKind,
file_path: &str,
language: &str,
) -> CodeNode {
CodeNode {
id: None,
repo_id: "test".to_string(),
graph_build_id: "build1".to_string(),
qualified_name: qualified_name.to_string(),
name: name.to_string(),
kind,
file_path: file_path.to_string(),
start_line: 1,
end_line: 10,
language: language.to_string(),
community_id: None,
is_entry_point: false,
graph_index: None,
}
}
#[test]
fn test_new_creates_index() {
let index = SymbolIndex::new();
assert!(index.is_ok());
}
#[test]
fn test_index_empty_nodes() {
let index = SymbolIndex::new().unwrap();
let result = index.index_nodes(&[]);
assert!(result.is_ok());
}
#[test]
fn test_index_and_search_single_node() {
let index = SymbolIndex::new().unwrap();
let nodes = vec![make_node(
"src/main.rs::main",
"main",
CodeNodeKind::Function,
"src/main.rs",
"rust",
)];
index.index_nodes(&nodes).unwrap();
let results = index.search("main", 10).unwrap();
assert!(!results.is_empty());
assert_eq!(results[0].name, "main");
assert_eq!(results[0].qualified_name, "src/main.rs::main");
}
#[test]
fn test_search_no_results() {
let index = SymbolIndex::new().unwrap();
let nodes = vec![make_node(
"src/main.rs::foo",
"foo",
CodeNodeKind::Function,
"src/main.rs",
"rust",
)];
index.index_nodes(&nodes).unwrap();
let results = index.search("zzzznonexistent", 10).unwrap();
assert!(results.is_empty());
}
#[test]
fn test_search_multiple_nodes() {
let index = SymbolIndex::new().unwrap();
let nodes = vec![
make_node(
"a.rs::handle_request",
"handle_request",
CodeNodeKind::Function,
"a.rs",
"rust",
),
make_node(
"b.rs::handle_response",
"handle_response",
CodeNodeKind::Function,
"b.rs",
"rust",
),
make_node(
"c.rs::process_data",
"process_data",
CodeNodeKind::Function,
"c.rs",
"rust",
),
];
index.index_nodes(&nodes).unwrap();
let results = index.search("handle", 10).unwrap();
assert!(results.len() >= 2);
}
#[test]
fn test_search_limit() {
let index = SymbolIndex::new().unwrap();
let mut nodes = Vec::new();
for i in 0..20 {
nodes.push(make_node(
&format!("mod::func_{i}"),
&format!("func_{i}"),
CodeNodeKind::Function,
"mod.rs",
"rust",
));
}
index.index_nodes(&nodes).unwrap();
let results = index.search("func", 5).unwrap();
assert!(results.len() <= 5);
}
#[test]
fn test_search_result_has_score() {
let index = SymbolIndex::new().unwrap();
let nodes = vec![make_node(
"src/lib.rs::compute",
"compute",
CodeNodeKind::Function,
"src/lib.rs",
"rust",
)];
index.index_nodes(&nodes).unwrap();
let results = index.search("compute", 10).unwrap();
assert!(!results.is_empty());
assert!(results[0].score > 0.0);
}
#[test]
fn test_search_result_fields() {
let index = SymbolIndex::new().unwrap();
let nodes = vec![make_node(
"src/app.py::MyClass",
"MyClass",
CodeNodeKind::Class,
"src/app.py",
"python",
)];
index.index_nodes(&nodes).unwrap();
let results = index.search("MyClass", 10).unwrap();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "MyClass");
assert_eq!(results[0].kind, "class");
assert_eq!(results[0].file_path, "src/app.py");
assert_eq!(results[0].language, "python");
}
#[test]
fn test_search_empty_query() {
let index = SymbolIndex::new().unwrap();
let nodes = vec![make_node(
"src/lib.rs::foo",
"foo",
CodeNodeKind::Function,
"src/lib.rs",
"rust",
)];
index.index_nodes(&nodes).unwrap();
// Empty query may parse error or return empty - both acceptable
let result = index.search("", 10);
// Just verify it doesn't panic
let _ = result;
}
}