use pattern_core::Pattern;
#[test]
fn fold_atomic_pattern_with_integer() {
let atom = Pattern::point(5);
let result = atom.fold(0, |acc, v| acc + v);
assert_eq!(result, 5);
}
#[test]
fn fold_atomic_pattern_with_string() {
let atom = Pattern::point("test");
let result = atom.fold(String::new(), |acc, s| acc + s);
assert_eq!(result, "test");
}
#[test]
fn fold_atomic_pattern_count() {
let atom = Pattern::point(42);
let count = atom.fold(0, |acc, _| acc + 1);
assert_eq!(count, 1);
}
#[test]
fn fold_flat_pattern_with_integer_sum() {
let elem1 = Pattern::point(10);
let elem2 = Pattern::point(20);
let elem3 = Pattern::point(30);
let pattern = Pattern::pattern(100, vec![elem1, elem2, elem3]);
let result = pattern.fold(0, |acc, v| acc + v);
assert_eq!(result, 160);
}
#[test]
fn fold_flat_pattern_with_string_concatenation() {
let elem1 = Pattern::point("hello");
let elem2 = Pattern::point("world");
let pattern = Pattern::pattern("greeting", vec![elem1, elem2]);
let result = pattern.fold(String::new(), |acc, s| acc + s);
assert_eq!(result, "greetinghelloworld");
}
#[test]
fn fold_flat_pattern_count() {
let elem1 = Pattern::point("a");
let elem2 = Pattern::point("b");
let elem3 = Pattern::point("c");
let pattern = Pattern::pattern("root", vec![elem1, elem2, elem3]);
let count = pattern.fold(0, |acc, _| acc + 1);
assert_eq!(count, 4);
}
#[test]
fn fold_flat_pattern_processes_pattern_value() {
let elem1 = Pattern::point(10);
let pattern = Pattern::pattern(5, vec![elem1]);
let result = pattern.fold(0, |acc, v| acc + v);
assert_eq!(result, 15);
}
#[test]
fn fold_nested_pattern_two_levels() {
let inner = Pattern::point(1);
let middle = Pattern::pattern(2, vec![inner]);
let outer = Pattern::pattern(3, vec![middle]);
let pattern = Pattern::pattern(4, vec![outer]);
let result = pattern.fold(0, |acc, v| acc + v);
assert_eq!(result, 10);
}
#[test]
fn fold_deeply_nested_pattern() {
let level4 = Pattern::point(1);
let level3 = Pattern::pattern(2, vec![level4]);
let level2 = Pattern::pattern(3, vec![level3]);
let level1 = Pattern::pattern(4, vec![level2]);
let pattern = Pattern::pattern(5, vec![level1]);
let result = pattern.fold(0, |acc, v| acc + v);
assert_eq!(result, 15);
}
#[test]
fn fold_nested_pattern_with_multiple_branches() {
let inner1 = Pattern::point(1);
let inner2 = Pattern::point(2);
let middle1 = Pattern::pattern(10, vec![inner1]);
let middle2 = Pattern::pattern(20, vec![inner2]);
let pattern = Pattern::pattern(100, vec![middle1, middle2]);
let result = pattern.fold(0, |acc, v| acc + v);
assert_eq!(result, 133);
}
#[test]
fn fold_nested_pattern_preserves_recursion() {
let inner1 = Pattern::point(1);
let inner2 = Pattern::point(2);
let middle = Pattern::pattern(10, vec![inner1, inner2]);
let pattern = Pattern::pattern(100, vec![middle]);
let result = pattern.fold(0, |acc, v| acc + v);
assert_eq!(result, 113);
}
#[test]
fn fold_preserves_depth_first_root_first_order() {
let pattern = Pattern::pattern(
"A",
vec![
Pattern::point("B"),
Pattern::pattern("C", vec![Pattern::point("D")]),
],
);
let result = pattern.fold(String::new(), |acc, s| acc + s);
assert_eq!(result, "ABCD");
}
#[test]
fn fold_processes_root_before_elements() {
let pattern = Pattern::pattern(
"first",
vec![Pattern::point("second"), Pattern::point("third")],
);
let result = pattern.fold(String::new(), |acc, s| acc + s);
assert_eq!(result, "firstsecondthird");
}
#[test]
fn fold_processes_elements_left_to_right() {
let pattern = Pattern::pattern(
1,
vec![Pattern::point(2), Pattern::point(3), Pattern::point(4)],
);
let result = pattern.fold(0, |acc, v| acc + v);
assert_eq!(result, 10); }
#[test]
fn fold_sum_includes_all_values() {
let pattern = Pattern::pattern(
2,
vec![Pattern::point(3), Pattern::point(4), Pattern::point(5)],
);
let sum = pattern.fold(0, |acc, v| acc + v);
assert_eq!(sum, 14); }
#[test]
fn fold_sum_with_nested_structure() {
let inner = Pattern::pattern(5, vec![Pattern::point(6)]);
let pattern = Pattern::pattern(1, vec![Pattern::point(2), inner]);
let sum = pattern.fold(0, |acc, v| acc + v);
assert_eq!(sum, 14); }
#[test]
fn fold_count_equals_size_atomic() {
let pattern = Pattern::point(42);
let count = pattern.fold(0, |acc, _| acc + 1);
assert_eq!(count, pattern.size());
}
#[test]
fn fold_count_equals_size_flat() {
let pattern = Pattern::pattern(
"root",
vec![
Pattern::point("a"),
Pattern::point("b"),
Pattern::point("c"),
],
);
let count = pattern.fold(0, |acc, _| acc + 1);
assert_eq!(count, pattern.size());
assert_eq!(count, 4); }
#[test]
fn fold_count_equals_size_nested() {
let inner = Pattern::pattern(2, vec![Pattern::point(3)]);
let pattern = Pattern::pattern(1, vec![inner, Pattern::point(4)]);
let count = pattern.fold(0, |acc, _| acc + 1);
assert_eq!(count, pattern.size());
assert_eq!(count, 4); }
#[test]
fn fold_count_equals_size_complex() {
let level3 = Pattern::point(4);
let level2 = Pattern::pattern(3, vec![level3]);
let level1 = Pattern::pattern(2, vec![level2]);
let pattern = Pattern::pattern(1, vec![level1, Pattern::point(5)]);
let count = pattern.fold(0, |acc, _| acc + 1);
assert_eq!(count, pattern.size());
assert_eq!(count, 5); }
#[test]
fn fold_pattern_unchanged_after_fold() {
let pattern = Pattern::pattern(1, vec![Pattern::point(2), Pattern::point(3)]);
let original = pattern.clone();
let _ = pattern.fold(0, |acc, v| acc + v);
assert_eq!(pattern, original);
}
#[test]
fn fold_can_be_called_multiple_times() {
let pattern = Pattern::pattern(2, vec![Pattern::point(3), Pattern::point(4)]);
let sum = pattern.fold(0, |acc, v| acc + v);
let product = pattern.fold(1, |acc, v| acc * v);
let count = pattern.fold(0, |acc, _| acc + 1);
assert_eq!(sum, 9); assert_eq!(product, 24); assert_eq!(count, 3);
}
#[test]
fn fold_with_custom_type() {
#[derive(Clone, PartialEq, Debug)]
struct Person {
name: String,
age: u32,
}
let person1 = Person {
name: "Alice".to_string(),
age: 30,
};
let person2 = Person {
name: "Bob".to_string(),
age: 25,
};
let person3 = Person {
name: "Charlie".to_string(),
age: 35,
};
let pattern = Pattern::pattern(
person1.clone(),
vec![
Pattern::point(person2.clone()),
Pattern::point(person3.clone()),
],
);
let count = pattern.fold(0, |acc, _| acc + 1);
assert_eq!(count, 3);
let total_age = pattern.fold(0u32, |acc, p| acc + p.age);
assert_eq!(total_age, 90); }