use std::path::Path;
use thread_flow::incremental::extractors::rust::{RustDependencyExtractor, Visibility};
#[test]
fn test_simple_import() {
let extractor = RustDependencyExtractor::new();
let source = "use std::collections::HashMap;";
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "std::collections");
assert_eq!(imports[0].symbols, vec!["HashMap"]);
assert!(!imports[0].is_wildcard);
}
#[test]
fn test_nested_import() {
let extractor = RustDependencyExtractor::new();
let source = "use std::collections::{HashMap, HashSet};";
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "std::collections");
assert!(imports[0].symbols.contains(&"HashMap".to_string()));
assert!(imports[0].symbols.contains(&"HashSet".to_string()));
assert_eq!(imports[0].symbols.len(), 2);
assert!(!imports[0].is_wildcard);
}
#[test]
fn test_wildcard_import() {
let extractor = RustDependencyExtractor::new();
let source = "use std::collections::*;";
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "std::collections");
assert!(imports[0].is_wildcard);
assert!(imports[0].symbols.is_empty());
}
#[test]
fn test_aliased_import() {
let extractor = RustDependencyExtractor::new();
let source = "use std::io::Result as IoResult;";
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "std::io");
assert_eq!(imports[0].symbols, vec!["Result"]);
assert_eq!(
imports[0].aliases,
vec![("Result".to_string(), "IoResult".to_string())]
);
}
#[test]
fn test_crate_relative_import() {
let extractor = RustDependencyExtractor::new();
let source = "use crate::core::Engine;";
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "crate::core");
assert_eq!(imports[0].symbols, vec!["Engine"]);
}
#[test]
fn test_super_import() {
let extractor = RustDependencyExtractor::new();
let source = "use super::utils;";
let imports = extractor
.extract_imports(source, Path::new("src/sub/mod.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "super");
assert_eq!(imports[0].symbols, vec!["utils"]);
}
#[test]
fn test_self_import() {
let extractor = RustDependencyExtractor::new();
let source = "use self::types::Config;";
let imports = extractor
.extract_imports(source, Path::new("src/lib.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "self::types");
assert_eq!(imports[0].symbols, vec!["Config"]);
}
#[test]
fn test_multiple_imports() {
let extractor = RustDependencyExtractor::new();
let source = r#"
use std::collections::HashMap;
use std::io::Read;
use crate::config::Settings;
"#;
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert_eq!(imports.len(), 3);
assert_eq!(imports[0].module_path, "std::collections");
assert_eq!(imports[0].symbols, vec!["HashMap"]);
assert_eq!(imports[1].module_path, "std::io");
assert_eq!(imports[1].symbols, vec!["Read"]);
assert_eq!(imports[2].module_path, "crate::config");
assert_eq!(imports[2].symbols, vec!["Settings"]);
}
#[test]
fn test_deeply_nested_import() {
let extractor = RustDependencyExtractor::new();
let source = "use a::b::c::d::E;";
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "a::b::c::d");
assert_eq!(imports[0].symbols, vec!["E"]);
}
#[test]
fn test_nested_with_alias() {
let extractor = RustDependencyExtractor::new();
let source = "use std::collections::{HashMap as Map, HashSet};";
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "std::collections");
assert!(imports[0].symbols.contains(&"HashMap".to_string()));
assert!(imports[0].symbols.contains(&"HashSet".to_string()));
assert_eq!(
imports[0].aliases,
vec![("HashMap".to_string(), "Map".to_string())]
);
}
#[test]
fn test_pub_use_reexport() {
let extractor = RustDependencyExtractor::new();
let source = "pub use types::Config;";
let exports = extractor
.extract_exports(source, Path::new("src/lib.rs"))
.unwrap();
assert_eq!(exports.len(), 1);
assert_eq!(exports[0].symbol_name, "Config");
assert_eq!(exports[0].module_path, "types");
assert_eq!(exports[0].visibility, Visibility::Public);
}
#[test]
fn test_pub_crate_use() {
let extractor = RustDependencyExtractor::new();
let source = "pub(crate) use internal::Helper;";
let exports = extractor
.extract_exports(source, Path::new("src/lib.rs"))
.unwrap();
assert_eq!(exports.len(), 1);
assert_eq!(exports[0].symbol_name, "Helper");
assert_eq!(exports[0].module_path, "internal");
assert_eq!(exports[0].visibility, Visibility::Crate);
}
#[test]
fn test_pub_use_wildcard() {
let extractor = RustDependencyExtractor::new();
let source = "pub use module::*;";
let exports = extractor
.extract_exports(source, Path::new("src/lib.rs"))
.unwrap();
assert_eq!(exports.len(), 1);
assert_eq!(exports[0].symbol_name, "*");
assert_eq!(exports[0].module_path, "module");
assert_eq!(exports[0].visibility, Visibility::Public);
}
#[test]
fn test_pub_use_nested() {
let extractor = RustDependencyExtractor::new();
let source = "pub use types::{Config, Settings};";
let exports = extractor
.extract_exports(source, Path::new("src/lib.rs"))
.unwrap();
assert_eq!(exports.len(), 2);
assert!(exports.iter().any(|e| e.symbol_name == "Config"));
assert!(exports.iter().any(|e| e.symbol_name == "Settings"));
assert!(exports.iter().all(|e| e.module_path == "types"));
assert!(exports.iter().all(|e| e.visibility == Visibility::Public));
}
#[test]
fn test_resolve_crate_path() {
let extractor = RustDependencyExtractor::new();
let resolved = extractor
.resolve_module_path(Path::new("src/handlers/auth.rs"), "crate::config")
.unwrap();
assert_eq!(resolved, Path::new("src/config.rs"));
}
#[test]
fn test_resolve_super_path() {
let extractor = RustDependencyExtractor::new();
let resolved = extractor
.resolve_module_path(Path::new("src/handlers/auth.rs"), "super::utils")
.unwrap();
assert_eq!(resolved, Path::new("src/handlers/utils.rs"));
}
#[test]
fn test_resolve_self_path() {
let extractor = RustDependencyExtractor::new();
let resolved = extractor
.resolve_module_path(Path::new("src/handlers/mod.rs"), "self::auth")
.unwrap();
assert_eq!(resolved, Path::new("src/handlers/auth.rs"));
}
#[test]
fn test_resolve_external_crate_returns_error() {
let extractor = RustDependencyExtractor::new();
let result = extractor.resolve_module_path(Path::new("src/main.rs"), "std::collections");
assert!(result.is_err());
}
#[test]
fn test_empty_source() {
let extractor = RustDependencyExtractor::new();
let imports = extractor
.extract_imports("", Path::new("src/main.rs"))
.unwrap();
assert!(imports.is_empty());
}
#[test]
fn test_no_imports() {
let extractor = RustDependencyExtractor::new();
let source = r#"
fn main() {
println!("Hello, world!");
}
"#;
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert!(imports.is_empty());
}
#[test]
fn test_bare_module_import() {
let extractor = RustDependencyExtractor::new();
let source = "use serde;";
let imports = extractor
.extract_imports(source, Path::new("src/main.rs"))
.unwrap();
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].module_path, "serde");
assert!(imports[0].symbols.is_empty());
assert!(!imports[0].is_wildcard);
}