Skip to content

Commit

Permalink
Feat: Add valid-range-aware int shrinker
Browse files Browse the repository at this point in the history
This enables having shinking that is kept within the range
given to generator, so shrinker, for example, avoids shrinking
to zero if zero is regarded as out of range in given property.

- Refactor: Simplify the int decrement iterator.
  The iterator is used in int shrinking, and did before have
  knowledge of it being used togheter with eager shrink
  iterator. Simplify decrement shrinker by having the logic
  for not repeating some values to the eager iterator instead.

- Deprecate old `shrink::int()`, and refer to use of either
  `shrink::int_in_range` for updated use or
  `shrink::int_to_zero` for old behaviour.

- Let shrinker emit candidates on both sides of target
  value, in essence trying out more candidates before giving
  up.
  • Loading branch information
jockbert committed May 9, 2024
1 parent dc466ed commit 5739ee8
Show file tree
Hide file tree
Showing 10 changed files with 334 additions and 86 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ and shrinkers for:

Other known limitations:

* For now, integer and float generators do not limit them self to shrink to
* For now, float generators do not limit them self to shrink to
values within given generator range, but will by default shrink toward zero.
For instance, let say that we create generator
`monkey_test::gen::i64::ranged(10..100)`, the associated shrinker will not
only try candidates withing the given range `10..100`, but can also try other
values like -10 and will ultimately try to shrink toward zero.
`monkey_test::gen::f64::ranged(10.0..100.0)`, the associated shrinker will not
only try candidates withing the given range `10.0..100.0`, but can also try other
values like -10.0 and will ultimately try to shrink toward zero.

For details on recent changes, see the [CHANGELOG](CHANGELOG.md).

Expand Down
8 changes: 4 additions & 4 deletions src/gen/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::ops::RangeBounds;
/// value zero, if in range of given bounds.
pub fn ranged<E, B>(bounds: B) -> BoxGen<E>
where
E: PrimInt + SampleUniform + 'static + std::fmt::Debug,
E: PrimInt + SampleUniform + std::fmt::Debug + 'static,
B: RangeBounds<E>,
{
let min = start(&bounds);
Expand All @@ -34,7 +34,7 @@ where
/// name, since `ranged` should be preferred.
pub fn completely_random<E, B>(bounds: B) -> BoxGen<E>
where
E: PrimInt + SampleUniform + 'static,
E: PrimInt + SampleUniform + std::fmt::Debug + 'static,
B: RangeBounds<E>,
{
let min = start(&bounds);
Expand All @@ -44,7 +44,7 @@ where
let distr = rand::distributions::Uniform::new_inclusive(min, max);
rand_chacha::ChaCha8Rng::seed_from_u64(seed).sample_iter(distr)
})
.with_shrinker(crate::shrink::int())
.with_shrinker(crate::shrink::int_in_range(min, max))
}

fn start<E, B>(bounds: &B) -> E
Expand Down Expand Up @@ -108,6 +108,6 @@ mod tests {

#[test]
fn has_shrinker() {
assert_generator_can_shrink(super::ranged(..10), 123);
assert_generator_can_shrink(super::ranged(..1000), 123);
}
}
4 changes: 2 additions & 2 deletions src/gen/mix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,13 @@ mod test {
#[test]
fn mix_should_reuse_shrinker_from_first_generator() {
let with_shrinker = super::mix_evenly(&[
crate::gen::u8::any().with_shrinker(crate::shrink::int()),
crate::gen::u8::any().with_shrinker(crate::shrink::int_to_zero()),
crate::gen::u8::any().with_shrinker(crate::shrink::none()),
]);

let without_shrinker = super::mix_evenly(&[
crate::gen::u8::any().with_shrinker(crate::shrink::none()),
crate::gen::u8::any().with_shrinker(crate::shrink::int()),
crate::gen::u8::any().with_shrinker(crate::shrink::int_to_zero()),
]);

assert_generator_can_shrink(with_shrinker, 10);
Expand Down
2 changes: 1 addition & 1 deletion src/gen/sized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub fn progressively_increasing(
max_iterator(start_size, percent_increase, max_size)
.map(move |max| rng.sample(Uniform::new_inclusive(0usize, max)))
})
.with_shrinker(crate::shrink::int())
.with_shrinker(crate::shrink::int_to_zero())
}

fn max_iterator(
Expand Down
7 changes: 6 additions & 1 deletion src/shrink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ pub use bool::bool_to_true;
pub use float::float;
pub use from_fn::from_fn;
pub use from_fn::from_fn_boxed;
pub use integer::int_to_zero as int;

#[allow(deprecated)]
pub use integer::int;
pub use integer::int_in_range;
pub use integer::int_to_zero;

pub use map::map;
pub use no_shrink::none;
pub use zip::zip;
Loading

0 comments on commit 5739ee8

Please sign in to comment.