use pattern_core::Pattern;
#[test]
fn test_find_first_root_matches() {
let pattern = Pattern::pattern(
"root",
vec![Pattern::point("child1"), Pattern::point("child2")],
);
let result = pattern.find_first(|p| p.value == "root");
assert!(result.is_some());
assert_eq!(result.unwrap().value, "root");
}
#[test]
fn test_find_first_root_matches_by_structure() {
let pattern = Pattern::pattern("root", vec![Pattern::point("child")]);
let result = pattern.find_first(|p| p.length() == 1);
assert!(result.is_some());
assert_eq!(result.unwrap().value, "root");
}
#[test]
fn test_find_first_element_matches() {
let pattern = Pattern::pattern(
"root",
vec![Pattern::point("target"), Pattern::point("other")],
);
let result = pattern.find_first(|p| p.value == "target");
assert!(result.is_some());
assert_eq!(result.unwrap().value, "target");
}
#[test]
fn test_find_first_second_element_matches() {
let pattern = Pattern::pattern(
"root",
vec![Pattern::point("first"), Pattern::point("target")],
);
let result = pattern.find_first(|p| p.value == "target");
assert!(result.is_some());
assert_eq!(result.unwrap().value, "target");
}
#[test]
fn test_find_first_deeply_nested() {
let pattern = Pattern::pattern(
"root",
vec![
Pattern::pattern(
"branch1",
vec![Pattern::pattern("branch2", vec![Pattern::point("target")])],
),
Pattern::point("sibling"),
],
);
let result = pattern.find_first(|p| p.value == "target");
assert!(result.is_some());
assert_eq!(result.unwrap().value, "target");
}
#[test]
fn test_find_first_very_deep_nesting() {
let mut pattern = Pattern::point("target".to_string());
for i in (0..10).rev() {
pattern = Pattern::pattern(format!("level{}", i), vec![pattern]);
}
let result = pattern.find_first(|p| p.value == "target");
assert!(result.is_some());
assert_eq!(result.unwrap().value, "target");
}
#[test]
fn test_find_first_no_matches() {
let pattern = Pattern::pattern(
"root",
vec![Pattern::point("child1"), Pattern::point("child2")],
);
let result = pattern.find_first(|p| p.value == "nonexistent");
assert!(result.is_none());
}
#[test]
fn test_find_first_no_matches_structural_predicate() {
let pattern = Pattern::pattern(
"root",
vec![Pattern::point("child1"), Pattern::point("child2")],
);
let result = pattern.find_first(|p| p.length() > 2);
assert!(result.is_none());
}
#[test]
fn test_find_first_pre_order_traversal() {
let pattern = Pattern::pattern(
"root",
vec![
Pattern::pattern("branch", vec![Pattern::point("match2")]),
Pattern::point("match1"),
],
);
let result = pattern.find_first(|p| p.is_atomic());
assert!(result.is_some());
assert_eq!(result.unwrap().value, "match2");
}
#[test]
fn test_find_first_multiple_value_matches() {
let pattern = Pattern::pattern(
"a",
vec![
Pattern::pattern("a", vec![Pattern::point("a")]),
Pattern::point("a"),
],
);
let result = pattern.find_first(|p| p.value == "a");
assert!(result.is_some());
assert_eq!(result.unwrap().length(), 2);
}
#[test]
fn test_find_first_left_before_right() {
let pattern = Pattern::pattern(
"root",
vec![Pattern::point("left"), Pattern::point("right")],
);
let result = pattern.find_first(|p| p.is_atomic());
assert!(result.is_some());
assert_eq!(result.unwrap().value, "left");
}
#[test]
fn test_find_first_atomic_pattern_matches_itself() {
let pattern = Pattern::point("atomic");
let result = pattern.find_first(|p| p.value == "atomic");
assert!(result.is_some());
assert_eq!(result.unwrap().value, "atomic");
}
#[test]
fn test_find_first_atomic_pattern_no_match() {
let pattern = Pattern::point("atomic");
let result = pattern.find_first(|p| p.value == "other");
assert!(result.is_none());
}
#[test]
fn test_find_first_atomic_pattern_structural() {
let pattern = Pattern::point("atomic");
let result = pattern.find_first(|p| p.is_atomic());
assert!(result.is_some());
assert_eq!(result.unwrap().value, "atomic");
}
#[test]
fn test_find_first_empty_elements() {
let pattern = Pattern::pattern("root", vec![]);
let result = pattern.find_first(|p| p.value == "root");
assert!(result.is_some());
assert_eq!(result.unwrap().value, "root");
}
#[test]
fn test_find_first_empty_elements_is_atomic() {
let pattern = Pattern::pattern("root", vec![]);
let result = pattern.find_first(|p| p.is_atomic());
assert!(result.is_some());
assert_eq!(result.unwrap().value, "root");
}
#[test]
fn test_find_first_empty_elements_structural() {
let pattern = Pattern::pattern("root", vec![]);
let result = pattern.find_first(|p| p.length() == 0);
assert!(result.is_some());
assert_eq!(result.unwrap().value, "root");
}
#[test]
fn test_find_first_100_level_nesting() {
let mut pattern = Pattern::point("bottom".to_string());
for i in (0..100).rev() {
pattern = Pattern::pattern(format!("level{}", i), vec![pattern]);
}
let result = pattern.find_first(|p| p.value == "bottom");
assert!(result.is_some());
assert_eq!(result.unwrap().value, "bottom");
}
#[test]
fn test_find_first_120_level_nesting() {
let mut pattern = Pattern::point("bottom".to_string());
for i in (0..120).rev() {
pattern = Pattern::pattern(format!("level{}", i), vec![pattern]);
}
let result = pattern.find_first(|p| p.value == "bottom");
assert!(result.is_some());
assert_eq!(result.unwrap().value, "bottom");
}
#[test]
fn test_find_first_combined_value_and_structure() {
let pattern = Pattern::pattern(
"root",
vec![
Pattern::pattern(
"branch",
vec![Pattern::point("child1"), Pattern::point("child2")],
),
Pattern::point("leaf"),
],
);
let result = pattern.find_first(|p| p.value == "branch" && p.length() == 2);
assert!(result.is_some());
assert_eq!(result.unwrap().value, "branch");
}
#[test]
fn test_find_first_structural_predicate_depth() {
let pattern = Pattern::pattern(
"root",
vec![
Pattern::pattern(
"branch",
vec![Pattern::pattern("deep", vec![Pattern::point("deepest")])],
),
Pattern::point("shallow"),
],
);
let result = pattern.find_first(|p| p.depth() >= 2);
assert!(result.is_some());
assert_eq!(result.unwrap().value, "root");
}
#[test]
fn test_find_first_structural_predicate_size() {
let pattern = Pattern::pattern(
"root",
vec![
Pattern::pattern(
"branch",
vec![
Pattern::point("child1"),
Pattern::point("child2"),
Pattern::point("child3"),
],
),
Pattern::point("leaf"),
],
);
let result = pattern.find_first(|p| p.size() >= 3);
assert!(result.is_some());
assert_eq!(result.unwrap().value, "root");
}
#[test]
fn test_find_first_with_any_value() {
let pattern = Pattern::pattern(
1,
vec![
Pattern::pattern(2, vec![Pattern::point(5), Pattern::point(10)]),
Pattern::point(3),
],
);
let result = pattern.find_first(|p| p.any_value(|v| *v > 8));
assert!(result.is_some());
assert_eq!(result.unwrap().value, 1);
}
#[test]
fn test_find_first_with_all_values() {
let pattern = Pattern::pattern(
1,
vec![
Pattern::pattern(2, vec![Pattern::point(5), Pattern::point(10)]),
Pattern::point(-3),
],
);
let result = pattern.find_first(|p| p.all_values(|v| *v > 0));
assert!(result.is_some());
assert_eq!(result.unwrap().value, 2);
}
#[test]
fn test_find_first_with_filter_consistency() {
let pattern = Pattern::pattern(
"root",
vec![
Pattern::point("a"),
Pattern::pattern("branch", vec![Pattern::point("b")]),
Pattern::point("c"),
],
);
let predicate = |p: &Pattern<&str>| p.is_atomic();
let first = pattern.find_first(predicate);
let all_matches = pattern.filter(predicate);
assert!(first.is_some());
assert!(!all_matches.is_empty());
assert_eq!(first.unwrap().value, all_matches[0].value);
}
#[test]
fn test_find_first_returns_reference_not_clone() {
let pattern = Pattern::pattern(
"root".to_string(),
vec![Pattern::point("child".to_string())],
);
let result = pattern.find_first(|p| p.value == "child");
assert!(result.is_some());
let child_ref = &pattern.elements[0];
let result_ref = result.unwrap();
assert!(std::ptr::eq(child_ref, result_ref));
}