use std::path::PathBuf;
use xlog_logic::resolver::ModuleResolver;
fn test_modules_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("modules")
}
#[test]
fn test_basic_import() {
let dir = test_modules_dir().join("basic");
let mut resolver = ModuleResolver::new(vec![]);
let result = resolver.load_module(&dir, &["main".into()]);
assert!(result.is_ok(), "Failed to load basic module: {:?}", result);
assert!(resolver.is_loaded("main"), "main not loaded");
assert!(resolver.is_loaded("helper"), "helper not loaded");
}
#[test]
fn test_nested_import() {
let dir = test_modules_dir().join("nested");
let mut resolver = ModuleResolver::new(vec![]);
let result = resolver.load_module(&dir, &["main".into()]);
assert!(result.is_ok(), "Failed to load nested module: {:?}", result);
assert!(resolver.is_loaded("main"), "main not loaded");
assert!(resolver.is_loaded("lib/utils"), "lib/utils not loaded");
}
#[test]
fn test_circular_import_detected() {
let dir = test_modules_dir().join("circular");
let mut resolver = ModuleResolver::new(vec![]);
let result = resolver.load_module(&dir, &["a".into()]);
assert!(
matches!(
result,
Err(xlog_logic::module::ModuleError::CircularImport { .. })
),
"Expected CircularImport error, got: {:?}",
result
);
}
#[test]
fn test_visibility_exports() {
let dir = test_modules_dir().join("visibility");
let mut resolver = ModuleResolver::new(vec![]);
let result = resolver.load_module(&dir, &["internal".into()]);
assert!(
result.is_ok(),
"Failed to load visibility module: {:?}",
result
);
let module = resolver.get_module(&["internal".into()]).unwrap();
assert!(
module.exports.contains("public_pred"),
"public_pred should be exported"
);
assert!(
!module.exports.contains("private_pred"),
"private_pred should NOT be exported"
);
}
#[test]
fn test_search_paths() {
let base = test_modules_dir();
let search = vec![base.join("basic")];
let resolver = ModuleResolver::new(search);
let result = resolver.find_module_file(&base, &["helper".into()]);
assert!(result.is_some(), "helper.xlog not found via search path");
}
#[test]
fn test_transitive_dependencies() {
let dir = test_modules_dir().join("transitive");
let mut resolver = ModuleResolver::new(vec![]);
let result = resolver.load_module(&dir, &["main".into()]);
assert!(
result.is_ok(),
"Failed to load transitive chain: {:?}",
result
);
assert!(resolver.is_loaded("main"), "main not loaded");
assert!(resolver.is_loaded("mid"), "mid not loaded");
assert!(resolver.is_loaded("base"), "base not loaded");
}
#[test]
fn test_search_path_precedence() {
let base = test_modules_dir().join("basic");
let search = vec![test_modules_dir().join("nested")];
let resolver = ModuleResolver::new(search);
let result = resolver.find_module_file(&base, &["helper".into()]);
assert!(result.is_some(), "helper not found");
assert!(
result.unwrap().starts_with(&base),
"Should find helper in relative path first"
);
}
#[test]
fn test_module_exports_from_rules() {
let dir = test_modules_dir().join("basic");
let mut resolver = ModuleResolver::new(vec![]);
let result = resolver.load_module(&dir, &["helper".into()]);
assert!(result.is_ok());
let module = resolver.get_module(&["helper".into()]).unwrap();
assert!(module.exports.contains("helper_pred"));
}