use pattern_core::Pattern;
use proptest::prelude::*;
fn pattern_strategy() -> impl Strategy<Value = Pattern<i32>> {
let leaf = any::<i32>().prop_map(Pattern::point);
leaf.prop_recursive(
3, 10, 5, |inner| {
(any::<i32>(), prop::collection::vec(inner, 0..5))
.prop_map(|(v, elements)| Pattern::pattern(v, elements))
},
)
}
proptest! {
#[test]
fn prop_any_value_const_true_always_returns_true(pattern in pattern_strategy()) {
prop_assert!(pattern.any_value(|_| true));
}
#[test]
fn prop_any_value_const_false_always_returns_false(pattern in pattern_strategy()) {
prop_assert!(!pattern.any_value(|_| false));
}
#[test]
fn prop_any_value_consistent_with_iterator_any(pattern in pattern_strategy()) {
let predicate = |v: &i32| *v > 0;
let any_value_result = pattern.any_value(predicate);
let values_any_result = pattern.values().into_iter().any(|v| predicate(v));
prop_assert_eq!(any_value_result, values_any_result,
"any_value should match Iterator::any over values()");
}
#[test]
fn prop_any_value_with_negation(pattern in pattern_strategy()) {
let predicate = |v: &i32| *v > 0;
let neg_predicate = |v: &i32| *v <= 0;
let has_positive = pattern.any_value(predicate);
let has_non_positive = pattern.any_value(neg_predicate);
if pattern.size() > 0 {
prop_assert!(has_positive || has_non_positive,
"For non-empty patterns, either some value satisfies p or some satisfies !p");
}
}
#[test]
fn prop_any_value_monotonic(pattern in pattern_strategy()) {
let strict = |v: &i32| *v > 10;
let loose = |v: &i32| *v > 5;
if pattern.any_value(strict) {
prop_assert!(pattern.any_value(loose),
"If a stricter predicate matches, a looser one should too");
}
}
}