use crate::*;
use super::and;
pub fn vec<'a, T>(inner_fact: impl Fact<'a, T>) -> impl Fact<'a, Vec<T>>
where
T: Target<'a> + Clone,
{
lambda("vec", inner_fact, |g, f, t: Vec<T>| {
t.into_iter()
.enumerate()
.map(|(i, o)| {
f.mutate(g, o)
.map_check_err(|e| format!("seq[{}]: {}", i, e))
})
.collect::<Result<Vec<_>, _>>()
})
}
pub fn vec_len<'a, T>(len: usize) -> LambdaUnit<'a, Vec<T>>
where
T: Target<'a> + Clone + 'a,
{
lambda_unit("vec_len", move |g, mut t: Vec<T>| {
if t.len() > len {
g.fail(format!(
"vec should be of length {} but is actually of length {}",
len,
t.len()
))?;
t = t[0..len].to_vec();
}
while t.len() < len {
t.push(g.arbitrary(|| {
format!(
"vec should be of length {} but is actually of length {}",
len,
t.len()
)
})?)
}
Ok(t)
})
}
pub fn vec_of_length<'a, T>(len: usize, inner_fact: impl Fact<'a, T>) -> impl Fact<'a, Vec<T>>
where
T: Target<'a> + 'a,
{
and(vec_len(len), vec(inner_fact))
}
#[cfg(test)]
mod tests {
use std::sync::{
atomic::{AtomicU8, Ordering},
Arc,
};
use crate::facts::*;
use arbitrary::*;
#[derive(Debug, Clone, PartialEq, Arbitrary)]
struct S {
x: u32,
y: u32,
}
#[test]
fn test_seq() {
observability::test_run().ok();
let mut g = utils::random_generator();
let f = facts![
brute("len must be >= 3", |v: &Vec<_>| v.len() >= 3),
vec(eq(1)),
];
let ones = f.clone().build(&mut g);
f.check(&ones).unwrap();
assert!(ones.len() >= 3);
assert!(ones.iter().all(|s| *s == 1));
}
#[test]
fn test_len() {
observability::test_run().ok();
let mut g = utils::random_generator();
let ones: Vec<u8> = vec_len(5).build(&mut g);
vec_len(5).check(&ones).unwrap();
assert_eq!(ones.len(), 5);
}
#[test]
fn test_sized_seq() {
let mut g = utils::random_generator();
let f = || vec_of_length(5, consecutive_int_(0));
let count: Vec<u8> = f().build(&mut g);
f().check(&count).unwrap();
assert_eq!(count, vec![0, 1, 2, 3, 4]);
}
#[test]
fn test_mutation_replay() {
let mut g = utils::random_generator();
let piecewise = move || {
let count = Arc::new(AtomicU8::new(0));
lambda("piecewise", (), move |g, (), mut t| {
let c = count.fetch_add(1, Ordering::SeqCst);
if c < 3 {
g.set(&mut t, &999, || "i'm being difficult, haha")?;
}
Ok(t)
})
};
{
let f = vec_of_length(10, facts!(consecutive_int_(0), piecewise()));
let items = f.build(&mut g);
assert_eq!(items, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
{
let mut f = facts!(eq(0), piecewise());
for _ in 0..3 {
let val = f.mutate(&mut g, 0).unwrap();
assert!(f.clone().check(&val).is_err());
}
let val = f.mutate(&mut g, 0).unwrap();
f.check(&val).unwrap();
}
}
}