use pattern_core::Pattern;
use std::time::Instant;
fn create_deep_pattern(depth: usize) -> Pattern<i32> {
let mut pattern = Pattern::point(depth as i32);
for i in (0..depth).rev() {
pattern = Pattern::pattern(i as i32, vec![pattern]);
}
pattern
}
fn create_balanced_tree(depth: usize, value: i32) -> Pattern<i32> {
if depth == 0 {
Pattern::point(value)
} else {
Pattern::pattern(
value,
vec![
create_balanced_tree(depth - 1, value * 2),
create_balanced_tree(depth - 1, value * 2 + 1),
],
)
}
}
fn create_wide_pattern(width: usize) -> Pattern<i32> {
let elements: Vec<Pattern<i32>> = (0..width).map(|i| Pattern::point(i as i32)).collect();
Pattern::pattern(-1, elements)
}
fn create_flat_pattern(size: usize) -> Pattern<i32> {
let elements: Vec<Pattern<i32>> = (1..size).map(|i| Pattern::point(i as i32)).collect();
Pattern::pattern(0, elements)
}
#[test]
fn fold_handles_100_level_deep_nesting() {
let pattern = create_deep_pattern(100);
assert_eq!(pattern.depth(), 100);
assert_eq!(pattern.size(), 101);
let sum = pattern.fold(0i32, |acc, v| acc + v);
assert_eq!(sum, 5050);
let values = pattern.values();
assert_eq!(values.len(), 101);
}
#[test]
fn fold_handles_200_level_deep_nesting() {
let pattern = create_deep_pattern(200);
assert_eq!(pattern.depth(), 200);
assert_eq!(pattern.size(), 201);
let count = pattern.fold(0usize, |acc, _| acc + 1);
assert_eq!(count, 201);
}
#[test]
fn fold_handles_500_level_deep_nesting() {
let pattern = create_deep_pattern(500);
assert_eq!(pattern.depth(), 500);
let count = pattern.fold(0usize, |acc, _| acc + 1);
assert_eq!(count, 501);
}
#[test]
fn values_handles_deep_nesting() {
let pattern = create_deep_pattern(100);
let values = pattern.values();
assert_eq!(values.len(), 101);
for (i, &&v) in values.iter().enumerate() {
assert_eq!(v, i as i32);
}
}
#[test]
fn fold_handles_1000_wide_siblings() {
let pattern = create_wide_pattern(1000);
assert_eq!(pattern.size(), 1001); assert_eq!(pattern.length(), 1000);
let sum = pattern.fold(0i32, |acc, v| acc + v);
assert_eq!(sum, 499499);
}
#[test]
fn fold_handles_5000_wide_siblings() {
let pattern = create_wide_pattern(5000);
assert_eq!(pattern.size(), 5001);
let count = pattern.fold(0usize, |acc, _| acc + 1);
assert_eq!(count, 5001);
}
#[test]
fn fold_handles_10000_wide_siblings() {
let pattern = create_wide_pattern(10000);
assert_eq!(pattern.size(), 10001);
let count = pattern.fold(0usize, |acc, _| acc + 1);
assert_eq!(count, 10001);
}
#[test]
fn values_handles_wide_patterns() {
let pattern = create_wide_pattern(1000);
let values = pattern.values();
assert_eq!(values.len(), 1001);
assert_eq!(*values[0], -1);
for i in 1..=1000 {
assert_eq!(*values[i], (i - 1) as i32);
}
}
#[test]
fn fold_1000_nodes_completes_quickly() {
let pattern = create_balanced_tree(9, 1);
assert_eq!(pattern.size(), 1023);
let start = Instant::now();
let sum = pattern.fold(0i32, |acc, v| acc + v);
let duration = start.elapsed();
assert!(sum > 0);
println!("Fold of 1023 nodes took: {:?}", duration);
assert!(
duration.as_millis() < 10,
"Fold took {:?}, expected < 10ms",
duration
);
}
#[test]
fn fold_flat_1000_nodes_completes_quickly() {
let pattern = create_flat_pattern(1000);
assert_eq!(pattern.size(), 1000);
let start = Instant::now();
let sum = pattern.fold(0i32, |acc, v| acc + v);
let duration = start.elapsed();
assert_eq!(sum, 499500);
println!("Flat fold of 1000 nodes took: {:?}", duration);
assert!(
duration.as_millis() < 10,
"Fold took {:?}, expected < 10ms",
duration
);
}
#[test]
fn values_1000_nodes_completes_quickly() {
let pattern = create_balanced_tree(9, 1);
assert_eq!(pattern.size(), 1023);
let start = Instant::now();
let values = pattern.values();
let duration = start.elapsed();
assert_eq!(values.len(), 1023);
println!("Values of 1023 nodes took: {:?}", duration);
assert!(
duration.as_millis() < 10,
"Values took {:?}, expected < 10ms",
duration
);
}
#[test]
fn fold_handles_10000_elements() {
let pattern = create_flat_pattern(10000);
assert_eq!(pattern.size(), 10000);
let start = Instant::now();
let sum = pattern.fold(0i64, |acc, v| acc + (*v as i64));
let duration = start.elapsed();
assert_eq!(sum, 49995000);
println!("Fold of 10,000 elements took: {:?}", duration);
assert!(duration.as_millis() < 100);
}
#[test]
fn values_handles_10000_elements() {
let pattern = create_flat_pattern(10000);
let start = Instant::now();
let values = pattern.values();
let duration = start.elapsed();
assert_eq!(values.len(), 10000);
println!("Values of 10,000 elements took: {:?}", duration);
assert!(duration.as_millis() < 100);
}
#[test]
fn fold_handles_balanced_tree_with_8000_plus_nodes() {
let pattern = create_balanced_tree(12, 1);
assert_eq!(pattern.size(), 8191);
let start = Instant::now();
let count = pattern.fold(0usize, |acc, _| acc + 1);
let duration = start.elapsed();
assert_eq!(count, 8191);
println!(
"Fold of 8191 nodes (balanced tree depth 12) took: {:?}",
duration
);
assert!(duration.as_millis() < 50);
}
#[test]
fn fold_deep_and_wide_pattern() {
fn create_deep_wide(depth: usize, width: usize) -> Pattern<i32> {
if depth == 0 {
Pattern::point(0)
} else {
let children: Vec<Pattern<i32>> = (0..width.min(10))
.map(|_| create_deep_wide(depth - 1, width))
.collect();
Pattern::pattern(depth as i32, children)
}
}
let pattern = create_deep_wide(10, 5);
let count = pattern.fold(0usize, |acc, _| acc + 1);
assert!(count > 1000);
let values = pattern.values();
assert_eq!(values.len(), count);
}
#[test]
fn fold_reusable_on_large_pattern() {
let pattern = create_flat_pattern(1000);
let sum = pattern.fold(0i32, |acc, v| acc + v);
let count = pattern.fold(0usize, |acc, _| acc + 1);
let max = pattern.fold(i32::MIN, |acc, v| acc.max(*v));
let min = pattern.fold(i32::MAX, |acc, v| acc.min(*v));
assert_eq!(sum, 499500);
assert_eq!(count, 1000);
assert_eq!(max, 999);
assert_eq!(min, 0);
}
#[test]
fn fold_large_pattern_preserves_order() {
let pattern = create_flat_pattern(1000);
let concat = pattern.fold(String::new(), |mut acc, v| {
if !acc.is_empty() {
acc.push(',');
}
acc.push_str(&v.to_string());
acc
});
assert!(concat.starts_with("0,1,2,3,4,5"));
assert!(concat.ends_with("997,998,999"));
}