use super::*;
#[test]
fn test_node_size() {
let size = std::mem::size_of::<UnifiedAstNode>();
assert!(
size <= 128,
"Node size {size} exceeds maximum expected size of 128 bytes"
);
assert!(
size >= 64,
"Node size {size} is smaller than minimum expected size of 64 bytes"
);
}
#[test]
fn test_node_alignment() {
assert_eq!(std::mem::align_of::<UnifiedAstNode>(), 32);
}
#[test]
fn test_language_values() {
assert_eq!(Language::Rust as u8, 0);
assert_eq!(Language::TypeScript as u8, 1);
assert_eq!(Language::JavaScript as u8, 2);
assert_eq!(Language::Python as u8, 3);
assert_eq!(Language::Markdown as u8, 4);
assert_eq!(Language::Makefile as u8, 5);
}
#[test]
fn test_language_clone() {
let lang = Language::Rust;
let cloned = lang;
assert_eq!(lang, cloned);
}
#[test]
fn test_language_equality() {
assert_eq!(Language::Rust, Language::Rust);
assert_ne!(Language::Rust, Language::Python);
}
#[test]
fn test_language_debug() {
let lang = Language::TypeScript;
let debug_str = format!("{:?}", lang);
assert_eq!(debug_str, "TypeScript");
}
#[test]
fn test_node_flags() {
let mut flags = NodeFlags::new();
flags.set(NodeFlags::ASYNC);
flags.set(NodeFlags::EXPORTED);
assert!(flags.has(NodeFlags::ASYNC));
assert!(flags.has(NodeFlags::EXPORTED));
assert!(!flags.has(NodeFlags::PRIVATE));
flags.unset(NodeFlags::ASYNC);
assert!(!flags.has(NodeFlags::ASYNC));
}
#[test]
fn test_node_flags_new() {
let flags = NodeFlags::new();
assert!(!flags.has(NodeFlags::ASYNC));
assert!(!flags.has(NodeFlags::GENERATOR));
assert!(!flags.has(NodeFlags::ABSTRACT));
}
#[test]
fn test_node_flags_default() {
let flags = NodeFlags::default();
assert!(!flags.has(NodeFlags::ASYNC));
assert!(!flags.has(NodeFlags::STATIC));
}
#[test]
fn test_node_flags_multiple_set() {
let mut flags = NodeFlags::new();
flags.set(NodeFlags::ASYNC | NodeFlags::STATIC | NodeFlags::CONST);
assert!(flags.has(NodeFlags::ASYNC));
assert!(flags.has(NodeFlags::STATIC));
assert!(flags.has(NodeFlags::CONST));
}
#[test]
fn test_node_flags_unset_multiple() {
let mut flags = NodeFlags::new();
flags.set(NodeFlags::ASYNC | NodeFlags::EXPORTED);
flags.unset(NodeFlags::ASYNC | NodeFlags::EXPORTED);
assert!(!flags.has(NodeFlags::ASYNC));
assert!(!flags.has(NodeFlags::EXPORTED));
}
#[test]
fn test_node_flags_all_flags() {
let mut flags = NodeFlags::new();
flags.set(NodeFlags::ASYNC);
flags.set(NodeFlags::GENERATOR);
flags.set(NodeFlags::ABSTRACT);
flags.set(NodeFlags::STATIC);
flags.set(NodeFlags::CONST);
flags.set(NodeFlags::EXPORTED);
flags.set(NodeFlags::PRIVATE);
flags.set(NodeFlags::DEPRECATED);
assert!(flags.has(NodeFlags::ASYNC));
assert!(flags.has(NodeFlags::GENERATOR));
assert!(flags.has(NodeFlags::ABSTRACT));
assert!(flags.has(NodeFlags::STATIC));
assert!(flags.has(NodeFlags::CONST));
assert!(flags.has(NodeFlags::EXPORTED));
assert!(flags.has(NodeFlags::PRIVATE));
assert!(flags.has(NodeFlags::DEPRECATED));
}
#[test]
fn test_node_flags_debug() {
let flags = NodeFlags::new();
let debug_str = format!("{:?}", flags);
assert!(debug_str.contains("NodeFlags"));
}
#[test]
fn test_byte_pos_to_usize() {
let pos = BytePos(100);
assert_eq!(pos.to_usize(), 100);
}
#[test]
fn test_byte_pos_from_usize() {
let pos = BytePos::from_usize(42);
assert_eq!(pos.0, 42);
assert_eq!(pos.to_usize(), 42);
}
#[test]
fn test_byte_pos_ordering() {
let pos1 = BytePos(10);
let pos2 = BytePos(20);
assert!(pos1 < pos2);
assert!(pos2 > pos1);
assert!(pos1 <= pos1);
}
#[test]
fn test_byte_pos_equality() {
let pos1 = BytePos(50);
let pos2 = BytePos(50);
assert_eq!(pos1, pos2);
}
#[test]
fn test_byte_pos_zero() {
let pos = BytePos(0);
assert_eq!(pos.to_usize(), 0);
}
#[test]
fn test_span_new() {
let span = Span::new(10, 50);
assert_eq!(span.start.0, 10);
assert_eq!(span.end.0, 50);
}
#[test]
fn test_span_len() {
let span = Span::new(0, 100);
assert_eq!(span.len(), 100);
}
#[test]
fn test_span_len_with_offset() {
let span = Span::new(50, 150);
assert_eq!(span.len(), 100);
}
#[test]
fn test_span_is_empty() {
let empty_span = Span::new(10, 10);
assert!(empty_span.is_empty());
let non_empty = Span::new(0, 1);
assert!(!non_empty.is_empty());
}
#[test]
fn test_span_is_empty_invalid() {
let invalid_span = Span::new(50, 30);
assert!(invalid_span.is_empty());
}
#[test]
fn test_span_contains() {
let span = Span::new(10, 50);
assert!(span.contains(BytePos(10)));
assert!(span.contains(BytePos(25)));
assert!(span.contains(BytePos(49)));
assert!(!span.contains(BytePos(50)));
assert!(!span.contains(BytePos(9)));
}
#[test]
fn test_span_equality() {
let span1 = Span::new(0, 100);
let span2 = Span::new(0, 100);
assert_eq!(span1, span2);
}
#[test]
fn test_location_new() {
let loc = Location::new(PathBuf::from("test.rs"), 0, 100);
assert_eq!(loc.file_path, PathBuf::from("test.rs"));
assert_eq!(loc.span.start.0, 0);
assert_eq!(loc.span.end.0, 100);
}
#[test]
fn test_location_contains() {
let outer = Location::new(PathBuf::from("test.rs"), 0, 100);
let inner = Location::new(PathBuf::from("test.rs"), 10, 50);
assert!(outer.contains(&inner));
assert!(!inner.contains(&outer));
}
#[test]
fn test_location_contains_different_files() {
let loc1 = Location::new(PathBuf::from("file1.rs"), 0, 100);
let loc2 = Location::new(PathBuf::from("file2.rs"), 0, 50);
assert!(!loc1.contains(&loc2));
}
#[test]
fn test_location_overlaps() {
let loc1 = Location::new(PathBuf::from("test.rs"), 0, 50);
let loc2 = Location::new(PathBuf::from("test.rs"), 25, 75);
assert!(loc1.overlaps(&loc2));
assert!(loc2.overlaps(&loc1));
}
#[test]
fn test_location_no_overlap() {
let loc1 = Location::new(PathBuf::from("test.rs"), 0, 50);
let loc2 = Location::new(PathBuf::from("test.rs"), 100, 150);
assert!(!loc1.overlaps(&loc2));
assert!(!loc2.overlaps(&loc1));
}
#[test]
fn test_location_overlaps_different_files() {
let loc1 = Location::new(PathBuf::from("file1.rs"), 0, 100);
let loc2 = Location::new(PathBuf::from("file2.rs"), 50, 150);
assert!(!loc1.overlaps(&loc2));
}
#[test]
fn test_location_equality() {
let loc1 = Location::new(PathBuf::from("test.rs"), 0, 100);
let loc2 = Location::new(PathBuf::from("test.rs"), 0, 100);
assert_eq!(loc1, loc2);
}
#[test]
fn test_qualified_name_new() {
let qname = QualifiedName::new(
vec!["std".to_string(), "collections".to_string()],
"HashMap".to_string(),
);
assert_eq!(qname.module_path, vec!["std", "collections"]);
assert_eq!(qname.name, "HashMap");
assert!(qname.disambiguator.is_none());
}
#[test]
fn test_qualified_name_empty_module_path() {
let qname = QualifiedName::new(vec![], "foo".to_string());
assert!(qname.module_path.is_empty());
assert_eq!(qname.name, "foo");
}
#[test]
fn test_qualified_name_to_qualified_string() {
let qname = QualifiedName::new(
vec!["std".to_string(), "io".to_string()],
"Write".to_string(),
);
assert_eq!(qname.to_qualified_string(), "std::io::Write");
}
#[test]
fn test_qualified_name_single_name_to_string() {
let qname = QualifiedName::new(vec![], "main".to_string());
assert_eq!(qname.to_qualified_string(), "main");
}
#[test]
fn test_qualified_name_equality() {
let qname1 = QualifiedName::new(vec!["a".to_string()], "b".to_string());
let qname2 = QualifiedName::new(vec!["a".to_string()], "b".to_string());
assert_eq!(qname1, qname2);
}
#[test]
fn test_qualified_name_from_str() {
let qname: QualifiedName = "std::collections::HashMap".parse().unwrap();
assert_eq!(qname.module_path, vec!["std", "collections"]);
assert_eq!(qname.name, "HashMap");
}
#[test]
fn test_qualified_name_from_str_simple() {
let qname: QualifiedName = "main".parse().unwrap();
assert!(qname.module_path.is_empty());
assert_eq!(qname.name, "main");
}
#[test]
fn test_ast_dag() {
let mut dag = AstDag::new();
let node = UnifiedAstNode::new(AstKind::Function(FunctionKind::Regular), Language::Rust);
let key = dag.add_node(node);
assert_eq!(dag.nodes.len(), 1);
assert!(dag.dirty_nodes.contains(key));
dag.mark_clean(key);
assert!(!dag.dirty_nodes.contains(key));
}
#[test]
fn test_ast_dag_default() {
let dag = AstDag::default();
assert!(dag.nodes.is_empty());
assert!(dag.dirty_nodes.is_empty());
}
#[test]
fn test_ast_dag_add_multiple_nodes() {
let mut dag = AstDag::new();
let node1 = UnifiedAstNode::new(AstKind::Function(FunctionKind::Regular), Language::Rust);
let node2 = UnifiedAstNode::new(AstKind::Function(FunctionKind::Lambda), Language::Python);
let key1 = dag.add_node(node1);
let key2 = dag.add_node(node2);
assert_eq!(dag.nodes.len(), 2);
assert_ne!(key1, key2);
}
#[test]
fn test_ast_dag_generation() {
let dag = AstDag::new();
let gen = dag.generation.load(std::sync::atomic::Ordering::SeqCst);
assert_eq!(gen, 0);
}
#[test]
fn test_ast_dag_dirty_nodes() {
let mut dag = AstDag::new();
let node = UnifiedAstNode::new(AstKind::Module(ModuleKind::File), Language::TypeScript);
let key = dag.add_node(node);
assert!(dag.dirty_nodes.contains(key));
}
#[test]
fn test_invalid_node_key() {
assert_eq!(INVALID_NODE_KEY, u32::MAX);
}
#[test]
fn test_unified_ast_node_new() {
let node = UnifiedAstNode::new(AstKind::Function(FunctionKind::Regular), Language::Rust);
assert_eq!(node.kind, AstKind::Function(FunctionKind::Regular));
assert_eq!(node.lang, Language::Rust);
}
#[test]
fn test_unified_ast_node_different_kinds() {
let module = UnifiedAstNode::new(AstKind::Module(ModuleKind::File), Language::Python);
let func = UnifiedAstNode::new(AstKind::Function(FunctionKind::Lambda), Language::Python);
let class = UnifiedAstNode::new(AstKind::Class(ClassKind::Regular), Language::TypeScript);
assert_eq!(module.kind, AstKind::Module(ModuleKind::File));
assert_eq!(func.kind, AstKind::Function(FunctionKind::Lambda));
assert_eq!(class.kind, AstKind::Class(ClassKind::Regular));
}
#[test]
fn test_unified_ast_node_languages() {
let rust_node = UnifiedAstNode::new(AstKind::Module(ModuleKind::File), Language::Rust);
let ts_node = UnifiedAstNode::new(AstKind::Module(ModuleKind::File), Language::TypeScript);
let py_node = UnifiedAstNode::new(AstKind::Module(ModuleKind::File), Language::Python);
assert_eq!(rust_node.lang, Language::Rust);
assert_eq!(ts_node.lang, Language::TypeScript);
assert_eq!(py_node.lang, Language::Python);
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests {
use proptest::prelude::*;
proptest! {
#[test]
fn basic_property_stability(_input in ".*") {
prop_assert!(true);
}
#[test]
fn module_consistency_check(_x in 0u32..1000) {
prop_assert!(_x < 1001);
}
}
}