use pattern_core::Pattern;
use std::cmp::Ordering;
#[test]
fn test_compare_atomic_patterns_different_values() {
let p1 = Pattern::point(1);
let p2 = Pattern::point(2);
assert_eq!(p1.cmp(&p2), Ordering::Less);
assert_eq!(p2.cmp(&p1), Ordering::Greater);
assert!(p1 < p2);
assert!(p1 <= p2);
assert!(p2 > p1);
assert!(p2 >= p1);
assert!(p1 != p2);
}
#[test]
fn test_compare_atomic_patterns_same_value() {
let p1 = Pattern::point(5);
let p2 = Pattern::point(5);
assert_eq!(p1.cmp(&p2), Ordering::Equal);
assert!(p1 == p2);
assert!(p1 <= p2);
assert!(p1 >= p2);
assert!(!(p1 < p2));
assert!(!(p1 > p2));
assert_eq!(p1.cmp(&p1), Ordering::Equal);
}
#[test]
fn test_compare_nested_patterns_different_values() {
let p1 = Pattern::pattern(3, vec![Pattern::point(100)]);
let p2 = Pattern::pattern(4, vec![Pattern::point(1)]);
assert!(p1 < p2);
let p3 = Pattern::pattern(
1,
vec![
Pattern::point(999),
Pattern::point(888),
Pattern::point(777),
],
);
let p4 = Pattern::pattern(2, vec![Pattern::point(1)]);
assert!(p3 < p4); }
#[test]
fn test_compare_nested_patterns_same_value_different_elements() {
let p1 = Pattern::pattern(5, vec![Pattern::point(1)]);
let p2 = Pattern::pattern(5, vec![Pattern::point(2)]);
assert!(p1 < p2);
let p3 = Pattern::pattern(5, vec![Pattern::point(1), Pattern::point(3)]);
let p4 = Pattern::pattern(5, vec![Pattern::point(1), Pattern::point(4)]);
assert!(p3 < p4);
let p5 = Pattern::pattern(5, vec![Pattern::pattern(1, vec![Pattern::point(10)])]);
let p6 = Pattern::pattern(5, vec![Pattern::pattern(1, vec![Pattern::point(20)])]);
assert!(p5 < p6); }
#[test]
fn test_compare_patterns_prefix() {
let p1 = Pattern::pattern(5, vec![Pattern::point(1)]);
let p2 = Pattern::pattern(5, vec![Pattern::point(1), Pattern::point(2)]);
assert!(p1 < p2);
let p3 = Pattern::pattern(5, vec![]);
let p4 = Pattern::pattern(5, vec![Pattern::point(1)]);
assert!(p3 < p4);
let p5 = Pattern::pattern(5, vec![Pattern::point(1), Pattern::point(2)]);
let p6 = Pattern::pattern(
5,
vec![Pattern::point(1), Pattern::point(2), Pattern::point(3)],
);
assert!(p5 < p6); }
#[test]
fn test_compare_deeply_nested_patterns() {
fn create_deep_pattern(depth: usize, value: i32) -> Pattern<i32> {
if depth == 0 {
Pattern::point(value)
} else {
Pattern::pattern(value, vec![create_deep_pattern(depth - 1, value + 1)])
}
}
let p1 = create_deep_pattern(80, 0);
let p2 = create_deep_pattern(80, 0);
assert_eq!(p1.cmp(&p2), Ordering::Equal);
let p3 = create_deep_pattern(80, 0);
let p4 = create_deep_pattern(80, 1);
assert!(p3 < p4);
let p5 = Pattern::pattern(0, vec![create_deep_pattern(79, 1)]);
let p6 = Pattern::pattern(0, vec![create_deep_pattern(79, 2)]);
assert!(p5 < p6); }
#[test]
fn test_compare_wide_patterns() {
let elements1: Vec<Pattern<i32>> = (0..1500).map(Pattern::point).collect();
let p1 = Pattern::pattern(0, elements1);
let elements2: Vec<Pattern<i32>> = (0..1500).map(Pattern::point).collect();
let p2 = Pattern::pattern(0, elements2);
assert_eq!(p1.cmp(&p2), Ordering::Equal);
let mut elements3: Vec<Pattern<i32>> = (0..1500).map(Pattern::point).collect();
elements3[1000] = Pattern::point(9999); let p3 = Pattern::pattern(0, elements3);
assert!(p2 < p3);
let elements4: Vec<Pattern<i32>> = (0..1000).map(Pattern::point).collect();
let p4 = Pattern::pattern(0, elements4);
let elements5: Vec<Pattern<i32>> = (0..2000).map(Pattern::point).collect();
let p5 = Pattern::pattern(0, elements5);
assert!(p4 < p5); }
#[test]
fn test_sort_small_collection() {
let mut patterns = vec![
Pattern::point(5),
Pattern::point(2),
Pattern::point(8),
Pattern::point(1),
Pattern::point(9),
Pattern::point(3),
Pattern::point(7),
Pattern::point(4),
Pattern::point(6),
Pattern::point(10),
];
patterns.sort();
let expected: Vec<Pattern<i32>> = (1..=10).map(Pattern::point).collect();
assert_eq!(patterns, expected);
}
#[test]
fn test_sort_large_collection() {
let mut patterns: Vec<Pattern<i32>> = (0..1000)
.map(|i| Pattern::point((i * 7919) % 10000)) .collect();
patterns.sort();
for i in 0..patterns.len() - 1 {
assert!(patterns[i] <= patterns[i + 1], "Not sorted at index {}", i);
}
}
#[test]
fn test_binary_search() {
let patterns: Vec<Pattern<i32>> = (0..100).step_by(2).map(Pattern::point).collect();
let target = Pattern::point(50);
match patterns.binary_search(&target) {
Ok(index) => assert_eq!(patterns[index], target),
Err(_) => panic!("Should have found pattern"),
}
let target2 = Pattern::point(51); match patterns.binary_search(&target2) {
Ok(_) => panic!("Should not have found pattern"),
Err(index) => {
assert!(index > 0 && index < patterns.len());
assert!(patterns[index - 1] < target2);
assert!(target2 < patterns[index]);
}
}
}
#[test]
fn test_sort_stability() {
#[derive(Debug)]
struct Tagged {
pattern: Pattern<i32>,
original_index: usize,
}
let mut tagged: Vec<Tagged> = vec![
Tagged {
pattern: Pattern::point(5),
original_index: 0,
},
Tagged {
pattern: Pattern::point(3),
original_index: 1,
},
Tagged {
pattern: Pattern::point(5),
original_index: 2,
},
Tagged {
pattern: Pattern::point(3),
original_index: 3,
},
Tagged {
pattern: Pattern::point(5),
original_index: 4,
},
];
tagged.sort_by(|a, b| a.pattern.cmp(&b.pattern));
let threes_end = tagged
.iter()
.position(|t| t.pattern == Pattern::point(5))
.unwrap();
for i in 0..threes_end {
assert_eq!(tagged[i].pattern, Pattern::point(3));
}
for i in threes_end..tagged.len() {
assert_eq!(tagged[i].pattern, Pattern::point(5));
}
assert!(tagged[0].original_index < tagged[1].original_index);
assert!(tagged[2].original_index < tagged[3].original_index);
assert!(tagged[3].original_index < tagged[4].original_index);
}