use tempfile::TempDir;
#[test]
fn test_multi_language_scan() {
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test.db");
let mut graph = magellan::CodeGraph::open(&db_path).unwrap();
let rust_file = temp_dir.path().join("main.rs");
std::fs::write(
&rust_file,
r#"
fn main() {
println!("Hello");
}
struct Point {
x: i32,
}
"#,
)
.unwrap();
let python_file = temp_dir.path().join("utils.py");
std::fs::write(
&python_file,
r#"
def helper():
pass
class DataProcessor:
def process(self):
pass
"#,
)
.unwrap();
let c_file = temp_dir.path().join("config.c");
std::fs::write(
&c_file,
r#"
int get_config() {
return 0;
}
struct Config {
int value;
};
enum Status {
OK,
Error
};
"#,
)
.unwrap();
let cpp_file = temp_dir.path().join("processor.cpp");
std::fs::write(
&cpp_file,
r#"
class Processor {
public:
void process() {}
};
namespace utils {
struct Helper {};
}
"#,
)
.unwrap();
let java_file = temp_dir.path().join("Main.java");
std::fs::write(
&java_file,
r#"
class Main {
public static void run() {}
}
interface Handler {
void handle();
}
enum Color {
RED, GREEN
}
"#,
)
.unwrap();
let js_file = temp_dir.path().join("app.js");
std::fs::write(
&js_file,
r#"
function init() {
return;
}
class App {
render() {}
}
export function helper() {}
"#,
)
.unwrap();
let ts_file = temp_dir.path().join("types.ts");
std::fs::write(
&ts_file,
r#"
interface Options {
name: string;
}
type Config = string | number;
enum Status {
Pending,
Done
}
namespace utils {
class Helper {}
}
"#,
)
.unwrap();
let file_count = graph.scan_directory(temp_dir.path(), None).unwrap();
assert_eq!(file_count, 7, "Should scan 7 source files");
let rust_symbols = graph.symbols_in_file(rust_file.to_str().unwrap()).unwrap();
assert!(
rust_symbols.len() >= 2,
"Rust file should have at least 2 symbols"
);
let python_symbols = graph
.symbols_in_file(python_file.to_str().unwrap())
.unwrap();
assert!(
python_symbols.len() >= 2,
"Python file should have at least 2 symbols"
);
let c_symbols = graph.symbols_in_file(c_file.to_str().unwrap()).unwrap();
assert!(
c_symbols.len() >= 3,
"C file should have at least 3 symbols"
);
let cpp_symbols = graph.symbols_in_file(cpp_file.to_str().unwrap()).unwrap();
assert!(
cpp_symbols.len() >= 2,
"C++ file should have at least 2 symbols"
);
let java_symbols = graph.symbols_in_file(java_file.to_str().unwrap()).unwrap();
assert!(
java_symbols.len() >= 3,
"Java file should have at least 3 symbols"
);
let js_symbols = graph.symbols_in_file(js_file.to_str().unwrap()).unwrap();
assert!(
js_symbols.len() >= 2,
"JavaScript file should have at least 2 symbols"
);
let ts_symbols = graph.symbols_in_file(ts_file.to_str().unwrap()).unwrap();
assert!(
ts_symbols.len() >= 4,
"TypeScript file should have at least 4 symbols"
);
let rust_functions: Vec<_> = rust_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Function)
.collect();
assert_eq!(rust_functions.len(), 1);
let rust_classes: Vec<_> = rust_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Class)
.collect();
assert_eq!(rust_classes.len(), 1);
let python_functions: Vec<_> = python_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Function)
.collect();
assert_eq!(
python_functions.len(),
2,
"Should have 2 functions (helper + process)"
);
let python_classes: Vec<_> = python_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Class)
.collect();
assert_eq!(python_classes.len(), 1);
let c_enums: Vec<_> = c_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Enum)
.collect();
assert_eq!(c_enums.len(), 1);
let cpp_namespaces: Vec<_> = cpp_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Namespace)
.collect();
assert_eq!(
cpp_namespaces.len(),
1,
"Should have exactly 1 namespace (utils)"
);
let java_interfaces: Vec<_> = java_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Interface)
.collect();
assert_eq!(java_interfaces.len(), 1);
let java_methods: Vec<_> = java_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Method)
.collect();
assert_eq!(
java_methods.len(),
2,
"Should have 2 methods (run + handle)"
);
let ts_interfaces: Vec<_> = ts_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Interface)
.collect();
assert_eq!(ts_interfaces.len(), 1);
let ts_type_aliases: Vec<_> = ts_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::TypeAlias)
.collect();
assert_eq!(ts_type_aliases.len(), 1);
let ts_namespaces: Vec<_> = ts_symbols
.iter()
.filter(|s| s.kind == magellan::SymbolKind::Namespace)
.collect();
assert_eq!(ts_namespaces.len(), 1);
}
#[test]
fn test_scan_filters_unsupported_files() {
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test.db");
let mut graph = magellan::CodeGraph::open(&db_path).unwrap();
let rs_file = temp_dir.path().join("code.rs");
std::fs::write(&rs_file, b"fn test() {}").unwrap();
let txt_file = temp_dir.path().join("README.txt");
std::fs::write(&txt_file, b"Some text").unwrap();
let md_file = temp_dir.path().join("doc.md");
std::fs::write(&md_file, b"# Documentation").unwrap();
let json_file = temp_dir.path().join("data.json");
std::fs::write(&json_file, b"{}").unwrap();
let file_count = graph.scan_directory(temp_dir.path(), None).unwrap();
assert_eq!(file_count, 1, "Should only scan 1 source file");
let symbols = graph.symbols_in_file(rs_file.to_str().unwrap()).unwrap();
assert_eq!(symbols.len(), 1);
}
#[test]
fn test_language_detection_in_indexing() {
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test.db");
let mut graph = magellan::CodeGraph::open(&db_path).unwrap();
let py_file = temp_dir.path().join("test.py");
let py_source = b"
def python_function():
pass
class PythonClass:
pass
";
graph
.index_file(py_file.to_str().unwrap(), py_source)
.unwrap();
let py_symbols = graph.symbols_in_file(py_file.to_str().unwrap()).unwrap();
assert_eq!(py_symbols.len(), 2);
let cpp_file = temp_dir.path().join("test.cpp");
let cpp_source = b"
class CppClass {};
namespace CppNamespace {}
";
graph
.index_file(cpp_file.to_str().unwrap(), cpp_source)
.unwrap();
let cpp_symbols = graph.symbols_in_file(cpp_file.to_str().unwrap()).unwrap();
assert_eq!(cpp_symbols.len(), 2);
let ts_file = temp_dir.path().join("test.ts");
let ts_source = b"
interface TsInterface {}
type TsType = string;
enum TsEnum {}
namespace TsNamespace {}
";
graph
.index_file(ts_file.to_str().unwrap(), ts_source)
.unwrap();
let ts_symbols = graph.symbols_in_file(ts_file.to_str().unwrap()).unwrap();
assert_eq!(ts_symbols.len(), 4);
}
#[test]
fn test_graceful_degradation_for_unsupported_language() {
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test.db");
let mut graph = magellan::CodeGraph::open(&db_path).unwrap();
let go_file = temp_dir.path().join("test.go");
let go_source = b"package main\n\nfunc main() {}";
let result = graph.index_file(go_file.to_str().unwrap(), go_source);
assert!(result.is_ok());
assert_eq!(result.unwrap(), 0);
}