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_all_values_const_true_always_returns_true(pattern in pattern_strategy()) {
prop_assert!(pattern.all_values(|_| true));
}
#[test]
fn prop_all_values_const_false_always_returns_false(pattern in pattern_strategy()) {
prop_assert!(!pattern.all_values(|_| false));
}
#[test]
fn prop_all_values_consistent_with_iterator_all(pattern in pattern_strategy()) {
let predicate = |v: &i32| *v > 0;
let all_values_result = pattern.all_values(predicate);
let values_all_result = pattern.values().into_iter().all(|v| predicate(v));
prop_assert_eq!(all_values_result, values_all_result,
"all_values should match Iterator::all over values()");
}
#[test]
fn prop_all_values_complementary_to_any_value(pattern in pattern_strategy()) {
let predicate = |v: &i32| *v > 0;
let neg_predicate = |v: &i32| *v <= 0;
let all_positive = pattern.all_values(predicate);
let any_non_positive = pattern.any_value(neg_predicate);
prop_assert_eq!(all_positive, !any_non_positive,
"all_values(p) should equal !any_value(!p)");
}
#[test]
fn prop_all_values_monotonic(pattern in pattern_strategy()) {
let loose = |v: &i32| *v > -100;
let strict = |v: &i32| *v > 0;
if pattern.all_values(strict) {
prop_assert!(pattern.all_values(loose),
"If all values satisfy a strict predicate, they should satisfy a looser one");
}
}
#[test]
fn prop_all_values_implies_any_value(pattern in pattern_strategy()) {
let predicate = |v: &i32| *v > 0;
if pattern.all_values(predicate) && pattern.size() > 0 {
prop_assert!(pattern.any_value(predicate),
"If all values satisfy predicate, then at least one does (for non-empty patterns)");
}
}
}