#![cfg(feature = "geometric-backend")]
use std::path::PathBuf;
use tempfile::tempdir;
use magellan::graph::geometric_backend::{GeometricBackend, InsertSymbol};
use magellan::ingest::{Language, SymbolKind};
fn temp_geo_path() -> (tempfile::TempDir, PathBuf) {
let temp_dir = tempdir().unwrap();
let db_path = temp_dir.path().join("test.geo");
(temp_dir, db_path)
}
fn sample_symbol(id: u64) -> InsertSymbol {
InsertSymbol {
name: format!("test_func_{}", id),
fqn: format!("crate::module::test_func_{}", id),
kind: SymbolKind::Function,
file_path: format!("/home/project/src/file_{}.rs", id % 3),
byte_start: id * 100,
byte_end: id * 100 + 50,
start_line: id * 10,
start_col: 0,
end_line: id * 10 + 5,
end_col: 1,
language: Language::Rust,
}
}
#[test]
fn geometric_persists_symbol_name_metadata() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![sample_symbol(1)];
let ids = backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let info = backend.find_symbol_by_id_info(ids[0]).unwrap();
assert_eq!(info.name, "test_func_1", "Symbol name should be persisted");
}
#[test]
fn geometric_persists_fqn_metadata() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![sample_symbol(1)];
let ids = backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let info = backend.find_symbol_by_id_info(ids[0]).unwrap();
assert_eq!(
info.fqn, "crate::module::test_func_1",
"FQN should be persisted"
);
}
#[test]
fn geometric_persists_file_path_metadata() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![sample_symbol(1)];
let ids = backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let info = backend.find_symbol_by_id_info(ids[0]).unwrap();
assert_eq!(
info.file_path, "/home/project/src/file_1.rs",
"File path should be persisted"
);
}
#[test]
fn geometric_file_count_is_real() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![
sample_symbol(0), sample_symbol(1), sample_symbol(2), sample_symbol(3), ];
backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let stats = backend.get_stats().unwrap();
assert_eq!(stats.file_count, 3, "Should have 3 unique files");
}
#[test]
fn geometric_find_by_name_works_after_reopen() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![sample_symbol(1), sample_symbol(2)];
backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let results = backend.find_symbols_by_name_info("test_func_1");
assert_eq!(results.len(), 1, "Should find exactly one symbol");
assert_eq!(results[0].name, "test_func_1");
assert_eq!(results[0].fqn, "crate::module::test_func_1");
}
#[test]
fn geometric_find_by_fqn_works_after_reopen() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![sample_symbol(1), sample_symbol(2)];
backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let info = backend
.find_symbol_by_fqn_info("crate::module::test_func_2")
.unwrap();
assert_eq!(info.name, "test_func_2");
assert_eq!(info.fqn, "crate::module::test_func_2");
}
#[test]
fn geometric_symbols_in_file_works_after_reopen() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![
sample_symbol(0), sample_symbol(3), sample_symbol(1), ];
backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let results = backend
.symbols_in_file("/home/project/src/file_0.rs")
.unwrap();
assert_eq!(results.len(), 2, "Should find 2 symbols in file_0.rs");
let names: Vec<_> = results.iter().map(|s| s.name.clone()).collect();
assert!(names.contains(&"test_func_0".to_string()));
assert!(names.contains(&"test_func_3".to_string()));
}
#[test]
fn geometric_export_uses_real_metadata_not_placeholders() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![sample_symbol(1)];
backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let json = backend.export_json().unwrap();
assert!(
!json.contains("symbol_1"),
"Export should not contain placeholder names"
);
assert!(
json.contains("test_func_1"),
"Export should contain real name"
);
assert!(
json.contains("crate::module::test_func_1"),
"Export should contain real FQN"
);
assert!(
json.contains("/home/project/src/file_1.rs"),
"Export should contain real file path"
);
}
#[test]
fn geometric_query_returns_real_symbols_not_empty_placeholders() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![sample_symbol(1), sample_symbol(2)];
backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let all = backend.get_all_symbols().unwrap();
assert_eq!(all.len(), 2, "Should return 2 symbols");
for info in &all {
assert!(
!info.name.starts_with("symbol_"),
"Should not have placeholder names"
);
assert!(!info.file_path.is_empty(), "Should have real file paths");
assert!(!info.fqn.is_empty(), "Should have real FQNs");
}
}
#[test]
fn geometric_find_by_name_and_path_works() {
let (_temp_dir, db_path) = temp_geo_path();
let backend = GeometricBackend::create(&db_path).unwrap();
let symbols = vec![
InsertSymbol {
name: "common_name".to_string(),
fqn: "crate::A::common_name".to_string(),
kind: SymbolKind::Function,
file_path: "/src/a.rs".to_string(),
byte_start: 0,
byte_end: 10,
start_line: 0,
start_col: 0,
end_line: 1,
end_col: 0,
language: Language::Rust,
},
InsertSymbol {
name: "common_name".to_string(),
fqn: "crate::B::common_name".to_string(),
kind: SymbolKind::Function,
file_path: "/src/b.rs".to_string(),
byte_start: 0,
byte_end: 10,
start_line: 0,
start_col: 0,
end_line: 1,
end_col: 0,
language: Language::Rust,
},
];
let ids = backend.insert_symbols(symbols).unwrap();
backend.save_to_disk().unwrap();
drop(backend);
let backend = GeometricBackend::open(&db_path).unwrap();
let id_a = backend.find_symbol_id_by_name_and_path("common_name", "/src/a.rs");
assert_eq!(id_a, Some(ids[0]), "Should find symbol in a.rs");
let id_b = backend.find_symbol_id_by_name_and_path("common_name", "/src/b.rs");
assert_eq!(id_b, Some(ids[1]), "Should find symbol in b.rs");
}