use pattern_core::Pattern;
#[test]
fn map_then_fold_composition() {
let pattern = Pattern::pattern(1, vec![Pattern::point(2), Pattern::point(3)]);
let result = pattern.map(|&v| v * 2).fold(0, |acc, &v| acc + v);
assert_eq!(result, 12); }
#[test]
fn map_transform_type_then_fold() {
let pattern = Pattern::pattern("hello", vec![Pattern::point("world"), Pattern::point("!")]);
let total_length = pattern.map(|s| s.len()).fold(0, |acc, &len| acc + len);
assert_eq!(total_length, 11); }
#[test]
fn map_then_fold_preserves_structure() {
let pattern = Pattern::pattern(
1,
vec![
Pattern::pattern(2, vec![Pattern::point(3)]),
Pattern::point(4),
],
);
let result = pattern.map(|&v| v + 10).fold(0, |acc, &v| acc + v);
assert_eq!(result, 50); }
#[test]
fn fold_multiple_times_on_same_pattern() {
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);
let max = pattern.fold(i32::MIN, |acc, &v| acc.max(v));
assert_eq!(sum, 9); assert_eq!(product, 24); assert_eq!(count, 3);
assert_eq!(max, 4);
}
#[test]
fn fold_after_fold_independent() {
let pattern = Pattern::pattern("a", vec![Pattern::point("b"), Pattern::point("c")]);
let concat1 = pattern.fold(String::new(), |acc, s| acc + s);
let concat2 = pattern.fold(String::from("start:"), |acc, s| acc + s);
assert_eq!(concat1, "abc");
assert_eq!(concat2, "start:abc");
}
#[test]
fn pattern_unchanged_after_single_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 pattern_unchanged_after_multiple_folds() {
let pattern = Pattern::pattern("x", vec![Pattern::point("y"), Pattern::point("z")]);
let original = pattern.clone();
let _ = pattern.fold(String::new(), |acc, s| acc + s);
let _ = pattern.fold(0, |acc, _| acc + 1);
let _ = pattern.fold(Vec::new(), |mut acc: Vec<String>, s| {
acc.push(s.to_string());
acc
});
assert_eq!(pattern, original);
}
#[test]
fn pattern_reusable_after_fold() {
let pattern = Pattern::pattern(5, vec![Pattern::point(10)]);
let sum1 = pattern.fold(0, |acc, &v| acc + v);
let sum2 = pattern.fold(100, |acc, &v| acc + v);
assert_eq!(sum1, 15); assert_eq!(sum2, 115); }
#[test]
fn complex_pipeline_map_fold_compare() {
let pattern1 = Pattern::pattern(1, vec![Pattern::point(2), Pattern::point(3)]);
let pattern2 = Pattern::pattern(10, vec![Pattern::point(20), Pattern::point(30)]);
let sum1 = pattern1.clone().map(|&v| v * 2).fold(0, |acc, &v| acc + v);
let sum2 = pattern2.clone().map(|&v| v / 10).fold(0, |acc, &v| acc + v);
assert_eq!(sum1, 12); assert_eq!(sum2, 6); assert!(sum1 > sum2);
}
#[test]
fn pipeline_with_filtering_logic() {
let pattern = Pattern::pattern(
1,
vec![
Pattern::point(2),
Pattern::point(3),
Pattern::point(4),
Pattern::point(5),
],
);
let even_count = pattern.fold(0, |acc, &v| if v % 2 == 0 { acc + 1 } else { acc });
let odd_sum = pattern.fold(0, |acc, &v| if v % 2 != 0 { acc + v } else { acc });
assert_eq!(even_count, 2); assert_eq!(odd_sum, 9); }
#[test]
fn pipeline_map_to_option_then_fold() {
let pattern = Pattern::pattern(1, vec![Pattern::point(2), Pattern::point(3)]);
let with_options = pattern.map(|&v| if v > 1 { Some(v * 10) } else { None });
let valid_values = with_options.fold(Vec::new(), |mut acc, opt| {
if let Some(val) = opt {
acc.push(*val);
}
acc
});
assert_eq!(valid_values, vec![20, 30]); }
#[test]
fn pipeline_with_values_and_iterator() {
let pattern = Pattern::pattern(
1,
vec![Pattern::point(2), Pattern::point(3), Pattern::point(4)],
);
let doubled_sum: i32 = pattern.values().iter().map(|&&v| v * 2).sum();
assert_eq!(doubled_sum, 20);
let direct_fold_doubled = pattern.fold(0, |acc, &v| acc + (v * 2));
assert_eq!(doubled_sum, direct_fold_doubled);
}
#[test]
fn pipeline_nested_transformations() {
let inner = Pattern::pattern(5, vec![Pattern::point(6)]);
let pattern = Pattern::pattern(1, vec![Pattern::point(2), inner, Pattern::point(7)]);
let result = pattern
.map(|&v| v * 2)
.map(|&v| v.to_string())
.fold(String::new(), |acc, s| {
if acc.is_empty() {
s.to_string()
} else {
format!("{}-{}", acc, s)
}
});
assert_eq!(result, "2-4-10-12-14"); }
#[test]
fn fold_with_size_and_depth_queries() {
let pattern = Pattern::pattern(
1,
vec![
Pattern::pattern(2, vec![Pattern::point(3)]),
Pattern::point(4),
],
);
let fold_count = pattern.fold(0, |acc, _| acc + 1);
assert_eq!(fold_count, pattern.size());
assert_eq!(pattern.depth(), 2);
assert_eq!(pattern.length(), 2);
}
#[test]
fn map_fold_with_custom_types() {
#[derive(Clone, Debug)]
struct Point {
x: i32,
y: i32,
}
let p1 = Point { x: 1, y: 2 };
let p2 = Point { x: 3, y: 4 };
let p3 = Point { x: 5, y: 6 };
let pattern = Pattern::pattern(p1, vec![Pattern::point(p2), Pattern::point(p3)]);
let x_sum = pattern.map(|p| p.x).fold(0, |acc, &x| acc + x);
assert_eq!(x_sum, 9); }