#[cfg(test)]
mod tests {
use super::*;
fn make_result(name: &str, def_type: &str, source: &str, file: &str) -> QueryResult {
QueryResult {
file_path: file.to_string(),
function_name: name.to_string(),
signature: format!("fn {}()", name),
definition_type: def_type.to_string(),
doc_comment: None,
start_line: 1,
end_line: 10,
language: "rust".to_string(),
tdg_score: 0.5,
tdg_grade: "C".to_string(),
complexity: 5,
big_o: "O(n)".to_string(),
satd_count: 0,
loc: 10,
relevance_score: 0.0,
source: Some(source.to_string()),
calls: Vec::new(),
called_by: Vec::new(),
pagerank: 0.0,
in_degree: 0,
out_degree: 0,
commit_count: 0,
churn_score: 0.0,
clone_count: 0,
duplication_score: 0.0,
pattern_diversity: 0.0,
fault_annotations: Vec::new(),
line_coverage_pct: 0.0,
lines_covered: 0,
lines_total: 0,
missed_lines: 0,
impact_score: 0.0,
coverage_status: String::new(),
coverage_diff: 0.0,
coverage_exclusion:
crate::services::agent_context::query::coverage_exclusion::CoverageExclusion::None,
coverage_excluded: false,
cross_project_callers: 0,
io_classification: String::new(),
io_patterns: Vec::new(),
suggested_module: String::new(),
}
}
#[test]
fn test_classify_io_pure_function() {
let source = "fn add(a: i32, b: i32) -> i32 { a + b }";
let (class, patterns) = classify_io(source);
assert_eq!(class, "PURE");
assert!(patterns.is_empty());
}
#[test]
fn test_classify_io_print() {
let source = r#"fn greet() { println!("hello"); }"#;
let (class, patterns) = classify_io(source);
assert_eq!(class, "IO");
assert!(patterns.contains(&"PRINT".to_string()));
}
#[test]
fn test_classify_io_filesystem() {
let source = r#"fn read_file() { let f = File::open("test.txt"); }"#;
let (class, patterns) = classify_io(source);
assert_eq!(class, "IO");
assert!(patterns.contains(&"FS".to_string()));
}
#[test]
fn test_classify_io_multiple_patterns() {
let source =
r#"fn do_stuff() { println!("hi"); let f = File::open("x"); Command::new("ls"); }"#;
let (class, patterns) = classify_io(source);
assert_eq!(class, "IO");
assert!(patterns.contains(&"PRINT".to_string()));
assert!(patterns.contains(&"FS".to_string()));
assert!(patterns.contains(&"PROCESS".to_string()));
}
#[test]
fn test_classify_io_database() {
let source = r#"fn query_db() { rusqlite::Connection::open("db"); }"#;
let (class, patterns) = classify_io(source);
assert_eq!(class, "IO");
assert!(patterns.contains(&"DB".to_string()));
}
#[test]
fn test_group_by_prefix_minimum_three() {
let results = vec![
make_result("handle_get", "function", "fn x() {}", "src/handlers.rs"),
make_result("handle_post", "function", "fn x() {}", "src/handlers.rs"),
];
let groups = group_by_prefix(&results);
assert!(groups.is_empty());
let results3 = vec![
make_result("handle_get", "function", "fn x() {}", "src/handlers.rs"),
make_result("handle_post", "function", "fn x() {}", "src/handlers.rs"),
make_result("handle_delete", "function", "fn x() {}", "src/handlers.rs"),
];
let groups3 = group_by_prefix(&results3);
assert!(groups3.contains_key("handle"));
assert_eq!(groups3["handle"].len(), 3);
}
#[test]
fn test_group_by_prefix_ignores_non_functions() {
let results = vec![
make_result("handle_get", "function", "fn x() {}", "src/lib.rs"),
make_result("handle_post", "function", "fn x() {}", "src/lib.rs"),
make_result("handle_delete", "function", "fn x() {}", "src/lib.rs"),
make_result(
"HandleConfig",
"struct",
"struct HandleConfig {}",
"src/lib.rs",
),
];
let groups = group_by_prefix(&results);
assert!(groups.contains_key("handle"));
assert_eq!(groups["handle"].len(), 3);
}
#[test]
fn test_build_extraction_groups_max_lines() {
let mut results = vec![
make_result("parse_header", "function", "fn x() {}", "src/parser.rs"),
make_result("parse_body", "function", "fn x() {}", "src/parser.rs"),
make_result("parse_footer", "function", "fn x() {}", "src/parser.rs"),
];
for r in &mut results {
r.loc = 200;
}
classify_all_results(&mut results);
let prefix_groups = group_by_prefix(&results);
let cluster_groups = HashMap::new();
let groups = build_extraction_groups(&results, &prefix_groups, &cluster_groups, 500);
assert!(groups.is_empty() || groups[0].total_loc <= 500);
let groups = build_extraction_groups(&results, &prefix_groups, &cluster_groups, 700);
assert_eq!(groups.len(), 1);
assert_eq!(groups[0].functions.len(), 3);
}
#[test]
fn test_longest_common_prefix() {
assert_eq!(
longest_common_prefix(&["handle_get", "handle_post", "handle_delete"]),
"handle"
);
assert_eq!(
longest_common_prefix(&["parse_header", "parse_body"]),
"parse"
);
assert_eq!(longest_common_prefix(&["abc", "def"]), "");
assert_eq!(longest_common_prefix(&[]), "");
}
}