use proptest::prelude::*;
use proptest_derive::Arbitrary;
fn even(x: &usize) -> bool {
x % 2 == 0
}
fn rem3(x: &usize) -> bool {
x % 3 == 0
}
#[derive(Copy, Clone)]
struct Param(usize);
impl Default for Param {
fn default() -> Self {
Param(100)
}
}
#[derive(Debug, Arbitrary)]
#[proptest(filter("|x| x.foo % 3 == 0"))]
struct T0 {
#[proptest(no_params, filter(even))]
foo: usize,
#[proptest(filter("|x| x % 2 == 1"))]
bar: usize,
#[proptest(strategy = "0..100usize", filter = "|x| x % 2 == 1")]
baz: usize,
#[proptest(value = "42", filter(even))]
quux: usize,
#[proptest(params(Param), strategy("0..=params.0"), filter("|x| *x > 2"))]
wibble: usize,
}
#[derive(Debug, Arbitrary)]
#[proptest(params(Param))]
#[proptest(filter("|x| x.foo % 3 == 0"))]
struct T1 {
#[proptest(filter(even))]
foo: usize,
#[proptest(filter("|x| x % 2 == 1"))]
bar: usize,
#[proptest(strategy = "0..100usize", filter = "|x| x % 2 == 1")]
baz: usize,
#[proptest(value = "42", filter(even))]
quux: usize,
#[proptest(strategy("0..=params.0"), filter("|x| *x > 2"))]
wibble: usize,
}
#[derive(Debug, Arbitrary)]
#[proptest(filter("|x| x.0 % 3 == 0"))]
struct T2(
#[proptest(no_params, filter(even))] usize,
#[proptest(filter("|x| x % 2 == 1"))] usize,
#[proptest(strategy = "0..100usize", filter = "|x| x % 2 == 1")] usize,
#[proptest(value = "42", filter(even))] usize,
#[proptest(params(Param), strategy("0..=params.0"), filter("|x| *x > 2"))]
usize,
);
#[derive(Debug, Arbitrary)]
#[proptest(filter("|x| x.0 % 3 == 0"))]
struct T3(
#[proptest(no_params, filter(even))] usize,
#[proptest(filter("|x| x % 2 == 1"))] usize,
#[proptest(strategy = "0..100usize", filter = "|x| x % 2 == 1")] usize,
#[proptest(value = "42", filter(even))] usize,
#[proptest(params(Param), strategy("0..=params.0"), filter("|x| *x > 2"))]
usize,
);
fn is_v0(v: &T4) -> bool {
if let T4::V0 { .. } = v {
true
} else {
false
}
}
#[derive(Debug, Arbitrary)]
#[proptest(filter(is_v0))]
enum T4 {
V0 {
#[proptest(filter(even))]
field: usize,
},
V1,
}
fn t5_v0_rem_3(v: &T5) -> bool {
if let T5::V0 { field } = v {
rem3(&field)
} else {
false
}
}
fn t5_v1_rem_5(v: &T5) -> bool {
if let T5::V1(field) = v {
field % 5 == 0
} else {
false
}
}
#[derive(Debug, Arbitrary)]
enum T5 {
#[proptest(filter(t5_v0_rem_3))]
V0 {
#[proptest(filter(even))]
field: usize,
},
#[proptest(
strategy("(0..1000usize).prop_map(T5::V1)"),
filter(t5_v1_rem_5)
)]
V1(usize),
}
fn t6_v0_rem_3(v: &T6) -> bool {
if let T6::V0 { field } = v {
rem3(&field)
} else {
false
}
}
fn t6_v1_rem_5(v: &T6) -> bool {
if let T6::V1(field) = v {
field % 5 == 0
} else {
false
}
}
#[derive(Debug, Arbitrary)]
#[proptest(params(Param))]
enum T6 {
#[proptest(filter(t6_v0_rem_3))]
V0 {
#[proptest(filter(even))]
field: usize,
},
#[proptest(
strategy("(0..params.0).prop_map(T6::V1)"),
filter(t6_v1_rem_5)
)]
V1(usize),
}
#[derive(Debug, Arbitrary)]
struct T7 {
#[proptest(filter(even), filter(rem3))]
foo: usize,
}
proptest! {
#[test]
fn t0_test(v: T0) {
assert!(even(&v.foo) && rem3(&v.foo));
assert!(!even(&v.bar));
assert!(!even(&v.baz) && v.baz < 100);
assert!(even(&v.quux) && v.quux == 42);
assert!(even(&v.quux) && v.quux == 42);
assert!(v.wibble > 2 && v.wibble <= 100);
}
#[test]
fn t1_test(v: T1) {
assert!(even(&v.foo) && v.foo % 3 == 0);
assert!(!even(&v.bar));
assert!(!even(&v.baz) && v.baz < 100);
assert!(even(&v.quux) && v.quux == 42);
assert!(v.wibble > 2 && v.wibble <= 100);
}
#[test]
fn t2_test(v: T2) {
assert!(even(&v.0) && v.0 % 3 == 0);
assert!(!even(&v.1));
assert!(!even(&v.2) && v.2 < 100);
assert!(even(&v.3) && v.3 == 42);
assert!(v.4 > 2 && v.4 <= 100);
}
#[test]
fn t3_test(v: T3) {
assert!(even(&v.0) && v.0 % 3 == 0);
assert!(!even(&v.1));
assert!(!even(&v.2) && v.2 < 100);
assert!(even(&v.3) && v.3 == 42);
assert!(v.4 > 2 && v.4 <= 100);
}
#[test]
fn t4_test(v: T4) {
assert!(if let T4::V0 { field } = v { even(&field) } else { false });
}
#[test]
fn t5_test(v: T5) {
match v {
T5::V0 { field } => assert!(rem3(&field) && even(&field)),
T5::V1(field) => assert!(field < 1000 && field % 5 == 0),
}
}
#[test]
fn t6_test(v: T6) {
match v {
T6::V0 { field } => assert!(rem3(&field) && even(&field)),
T6::V1(field) => assert!(field < 100 && field % 5 == 0),
}
}
#[test]
fn t7_test(v: T7) {
assert!(even(&v.foo) && rem3(&v.foo));
}
}
#[test]
fn asserting_arbitrary() {
fn assert_arbitrary<T: Arbitrary>() {}
assert_arbitrary::<T0>();
assert_arbitrary::<T1>();
assert_arbitrary::<T2>();
assert_arbitrary::<T3>();
assert_arbitrary::<T4>();
assert_arbitrary::<T5>();
assert_arbitrary::<T6>();
assert_arbitrary::<T7>();
}