Macro shrink_a_field

Source
macro_rules! shrink_a_field {
    ($obj:expr, $field:ident) => { ... };
    ($obj:expr, $field:ident, $wrap_fn:expr, $unwrap_fn:expr) => { ... };
}
Expand description

Shrinks one field of an object.

For any object t of type T and a is one of its field, shrink_a_field!(t, a) will result in an iterator of type T, whose a fields are shrinked and the other fields are kept untouched. For example,

use rs_quickcheck_util::shrink_a_field;

#[derive(Debug, Clone)]
struct T {
    a: i64,
    b: i64,
}
let t = T {
    a: 100,
    b: 42,
};
for x in shrink_a_field!(t, a) {
    assert!(x.a < t.a);
    assert_eq!(x.b, t.b);
}

Sometimes, a field must be shrinked with a different behaviour, e.g., for a Vec field, shrinking the vector but not shrinking their elements. This can be achieved by “wrapping” the field.

use rs_quickcheck_util::{shrink_a_field, Unshrinkable};

#[derive(Debug, Clone)]
struct T {
    a: Vec<i64>,
}
let t = T {
    a: [10, 10].into(),
};
let it = shrink_a_field!(
    t,
    a,
    |xs: &Vec<i64>| {
        xs.iter().map(|x| Unshrinkable::new(*x)).collect::<Vec<_>>()
    },
    |xs: Vec<Unshrinkable::<i64>>| {
        xs.into_iter()
            .map(|x| x.take())
            .collect::<Vec<_>>()
    }
);
for x in it {
    assert!(x.a.iter().all(|y| *y == 10));
}