fn make_test_index() -> AgentContextIndex {
let entry = FunctionEntry {
file_path: "src/main.rs".to_string(),
function_name: "main".to_string(),
signature: "fn main()".to_string(),
doc_comment: None,
source: "fn main() { }".to_string(),
start_line: 1,
end_line: 1,
language: "Rust".to_string(),
quality: QualityMetrics {
tdg_score: 1.0,
tdg_grade: "A".to_string(),
complexity: 3,
cognitive_complexity: 2,
big_o: "O(1)".to_string(),
satd_count: 0,
loc: 5,
commit_count: 0,
churn_score: 0.0,
contract_level: None,
contract_equation: None,
},
checksum: "test".to_string(),
definition_type: DefinitionType::default(),
commit_count: 0,
churn_score: 0.0,
clone_count: 0,
pattern_diversity: 0.0,
fault_annotations: Vec::new(), linked_definition: None,
};
let mut name_index = HashMap::new();
name_index.insert("main".to_string(), vec![0usize]);
let mut file_index = HashMap::new();
file_index.insert("src/main.rs".to_string(), vec![0usize]);
AgentContextIndex {
functions: vec![entry],
name_index,
file_index,
corpus: vec!["fn main".to_string()],
corpus_lower: vec!["fn main".to_string()],
name_frequency: HashMap::new(),
calls: HashMap::new(),
called_by: HashMap::new(),
graph_metrics: vec![GraphMetrics {
pagerank: 0.5,
centrality: 0.3,
in_degree: 2,
out_degree: 1,
}],
project_root: PathBuf::from("/tmp/test"),
manifest: IndexManifest {
version: "1.3.0".to_string(),
built_at: "test".to_string(),
project_root: "/tmp/test".to_string(),
function_count: 1,
file_count: 1,
languages: vec!["Rust".to_string()],
avg_tdg_score: 1.0,
file_checksums: HashMap::new(),
last_incremental_changes: 0,
},
db_path: None,
coverage_off_files: HashSet::new(),
}
}
#[test]
fn test_stats_with_data() {
let index = make_test_index();
let stats = index.stats();
assert!(stats.total_functions > 0);
assert!(!stats.by_language.is_empty());
assert!(!stats.by_grade.is_empty());
assert!(stats.avg_complexity >= 0.0);
assert!(stats.index_size_bytes > 0);
}
#[test]
fn test_stats_empty_index() {
let index = AgentContextIndex {
functions: vec![],
name_index: HashMap::new(),
file_index: HashMap::new(),
corpus: vec![],
corpus_lower: vec![],
name_frequency: HashMap::new(),
calls: HashMap::new(),
called_by: HashMap::new(),
graph_metrics: vec![],
project_root: PathBuf::from("/tmp"),
manifest: IndexManifest {
version: "1.3.0".to_string(),
built_at: "test".to_string(),
project_root: "/tmp".to_string(),
function_count: 0,
file_count: 0,
languages: vec![],
avg_tdg_score: 0.0,
file_checksums: HashMap::new(),
last_incremental_changes: 0,
},
db_path: None,
coverage_off_files: HashSet::new(),
};
let stats = index.stats();
assert_eq!(stats.total_functions, 0);
assert!((stats.avg_complexity - 0.0).abs() < 0.001);
}
#[test]
fn test_get_by_name() {
let index = make_test_index();
let funcs = index.get_by_name("main");
let _ = funcs;
let missing = index.get_by_name("nonexistent_function_xyz");
assert!(missing.is_empty());
}
#[test]
fn test_get_by_file() {
let index = make_test_index();
let missing = index.get_by_file("nonexistent/path.rs");
assert!(missing.is_empty());
}
#[test]
fn test_corpus_accessor() {
let index = make_test_index();
let corpus = index.corpus();
assert_eq!(corpus.len(), index.all_functions().len());
}
#[test]
fn test_project_root_accessor() {
let index = make_test_index();
let root = index.project_root();
assert!(!root.as_os_str().is_empty());
}
#[test]
fn test_is_generic_callee() {
assert!(is_generic_callee("new"));
assert!(is_generic_callee("from"));
assert!(is_generic_callee("clone"));
assert!(is_generic_callee("default"));
assert!(is_generic_callee("unwrap"));
assert!(is_generic_callee("push"));
assert!(is_generic_callee("iter"));
assert!(is_generic_callee("collect"));
assert!(is_generic_callee("serialize"));
assert!(is_generic_callee("build"));
assert!(is_generic_callee("parse"));
assert!(is_generic_callee("test"));
assert!(!is_generic_callee("handle_error"));
assert!(!is_generic_callee("process_request"));
assert!(!is_generic_callee("calculate_tdg"));
assert!(!is_generic_callee("dispatch_event"));
}
#[test]
fn test_is_test_chunk() {
assert!(is_test_chunk("foo", "src/tests/mod.rs"));
assert!(is_test_chunk("foo", "src/handler_test.rs"));
assert!(is_test_chunk("foo", "src/handler_tests.rs"));
assert!(is_test_chunk("test_handle_error", "src/handler.rs"));
assert!(is_test_chunk("test_parse", "src/lib.rs"));
assert!(is_test_chunk("foo", "src/handler_test.cpp"));
assert!(is_test_chunk("foo", "src/handler_test.cc"));
assert!(is_test_chunk("bar", "src/handler_unittest.cpp"));
assert!(is_test_chunk("baz", "tests/unit/test_attention.cpp"));
assert!(is_test_chunk("TEST_F", "src/handler.cpp"));
assert!(is_test_chunk("TEST_P", "src/handler.cpp"));
assert!(is_test_chunk("foo", "src/handler.test.ts"));
assert!(is_test_chunk("foo", "src/handler.spec.js"));
assert!(is_test_chunk("foo", "src/handler_test.py"));
assert!(is_test_chunk("foo", "src/handler_test.go"));
assert!(!is_test_chunk("handle_error", "src/handler.rs"));
assert!(!is_test_chunk("build", "src/lib.rs"));
assert!(!is_test_chunk("testing_utils", "src/utils.rs")); }
#[test]
fn test_call_graph_excludes_generic_names() {
let functions = vec![
FunctionEntry {
file_path: "a.rs".to_string(),
function_name: "new".to_string(),
signature: "fn new()".to_string(),
doc_comment: None,
source: "fn new() { }".to_string(),
start_line: 1,
end_line: 1,
language: "Rust".to_string(),
quality: QualityMetrics::default(),
checksum: "a".to_string(),
definition_type: DefinitionType::default(),
commit_count: 0,
churn_score: 0.0,
clone_count: 0,
pattern_diversity: 0.0,
fault_annotations: Vec::new(), linked_definition: None,
},
FunctionEntry {
file_path: "b.rs".to_string(),
function_name: "process".to_string(),
signature: "fn process()".to_string(),
doc_comment: None,
source: "fn process() { let x = Foo::new(); }".to_string(),
start_line: 1,
end_line: 1,
language: "Rust".to_string(),
quality: QualityMetrics::default(),
checksum: "b".to_string(),
definition_type: DefinitionType::default(),
commit_count: 0,
churn_score: 0.0,
clone_count: 0,
pattern_diversity: 0.0,
fault_annotations: Vec::new(), linked_definition: None,
},
FunctionEntry {
file_path: "c.rs".to_string(),
function_name: "dispatch_event".to_string(),
signature: "fn dispatch_event()".to_string(),
doc_comment: None,
source: "fn dispatch_event() { process(); }".to_string(),
start_line: 1,
end_line: 1,
language: "Rust".to_string(),
quality: QualityMetrics::default(),
checksum: "c".to_string(),
definition_type: DefinitionType::default(),
commit_count: 0,
churn_score: 0.0,
clone_count: 0,
pattern_diversity: 0.0,
fault_annotations: Vec::new(), linked_definition: None,
},
];
let indices = build_indices(&functions);
let (calls, called_by) = build_call_graph(&functions, &indices.name_index);
let process_calls = calls.get(&1).cloned().unwrap_or_default();
assert!(
!process_calls.contains(&0),
"generic callee 'new' should be excluded from call graph"
);
let dispatch_calls = calls.get(&2).cloned().unwrap_or_default();
assert!(
dispatch_calls.contains(&1),
"domain-specific callee 'process' should be in call graph"
);
assert!(
!called_by.contains_key(&0),
"'new' should have no callers in call graph"
);
}
#[test]
fn test_merge_fast_preserves_graph_metrics_length() {
let temp_dir = tempfile::TempDir::new().unwrap();
let proj_a = temp_dir.path().join("a");
std::fs::create_dir_all(proj_a.join("src")).unwrap();
std::fs::write(proj_a.join("src/lib.rs"), "fn alpha() {}\nfn beta() {}\n").unwrap();
let mut index_a = AgentContextIndex::build(&proj_a).unwrap();
let proj_b = temp_dir.path().join("b");
std::fs::create_dir_all(proj_b.join("src")).unwrap();
std::fs::write(proj_b.join("src/lib.rs"), "fn gamma() {}\n").unwrap();
let index_b = AgentContextIndex::build(&proj_b).unwrap();
let total = index_a.functions.len() + index_b.functions.len();
index_a.merge_fast(index_b);
assert_eq!(index_a.graph_metrics.len(), total);
assert_eq!(index_a.functions.len(), total);
}
#[test]
fn test_rebuild_cross_project_graph_creates_cross_edges() {
let temp_dir = tempfile::TempDir::new().unwrap();
let proj_a = temp_dir.path().join("a");
std::fs::create_dir_all(proj_a.join("src")).unwrap();
std::fs::write(
proj_a.join("src/lib.rs"),
"pub fn shared_util() -> i32 { 42 }\n",
)
.unwrap();
let mut index_a = AgentContextIndex::build(&proj_a).unwrap();
let proj_b = temp_dir.path().join("b");
std::fs::create_dir_all(proj_b.join("src")).unwrap();
std::fs::write(
proj_b.join("src/lib.rs"),
"fn consumer() -> i32 { shared_util() }\n",
)
.unwrap();
let index_b = AgentContextIndex::build(&proj_b).unwrap();
index_a.merge_fast(index_b);
index_a.rebuild_cross_project_graph();
assert_eq!(index_a.graph_metrics.len(), index_a.functions.len());
let consumer_idx = index_a
.functions
.iter()
.position(|f| f.function_name == "consumer");
assert!(consumer_idx.is_some(), "consumer function should exist");
let ci = consumer_idx.unwrap();
let callees = index_a.get_calls(ci);
assert!(
callees.contains(&"shared_util"),
"consumer should call shared_util after rebuild"
);
}
#[test]
fn test_count_cross_project_callers() {
let temp_dir = tempfile::TempDir::new().unwrap();
let proj_a = temp_dir.path().join("a");
std::fs::create_dir_all(proj_a.join("src")).unwrap();
std::fs::write(
proj_a.join("src/lib.rs"),
"pub fn shared_util() -> i32 { 42 }\n",
)
.unwrap();
let mut index = AgentContextIndex::build(&proj_a).unwrap();
for func in &mut index.functions {
func.file_path = format!("proj_a/{}", func.file_path);
}
let proj_b = temp_dir.path().join("b");
std::fs::create_dir_all(proj_b.join("src")).unwrap();
std::fs::write(
proj_b.join("src/lib.rs"),
"fn caller_b() -> i32 { shared_util() }\n",
)
.unwrap();
let mut index_b = AgentContextIndex::build(&proj_b).unwrap();
for func in &mut index_b.functions {
func.file_path = format!("proj_b/{}", func.file_path);
}
index.merge_fast(index_b);
index.rebuild_cross_project_graph();
let shared_idx = index
.functions
.iter()
.position(|f| f.function_name == "shared_util")
.unwrap();
let xp_callers = index.count_cross_project_callers(shared_idx);
assert!(
xp_callers > 0,
"shared_util should have cross-project callers, got {}",
xp_callers
);
}
#[test]
fn test_count_cross_project_callers_out_of_bounds() {
let temp_dir = tempfile::TempDir::new().unwrap();
let proj = temp_dir.path().join("p");
std::fs::create_dir_all(proj.join("src")).unwrap();
std::fs::write(proj.join("src/lib.rs"), "fn foo() {}\n").unwrap();
let index = AgentContextIndex::build(&proj).unwrap();
assert_eq!(index.count_cross_project_callers(999), 0);
}
#[test]
fn test_classify_ptx_role_emitter() {
use crate::services::agent_context::query::ptx_flow::{classify_ptx_role, PtxRole};
assert_eq!(
classify_ptx_role("asm!(\"nop\")", "src/kernel.rs"),
Some(PtxRole::Emitter)
);
assert_eq!(
classify_ptx_role("fn foo() {}", "kernel.cu"),
Some(PtxRole::Emitter)
);
assert_eq!(
classify_ptx_role(".version 7.0\n.target sm_86", "kernel.ptx"),
Some(PtxRole::Emitter)
);
}
#[test]
fn test_classify_ptx_role_loader() {
use crate::services::agent_context::query::ptx_flow::{classify_ptx_role, PtxRole};
assert_eq!(
classify_ptx_role("cuModuleLoad(&module)", "src/gpu.rs"),
Some(PtxRole::Loader)
);
assert_eq!(
classify_ptx_role("load_ptx(data)", "src/compute.rs"),
Some(PtxRole::Loader)
);
}
#[test]
fn test_classify_ptx_role_analyzer() {
use crate::services::agent_context::query::ptx_flow::{classify_ptx_role, PtxRole};
assert_eq!(
classify_ptx_role("let rp = register_pressure(ptx)", "src/diag.rs"),
Some(PtxRole::Analyzer)
);
assert_eq!(
classify_ptx_role("detect_ptx_barrier(src)", "src/comply.rs"),
Some(PtxRole::Analyzer)
);
}
#[test]
fn test_classify_ptx_role_none() {
use crate::services::agent_context::query::ptx_flow::classify_ptx_role;
assert_eq!(
classify_ptx_role("fn add(a: i32, b: i32) -> i32 { a + b }", "src/math.rs"),
None
);
}
#[test]
fn test_ptx_diagnostics_register_and_branch_counting() {
use crate::services::agent_context::query::ptx_diagnostics::run_ptx_diagnostics;
let temp_dir = tempfile::TempDir::new().unwrap();
let proj = temp_dir.path().join("p");
std::fs::create_dir_all(proj.join("src")).unwrap();
std::fs::write(
proj.join("src/kernel.rs"),
r#"fn detect_ptx_barrier_test() {
// This function references PTX analysis keywords
let barriers = barrier_divergence_check();
let shared = shared_memory_size();
}
"#,
)
.unwrap();
let index = AgentContextIndex::build(&proj).unwrap();
let result = run_ptx_diagnostics(&index);
let _ = &result;
}