pub(crate) use super::*;
#[test]
fn test_ast_path_creation() {
let path = AstPath::new(
Token::new(TokenType::Identifier, "x"),
vec![
AstNodeType::Parameter,
AstNodeType::Function,
AstNodeType::Return,
],
Token::new(TokenType::Identifier, "result"),
);
assert_eq!(path.source().value(), "x");
assert_eq!(path.target().value(), "result");
assert_eq!(path.len(), 3);
assert!(!path.is_empty());
}
#[test]
fn test_path_string() {
let path = AstPath::new(
Token::new(TokenType::Identifier, "a"),
vec![AstNodeType::Parameter, AstNodeType::Function],
Token::new(TokenType::Identifier, "b"),
);
let path_str = path.to_path_string();
assert!(path_str.contains("a"));
assert!(path_str.contains("b"));
assert!(path_str.contains("Param"));
assert!(path_str.contains("Func"));
}
#[test]
fn test_path_extractor_simple() {
let mut func = AstNode::new(AstNodeType::Function, "add");
func.add_child(AstNode::new(AstNodeType::Parameter, "x"));
func.add_child(AstNode::new(AstNodeType::Parameter, "y"));
func.add_child(AstNode::new(AstNodeType::Return, "sum"));
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&func);
assert_eq!(paths.len(), 3);
}
#[test]
fn test_path_extractor_max_length() {
let mut func = AstNode::new(AstNodeType::Function, "test");
func.add_child(AstNode::new(AstNodeType::Parameter, "a"));
func.add_child(AstNode::new(AstNodeType::Parameter, "b"));
let extractor_unlimited = PathExtractor::new(100);
let all_paths = extractor_unlimited.extract(&func);
assert!(!all_paths.is_empty(), "Should have at least one path");
let actual_len = all_paths[0].len();
let extractor = PathExtractor::new(actual_len - 1);
let paths = extractor.extract(&func);
assert!(
paths.is_empty(),
"Expected no paths with max_len={}, but got {} paths",
actual_len - 1,
paths.len()
);
let extractor = PathExtractor::new(actual_len);
let paths = extractor.extract(&func);
assert!(
!paths.is_empty(),
"Expected paths with max_len={}",
actual_len
);
}
#[test]
fn test_path_context() {
let mut func = AstNode::new(AstNodeType::Function, "test");
func.add_child(AstNode::new(AstNodeType::Parameter, "a"));
func.add_child(AstNode::new(AstNodeType::Parameter, "b"));
func.add_child(AstNode::new(AstNodeType::Return, "c"));
let extractor = PathExtractor::new(10);
let contexts = extractor.extract_with_context(&func);
assert!(!contexts.is_empty());
for ctx in &contexts {
assert!(ctx.source_index < ctx.target_index);
}
}
#[test]
fn test_single_terminal() {
let func = AstNode::new(AstNodeType::Function, "empty");
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&func);
assert!(paths.is_empty());
}
#[test]
fn test_deep_tree_paths() {
let mut func = AstNode::new(AstNodeType::Function, "compute");
let mut block = AstNode::new(AstNodeType::Block, "body");
let mut cond = AstNode::new(AstNodeType::Conditional, "if");
cond.add_child(AstNode::new(AstNodeType::Variable, "condition"));
cond.add_child(AstNode::new(AstNodeType::Return, "early"));
block.add_child(cond);
block.add_child(AstNode::new(AstNodeType::Return, "final"));
func.add_child(block);
func.add_child(AstNode::new(AstNodeType::Parameter, "input"));
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&func);
assert!(!paths.is_empty());
}
#[test]
fn test_max_paths_limit() {
let mut func = AstNode::new(AstNodeType::Function, "many");
for i in 0..10 {
func.add_child(AstNode::new(AstNodeType::Parameter, format!("p{i}")));
}
let extractor = PathExtractor::new(10).with_max_paths(5);
let paths = extractor.extract(&func);
assert_eq!(paths.len(), 5);
}
#[test]
fn test_ast_path_empty() {
let path = AstPath::new(
Token::new(TokenType::Identifier, "a"),
vec![],
Token::new(TokenType::Identifier, "b"),
);
assert!(path.is_empty());
assert_eq!(path.len(), 0);
}
#[test]
fn test_ast_path_to_path_string_empty_nodes() {
let path = AstPath::new(
Token::new(TokenType::Identifier, "src"),
vec![],
Token::new(TokenType::Identifier, "tgt"),
);
let s = path.to_path_string();
assert_eq!(s, "src||tgt");
}
#[test]
fn test_path_extractor_default() {
let extractor = PathExtractor::default();
let mut func = AstNode::new(AstNodeType::Function, "test");
func.add_child(AstNode::new(AstNodeType::Parameter, "a"));
func.add_child(AstNode::new(AstNodeType::Parameter, "b"));
let paths = extractor.extract(&func);
assert!(!paths.is_empty());
}
#[test]
fn test_extract_with_context_max_paths_limit() {
let mut func = AstNode::new(AstNodeType::Function, "many");
for i in 0..10 {
func.add_child(AstNode::new(AstNodeType::Parameter, format!("p{i}")));
}
let extractor = PathExtractor::new(10).with_max_paths(3);
let contexts = extractor.extract_with_context(&func);
assert_eq!(contexts.len(), 3);
for ctx in &contexts {
assert!(ctx.source_index < ctx.target_index);
}
}
#[test]
fn test_extract_with_context_single_terminal() {
let func = AstNode::new(AstNodeType::Function, "single");
let extractor = PathExtractor::new(10);
let contexts = extractor.extract_with_context(&func);
assert!(contexts.is_empty());
}
#[test]
fn test_node_to_token_literal_branch() {
let mut parent = AstNode::new(AstNodeType::Function, "test");
parent.add_child(AstNode::new(AstNodeType::Literal, "42"));
parent.add_child(AstNode::new(AstNodeType::Parameter, "x"));
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&parent);
assert!(!paths.is_empty());
let has_literal = paths
.iter()
.any(|p| p.source().value() == "42" || p.target().value() == "42");
assert!(has_literal);
}
#[test]
fn test_node_to_token_type_annotation_branch() {
let mut parent = AstNode::new(AstNodeType::Function, "test");
parent.add_child(AstNode::new(AstNodeType::TypeAnnotation, "i32"));
parent.add_child(AstNode::new(AstNodeType::Parameter, "x"));
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&parent);
assert!(!paths.is_empty());
}
#[test]
fn test_node_to_token_binary_op_branch() {
let mut parent = AstNode::new(AstNodeType::Function, "test");
parent.add_child(AstNode::new(AstNodeType::BinaryOp, "+"));
parent.add_child(AstNode::new(AstNodeType::Parameter, "a"));
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&parent);
assert!(!paths.is_empty());
}
#[test]
fn test_node_to_token_unary_op_branch() {
let mut parent = AstNode::new(AstNodeType::Function, "test");
parent.add_child(AstNode::new(AstNodeType::UnaryOp, "-"));
parent.add_child(AstNode::new(AstNodeType::Parameter, "a"));
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&parent);
assert!(!paths.is_empty());
}
#[test]
fn test_node_to_token_generic_branch() {
let mut parent = AstNode::new(AstNodeType::Function, "test");
parent.add_child(AstNode::new(AstNodeType::Generic, "T"));
parent.add_child(AstNode::new(AstNodeType::Parameter, "x"));
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&parent);
assert!(!paths.is_empty());
}
#[test]
fn test_node_to_token_default_identifier_branch() {
let mut parent = AstNode::new(AstNodeType::Function, "test");
parent.add_child(AstNode::new(AstNodeType::Variable, "x"));
parent.add_child(AstNode::new(AstNodeType::Call, "foo"));
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&parent);
assert!(!paths.is_empty());
}
#[test]
fn test_node_to_token_with_explicit_token() {
let mut parent = AstNode::new(AstNodeType::Function, "test");
let terminal = AstNode::terminal(Token::new(TokenType::Number, "99"));
parent.add_child(terminal);
parent.add_child(AstNode::new(AstNodeType::Parameter, "y"));
let extractor = PathExtractor::new(10);
let paths = extractor.extract(&parent);
assert!(!paths.is_empty());
let has_99 = paths
.iter()
.any(|p| p.source().value() == "99" || p.target().value() == "99");
assert!(has_99);
}
#[test]
fn test_path_context_new() {
let path = AstPath::new(
Token::new(TokenType::Identifier, "a"),
vec![AstNodeType::Function],
Token::new(TokenType::Identifier, "b"),
);
let ctx = PathContext::new(path, 0, 1);
assert_eq!(ctx.source_index, 0);
assert_eq!(ctx.target_index, 1);
assert_eq!(ctx.path.source().value(), "a");
assert_eq!(ctx.path.target().value(), "b");
}
#[test]
fn test_path_clone_and_debug() {
let path = AstPath::new(
Token::new(TokenType::Identifier, "x"),
vec![AstNodeType::Function, AstNodeType::Return],
Token::new(TokenType::Identifier, "y"),
);
let cloned = path.clone();
assert_eq!(cloned.source().value(), "x");
assert_eq!(cloned.target().value(), "y");
assert_eq!(cloned.len(), 2);
let debug_str = format!("{:?}", path);
assert!(debug_str.contains("AstPath"));
}
#[test]
fn test_path_context_clone_and_debug() {
let path = AstPath::new(
Token::new(TokenType::Identifier, "a"),
vec![AstNodeType::Parameter],
Token::new(TokenType::Identifier, "b"),
);
let ctx = PathContext::new(path, 2, 5);
let cloned = ctx.clone();
assert_eq!(cloned.source_index, 2);
assert_eq!(cloned.target_index, 5);
let debug_str = format!("{:?}", ctx);
assert!(debug_str.contains("PathContext"));
}
#[test]
fn test_path_extractor_clone_and_debug() {
let extractor = PathExtractor::new(6).with_max_paths(10);
let cloned = extractor.clone();
let debug_str = format!("{:?}", extractor);
assert!(debug_str.contains("PathExtractor"));
let mut func = AstNode::new(AstNodeType::Function, "f");
func.add_child(AstNode::new(AstNodeType::Parameter, "a"));
func.add_child(AstNode::new(AstNodeType::Parameter, "b"));
let paths1 = extractor.extract(&func);
let paths2 = cloned.extract(&func);
assert_eq!(paths1.len(), paths2.len());
}