use std::char; use std::collections::{ BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque, }; use std::env; use std::ffi::{CString, OsString}; use std::hash::{BuildHasher, Hash}; use std::iter::{empty, once}; use std::net::{ IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, }; use std::num::Wrapping; use std::num::{ NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, }; use std::ops::{ Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, }; use std::path::PathBuf; use std::sync::Arc; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use rand::seq::SliceRandom; use rand::{self, Rng, SeedableRng}; /// Gen represents a PRNG. /// /// It is the source of randomness from which QuickCheck will generate /// values. An instance of `Gen` is passed to every invocation of /// `Arbitrary::arbitrary`, which permits callers to use lower level RNG /// routines to generate values. /// /// It is unspecified whether this is a secure RNG or not. Therefore, callers /// should assume it is insecure. pub struct Gen { rng: rand::rngs::SmallRng, size: usize, } impl Gen { /// Returns a `Gen` with the given size configuration. /// /// The `size` parameter controls the size of random values generated. /// For example, it specifies the maximum length of a randomly generated /// vector, but is and should not be used to control the range of a /// randomly generated number. (Unless that number is used to control the /// size of a data structure.) pub fn new(size: usize) -> Gen { Gen { rng: rand::rngs::SmallRng::from_entropy(), size: size } } /// Returns the size configured with this generator. pub fn size(&self) -> usize { self.size } /// Choose among the possible alternatives in the slice given. If the slice /// is empty, then `None` is returned. Otherwise, a non-`None` value is /// guaranteed to be returned. pub fn choose<'a, T>(&mut self, slice: &'a [T]) -> Option<&'a T> { slice.choose(&mut self.rng) } fn gen(&mut self) -> T where rand::distributions::Standard: rand::distributions::Distribution, { self.rng.gen() } fn gen_range(&mut self, range: R) -> T where T: rand::distributions::uniform::SampleUniform, R: rand::distributions::uniform::SampleRange, { self.rng.gen_range(range) } } /// Creates a shrinker with zero elements. pub fn empty_shrinker() -> Box> { Box::new(empty()) } /// Creates a shrinker with a single element. pub fn single_shrinker(value: A) -> Box> { Box::new(once(value)) } /// `Arbitrary` describes types whose values can be randomly generated and /// shrunk. /// /// Aside from shrinking, `Arbitrary` is different from typical RNGs in that /// it respects `Gen::size()` for controlling how much memory a particular /// value uses, for practical purposes. For example, `Vec::arbitrary()` /// respects `Gen::size()` to decide the maximum `len()` of the vector. /// This behavior is necessary due to practical speed and size limitations. /// Conversely, `i32::arbitrary()` ignores `size()` since all `i32` values /// require `O(1)` memory and operations between `i32`s require `O(1)` time /// (with the exception of exponentiation). /// /// Additionally, all types that implement `Arbitrary` must also implement /// `Clone`. pub trait Arbitrary: Clone + 'static { /// Return an arbitrary value. /// /// Implementations should respect `Gen::size()` when decisions about how /// big a particular value should be. Implementations should generally /// defer to other `Arbitrary` implementations to generate other random /// values when necessary. The `Gen` type also offers a few RNG helper /// routines. fn arbitrary(g: &mut Gen) -> Self; /// Return an iterator of values that are smaller than itself. /// /// The way in which a value is "smaller" is implementation defined. In /// some cases, the interpretation is obvious: shrinking an integer should /// produce integers smaller than itself. Others are more complex, for /// example, shrinking a `Vec` should both shrink its size and shrink its /// component values. /// /// The iterator returned should be bounded to some reasonable size. /// /// It is always correct to return an empty iterator, and indeed, this /// is the default implementation. The downside of this approach is that /// witnesses to failures in properties will be more inscrutable. fn shrink(&self) -> Box> { empty_shrinker() } } impl Arbitrary for () { fn arbitrary(_: &mut Gen) -> () { () } } impl Arbitrary for bool { fn arbitrary(g: &mut Gen) -> bool { g.gen() } fn shrink(&self) -> Box> { if *self { single_shrinker(false) } else { empty_shrinker() } } } impl Arbitrary for Option { fn arbitrary(g: &mut Gen) -> Option { if g.gen() { None } else { Some(Arbitrary::arbitrary(g)) } } fn shrink(&self) -> Box>> { match *self { None => empty_shrinker(), Some(ref x) => { let chain = single_shrinker(None).chain(x.shrink().map(Some)); Box::new(chain) } } } } impl Arbitrary for Result { fn arbitrary(g: &mut Gen) -> Result { if g.gen() { Ok(Arbitrary::arbitrary(g)) } else { Err(Arbitrary::arbitrary(g)) } } fn shrink(&self) -> Box>> { match *self { Ok(ref x) => { let xs = x.shrink(); let tagged = xs.map(Ok); Box::new(tagged) } Err(ref x) => { let xs = x.shrink(); let tagged = xs.map(Err); Box::new(tagged) } } } } macro_rules! impl_arb_for_single_tuple { ($(($type_param:ident, $tuple_index:tt),)*) => { impl<$($type_param),*> Arbitrary for ($($type_param,)*) where $($type_param: Arbitrary,)* { fn arbitrary(g: &mut Gen) -> ($($type_param,)*) { ( $( $type_param::arbitrary(g), )* ) } fn shrink(&self) -> Box> { let iter = ::std::iter::empty(); $( let cloned = self.clone(); let iter = iter.chain( self.$tuple_index.shrink().map(move |shr_value| { let mut result = cloned.clone(); result.$tuple_index = shr_value; result }) ); )* Box::new(iter) } } }; } macro_rules! impl_arb_for_tuples { (@internal [$($acc:tt,)*]) => { }; (@internal [$($acc:tt,)*] ($type_param:ident, $tuple_index:tt), $($rest:tt,)*) => { impl_arb_for_single_tuple!($($acc,)* ($type_param, $tuple_index),); impl_arb_for_tuples!(@internal [$($acc,)* ($type_param, $tuple_index),] $($rest,)*); }; ($(($type_param:ident, $tuple_index:tt),)*) => { impl_arb_for_tuples!(@internal [] $(($type_param, $tuple_index),)*); }; } impl_arb_for_tuples! { (A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5), (G, 6), (H, 7), } impl Arbitrary for Vec { fn arbitrary(g: &mut Gen) -> Vec { let size = { let s = g.size(); g.gen_range(0..s) }; (0..size).map(|_| A::arbitrary(g)).collect() } fn shrink(&self) -> Box>> { VecShrinker::new(self.clone()) } } ///Iterator which returns successive attempts to shrink the vector `seed` struct VecShrinker { seed: Vec, /// How much which is removed when trying with smaller vectors size: usize, /// The end of the removed elements offset: usize, /// The shrinker for the element at `offset` once shrinking of individual /// elements are attempted element_shrinker: Box>, } impl VecShrinker { fn new(seed: Vec) -> Box>> { let es = match seed.get(0) { Some(e) => e.shrink(), None => return empty_shrinker(), }; let size = seed.len(); Box::new(VecShrinker { seed: seed, size: size, offset: size, element_shrinker: es, }) } /// Returns the next shrunk element if any, `offset` points to the index /// after the returned element after the function returns fn next_element(&mut self) -> Option { loop { match self.element_shrinker.next() { Some(e) => return Some(e), None => match self.seed.get(self.offset) { Some(e) => { self.element_shrinker = e.shrink(); self.offset += 1; } None => return None, }, } } } } impl Iterator for VecShrinker where A: Arbitrary, { type Item = Vec; fn next(&mut self) -> Option> { // Try with an empty vector first if self.size == self.seed.len() { self.size /= 2; self.offset = self.size; return Some(vec![]); } if self.size != 0 { // Generate a smaller vector by removing the elements between // (offset - size) and offset let xs1 = self.seed[..(self.offset - self.size)] .iter() .chain(&self.seed[self.offset..]) .cloned() .collect(); self.offset += self.size; // Try to reduce the amount removed from the vector once all // previous sizes tried if self.offset > self.seed.len() { self.size /= 2; self.offset = self.size; } Some(xs1) } else { // A smaller vector did not work so try to shrink each element of // the vector instead Reuse `offset` as the index determining which // element to shrink // The first element shrinker is already created so skip the first // offset (self.offset == 0 only on first entry to this part of the // iterator) if self.offset == 0 { self.offset = 1 } match self.next_element() { Some(e) => Some( self.seed[..self.offset - 1] .iter() .cloned() .chain(Some(e).into_iter()) .chain(self.seed[self.offset..].iter().cloned()) .collect(), ), None => None, } } } } impl Arbitrary for BTreeMap { fn arbitrary(g: &mut Gen) -> BTreeMap { let vec: Vec<(K, V)> = Arbitrary::arbitrary(g); vec.into_iter().collect() } fn shrink(&self) -> Box>> { let vec: Vec<(K, V)> = self.clone().into_iter().collect(); Box::new( vec.shrink().map(|v| v.into_iter().collect::>()), ) } } impl< K: Arbitrary + Eq + Hash, V: Arbitrary, S: BuildHasher + Default + Clone + 'static, > Arbitrary for HashMap { fn arbitrary(g: &mut Gen) -> Self { let vec: Vec<(K, V)> = Arbitrary::arbitrary(g); vec.into_iter().collect() } fn shrink(&self) -> Box> { let vec: Vec<(K, V)> = self.clone().into_iter().collect(); Box::new(vec.shrink().map(|v| v.into_iter().collect::())) } } impl Arbitrary for BTreeSet { fn arbitrary(g: &mut Gen) -> BTreeSet { let vec: Vec = Arbitrary::arbitrary(g); vec.into_iter().collect() } fn shrink(&self) -> Box>> { let vec: Vec = self.clone().into_iter().collect(); Box::new(vec.shrink().map(|v| v.into_iter().collect::>())) } } impl Arbitrary for BinaryHeap { fn arbitrary(g: &mut Gen) -> BinaryHeap { let vec: Vec = Arbitrary::arbitrary(g); vec.into_iter().collect() } fn shrink(&self) -> Box>> { let vec: Vec = self.clone().into_iter().collect(); Box::new( vec.shrink().map(|v| v.into_iter().collect::>()), ) } } impl Arbitrary for HashSet { fn arbitrary(g: &mut Gen) -> Self { let vec: Vec = Arbitrary::arbitrary(g); vec.into_iter().collect() } fn shrink(&self) -> Box> { let vec: Vec = self.clone().into_iter().collect(); Box::new(vec.shrink().map(|v| v.into_iter().collect::())) } } impl Arbitrary for LinkedList { fn arbitrary(g: &mut Gen) -> LinkedList { let vec: Vec = Arbitrary::arbitrary(g); vec.into_iter().collect() } fn shrink(&self) -> Box>> { let vec: Vec = self.clone().into_iter().collect(); Box::new( vec.shrink().map(|v| v.into_iter().collect::>()), ) } } impl Arbitrary for VecDeque { fn arbitrary(g: &mut Gen) -> VecDeque { let vec: Vec = Arbitrary::arbitrary(g); vec.into_iter().collect() } fn shrink(&self) -> Box>> { let vec: Vec = self.clone().into_iter().collect(); Box::new(vec.shrink().map(|v| v.into_iter().collect::>())) } } impl Arbitrary for IpAddr { fn arbitrary(g: &mut Gen) -> IpAddr { let ipv4: bool = g.gen(); if ipv4 { IpAddr::V4(Arbitrary::arbitrary(g)) } else { IpAddr::V6(Arbitrary::arbitrary(g)) } } } impl Arbitrary for Ipv4Addr { fn arbitrary(g: &mut Gen) -> Ipv4Addr { Ipv4Addr::new(g.gen(), g.gen(), g.gen(), g.gen()) } } impl Arbitrary for Ipv6Addr { fn arbitrary(g: &mut Gen) -> Ipv6Addr { Ipv6Addr::new( g.gen(), g.gen(), g.gen(), g.gen(), g.gen(), g.gen(), g.gen(), g.gen(), ) } } impl Arbitrary for SocketAddr { fn arbitrary(g: &mut Gen) -> SocketAddr { SocketAddr::new(Arbitrary::arbitrary(g), g.gen()) } } impl Arbitrary for SocketAddrV4 { fn arbitrary(g: &mut Gen) -> SocketAddrV4 { SocketAddrV4::new(Arbitrary::arbitrary(g), g.gen()) } } impl Arbitrary for SocketAddrV6 { fn arbitrary(g: &mut Gen) -> SocketAddrV6 { SocketAddrV6::new(Arbitrary::arbitrary(g), g.gen(), g.gen(), g.gen()) } } impl Arbitrary for PathBuf { fn arbitrary(g: &mut Gen) -> PathBuf { // use some real directories as guesses, so we may end up with // actual working directories in case that is relevant. let here = env::current_dir().unwrap_or(PathBuf::from("/test/directory")); let temp = env::temp_dir(); #[allow(deprecated)] let home = env::home_dir().unwrap_or(PathBuf::from("/home/user")); let mut p = g .choose(&[ here, temp, home, PathBuf::from("."), PathBuf::from(".."), PathBuf::from("../../.."), PathBuf::new(), ]) .unwrap() .to_owned(); p.extend(Vec::::arbitrary(g).iter()); p } fn shrink(&self) -> Box> { let mut shrunk = vec![]; let mut popped = self.clone(); if popped.pop() { shrunk.push(popped); } // Iterating over a Path performs a small amount of normalization. let normalized = self.iter().collect::(); if normalized.as_os_str() != self.as_os_str() { shrunk.push(normalized); } // Add the canonicalized variant only if canonicalizing the path // actually does something, making it (hopefully) smaller. Also, ignore // canonicalization if canonicalization errors. if let Ok(canonicalized) = self.canonicalize() { if canonicalized.as_os_str() != self.as_os_str() { shrunk.push(canonicalized); } } Box::new(shrunk.into_iter()) } } impl Arbitrary for OsString { fn arbitrary(g: &mut Gen) -> OsString { OsString::from(String::arbitrary(g)) } fn shrink(&self) -> Box> { let mystring: String = self.clone().into_string().unwrap(); Box::new(mystring.shrink().map(|s| OsString::from(s))) } } impl Arbitrary for String { fn arbitrary(g: &mut Gen) -> String { let size = { let s = g.size(); g.gen_range(0..s) }; (0..size).map(|_| char::arbitrary(g)).collect() } fn shrink(&self) -> Box> { // Shrink a string by shrinking a vector of its characters. let chars: Vec = self.chars().collect(); Box::new(chars.shrink().map(|x| x.into_iter().collect::())) } } impl Arbitrary for CString { fn arbitrary(g: &mut Gen) -> Self { let size = { let s = g.size(); g.gen_range(0..s) }; // Use either random bytes or random UTF-8 encoded codepoints. let utf8: bool = g.gen(); if utf8 { CString::new( (0..) .map(|_| char::arbitrary(g)) .filter(|&c| c != '\0') .take(size) .collect::(), ) } else { CString::new( (0..) .map(|_| u8::arbitrary(g)) .filter(|&c| c != b'\0') .take(size) .collect::>(), ) } .expect("null characters should have been filtered out") } fn shrink(&self) -> Box> { // Use the implementation for a vec here, but make sure null characters // are filtered out. Box::new(VecShrinker::new(self.as_bytes().to_vec()).map(|bytes| { CString::new( bytes.into_iter().filter(|&c| c != 0).collect::>(), ) .expect("null characters should have been filtered out") })) } } impl Arbitrary for char { fn arbitrary(g: &mut Gen) -> char { let mode = g.gen_range(0..100); match mode { 0..=49 => { // ASCII + some control characters g.gen_range(0..0xB0) as u8 as char } 50..=59 => { // Unicode BMP characters loop { if let Some(x) = char::from_u32(g.gen_range(0..0x10000)) { return x; } // ignore surrogate pairs } } 60..=84 => { // Characters often used in programming languages g.choose(&[ ' ', ' ', ' ', '\t', '\n', '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '-', '=', '+', '[', ']', '{', '}', ':', ';', '\'', '"', '\\', '|', ',', '<', '>', '.', '/', '?', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ]) .unwrap() .to_owned() } 85..=89 => { // Tricky Unicode, part 1 g.choose(&[ '\u{0149}', // a deprecated character '\u{fff0}', // some of "Other, format" category: '\u{fff1}', '\u{fff2}', '\u{fff3}', '\u{fff4}', '\u{fff5}', '\u{fff6}', '\u{fff7}', '\u{fff8}', '\u{fff9}', '\u{fffA}', '\u{fffB}', '\u{fffC}', '\u{fffD}', '\u{fffE}', '\u{fffF}', '\u{0600}', '\u{0601}', '\u{0602}', '\u{0603}', '\u{0604}', '\u{0605}', '\u{061C}', '\u{06DD}', '\u{070F}', '\u{180E}', '\u{110BD}', '\u{1D173}', '\u{e0001}', // tag '\u{e0020}', // tag space '\u{e000}', '\u{e001}', '\u{ef8ff}', // private use '\u{f0000}', '\u{ffffd}', '\u{ffffe}', '\u{fffff}', '\u{100000}', '\u{10FFFD}', '\u{10FFFE}', '\u{10FFFF}', // "Other, surrogate" characters are so that very special // that they are not even allowed in safe Rust, //so omitted here '\u{3000}', // ideographic space '\u{1680}', // other space characters are already covered by two next // branches ]) .unwrap() .to_owned() } 90..=94 => { // Tricky unicode, part 2 char::from_u32(g.gen_range(0x2000..0x2070)).unwrap() } 95..=99 => { // Completely arbitrary characters g.gen() } _ => unreachable!(), } } fn shrink(&self) -> Box> { Box::new((*self as u32).shrink().filter_map(char::from_u32)) } } macro_rules! unsigned_shrinker { ($ty:ty) => { mod shrinker { pub struct UnsignedShrinker { x: $ty, i: $ty, } impl UnsignedShrinker { pub fn new(x: $ty) -> Box> { if x == 0 { super::empty_shrinker() } else { Box::new( vec![0] .into_iter() .chain(UnsignedShrinker { x: x, i: x / 2 }), ) } } } impl Iterator for UnsignedShrinker { type Item = $ty; fn next(&mut self) -> Option<$ty> { if self.x - self.i < self.x { let result = Some(self.x - self.i); self.i = self.i / 2; result } else { None } } } } }; } macro_rules! unsigned_problem_values { ($t:ty) => { &[<$t>::min_value(), 1, <$t>::max_value()] }; } macro_rules! unsigned_arbitrary { ($($ty:tt),*) => { $( impl Arbitrary for $ty { fn arbitrary(g: &mut Gen) -> $ty { match g.gen_range(0..10) { 0 => { *g.choose(unsigned_problem_values!($ty)).unwrap() }, _ => g.gen() } } fn shrink(&self) -> Box> { unsigned_shrinker!($ty); shrinker::UnsignedShrinker::new(*self) } } )* } } unsigned_arbitrary! { usize, u8, u16, u32, u64, u128 } macro_rules! signed_shrinker { ($ty:ty) => { mod shrinker { pub struct SignedShrinker { x: $ty, i: $ty, } impl SignedShrinker { pub fn new(x: $ty) -> Box> { if x == 0 { super::empty_shrinker() } else { let shrinker = SignedShrinker { x: x, i: x / 2 }; let mut items = vec![0]; if shrinker.i < 0 && shrinker.x != <$ty>::MIN { items.push(shrinker.x.abs()); } Box::new(items.into_iter().chain(shrinker)) } } } impl Iterator for SignedShrinker { type Item = $ty; fn next(&mut self) -> Option<$ty> { if self.x == <$ty>::MIN || (self.x - self.i).abs() < self.x.abs() { let result = Some(self.x - self.i); self.i = self.i / 2; result } else { None } } } } }; } macro_rules! signed_problem_values { ($t:ty) => { &[<$t>::min_value(), 0, <$t>::max_value()] }; } macro_rules! signed_arbitrary { ($($ty:tt),*) => { $( impl Arbitrary for $ty { fn arbitrary(g: &mut Gen) -> $ty { match g.gen_range(0..10) { 0 => { *g.choose(signed_problem_values!($ty)).unwrap() }, _ => g.gen() } } fn shrink(&self) -> Box> { signed_shrinker!($ty); shrinker::SignedShrinker::new(*self) } } )* } } signed_arbitrary! { isize, i8, i16, i32, i64, i128 } macro_rules! float_problem_values { ($path:path) => {{ // hack. see: https://github.com/rust-lang/rust/issues/48067 use $path as p; &[p::NAN, p::NEG_INFINITY, p::MIN, -0., 0., p::MAX, p::INFINITY] }}; } macro_rules! float_arbitrary { ($($t:ty, $path:path, $shrinkable:ty),+) => {$( impl Arbitrary for $t { fn arbitrary(g: &mut Gen) -> $t { match g.gen_range(0..10) { 0 => *g.choose(float_problem_values!($path)).unwrap(), _ => { use $path as p; let exp = g.gen_range((0.)..p::MAX_EXP as i16 as $t); let mantissa = g.gen_range((1.)..2.); let sign = *g.choose(&[-1., 1.]).unwrap(); sign * mantissa * exp.exp2() } } } fn shrink(&self) -> Box> { signed_shrinker!($shrinkable); let it = shrinker::SignedShrinker::new(*self as $shrinkable); Box::new(it.map(|x| x as $t)) } } )*}; } float_arbitrary!(f32, std::f32, i32, f64, std::f64, i64); macro_rules! unsigned_non_zero_shrinker { ($ty:tt) => { mod shrinker { pub struct UnsignedNonZeroShrinker { x: $ty, i: $ty, } impl UnsignedNonZeroShrinker { pub fn new(x: $ty) -> Box> { debug_assert!(x > 0); if x == 1 { super::empty_shrinker() } else { Box::new( std::iter::once(1).chain( UnsignedNonZeroShrinker { x: x, i: x / 2 }, ), ) } } } impl Iterator for UnsignedNonZeroShrinker { type Item = $ty; fn next(&mut self) -> Option<$ty> { if self.x - self.i < self.x { let result = Some(self.x - self.i); self.i = self.i / 2; result } else { None } } } } }; } macro_rules! unsigned_non_zero_arbitrary { ($($ty:tt => $inner:tt),*) => { $( impl Arbitrary for $ty { fn arbitrary(g: &mut Gen) -> $ty { let mut v: $inner = g.gen(); if v == 0 { v += 1; } $ty::new(v).expect("non-zero value contsturction failed") } fn shrink(&self) -> Box> { unsigned_non_zero_shrinker!($inner); Box::new(shrinker::UnsignedNonZeroShrinker::new(self.get()) .map($ty::new) .map(Option::unwrap)) } } )* } } unsigned_non_zero_arbitrary! { NonZeroUsize => usize, NonZeroU8 => u8, NonZeroU16 => u16, NonZeroU32 => u32, NonZeroU64 => u64, NonZeroU128 => u128 } impl Arbitrary for Wrapping { fn arbitrary(g: &mut Gen) -> Wrapping { Wrapping(T::arbitrary(g)) } fn shrink(&self) -> Box>> { Box::new(self.0.shrink().map(|inner| Wrapping(inner))) } } impl Arbitrary for Bound { fn arbitrary(g: &mut Gen) -> Bound { match g.gen_range(0..3) { 0 => Bound::Included(T::arbitrary(g)), 1 => Bound::Excluded(T::arbitrary(g)), _ => Bound::Unbounded, } } fn shrink(&self) -> Box>> { match *self { Bound::Included(ref x) => { Box::new(x.shrink().map(Bound::Included)) } Bound::Excluded(ref x) => { Box::new(x.shrink().map(Bound::Excluded)) } Bound::Unbounded => empty_shrinker(), } } } impl Arbitrary for Range { fn arbitrary(g: &mut Gen) -> Range { Arbitrary::arbitrary(g)..Arbitrary::arbitrary(g) } fn shrink(&self) -> Box>> { Box::new( (self.start.clone(), self.end.clone()).shrink().map(|(s, e)| s..e), ) } } impl Arbitrary for RangeInclusive { fn arbitrary(g: &mut Gen) -> RangeInclusive { Arbitrary::arbitrary(g)..=Arbitrary::arbitrary(g) } fn shrink(&self) -> Box>> { Box::new( (self.start().clone(), self.end().clone()) .shrink() .map(|(s, e)| s..=e), ) } } impl Arbitrary for RangeFrom { fn arbitrary(g: &mut Gen) -> RangeFrom { Arbitrary::arbitrary(g).. } fn shrink(&self) -> Box>> { Box::new(self.start.clone().shrink().map(|start| start..)) } } impl Arbitrary for RangeTo { fn arbitrary(g: &mut Gen) -> RangeTo { ..Arbitrary::arbitrary(g) } fn shrink(&self) -> Box>> { Box::new(self.end.clone().shrink().map(|end| ..end)) } } impl Arbitrary for RangeToInclusive { fn arbitrary(g: &mut Gen) -> RangeToInclusive { ..=Arbitrary::arbitrary(g) } fn shrink(&self) -> Box>> { Box::new(self.end.clone().shrink().map(|end| ..=end)) } } impl Arbitrary for RangeFull { fn arbitrary(_: &mut Gen) -> RangeFull { .. } } impl Arbitrary for Duration { fn arbitrary(gen: &mut Gen) -> Self { let seconds = gen.gen_range(0..gen.size() as u64); let nanoseconds = gen.gen_range(0..1_000_000); Duration::new(seconds, nanoseconds) } fn shrink(&self) -> Box> { Box::new( (self.as_secs(), self.subsec_nanos()) .shrink() .map(|(secs, nanos)| Duration::new(secs, nanos % 1_000_000)), ) } } impl Arbitrary for Box { fn arbitrary(g: &mut Gen) -> Box { Box::new(A::arbitrary(g)) } fn shrink(&self) -> Box>> { Box::new((**self).shrink().map(Box::new)) } } impl Arbitrary for Arc { fn arbitrary(g: &mut Gen) -> Arc { Arc::new(A::arbitrary(g)) } fn shrink(&self) -> Box>> { Box::new((**self).shrink().map(Arc::new)) } } impl Arbitrary for SystemTime { fn arbitrary(gen: &mut Gen) -> Self { let after_epoch = bool::arbitrary(gen); let duration = Duration::arbitrary(gen); if after_epoch { UNIX_EPOCH + duration } else { UNIX_EPOCH - duration } } fn shrink(&self) -> Box> { let duration = match self.duration_since(UNIX_EPOCH) { Ok(duration) => duration, Err(e) => e.duration(), }; Box::new( duration .shrink() .flat_map(|d| vec![UNIX_EPOCH + d, UNIX_EPOCH - d]), ) } } #[cfg(test)] mod test { use std::collections::{ BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque, }; use std::fmt::Debug; use std::hash::Hash; use std::num::Wrapping; use std::path::PathBuf; use super::{Arbitrary, Gen}; #[test] fn arby_unit() { assert_eq!(arby::<()>(), ()); } macro_rules! arby_int { ( $signed:expr, $($t:ty),+) => {$( let mut arbys = (0..1_000_000).map(|_| arby::<$t>()); let mut problems = if $signed { signed_problem_values!($t).iter() } else { unsigned_problem_values!($t).iter() }; assert!(problems.all(|p| arbys.any(|arby| arby == *p)), "Arbitrary does not generate all problematic values"); let max = <$t>::max_value(); let mid = (max + <$t>::min_value()) / 2; // split full range of $t into chunks // Arbitrary must return some value in each chunk let double_chunks: $t = 9; let chunks = double_chunks * 2; // chunks must be even let lim: Box> = if $signed { Box::new((0..=chunks) .map(|idx| idx - chunks / 2) .map(|x| mid + max / (chunks / 2) * x)) } else { Box::new((0..=chunks).map(|idx| max / chunks * idx)) }; let mut lim = lim.peekable(); while let (Some(low), Some(&high)) = (lim.next(), lim.peek()) { assert!(arbys.any(|arby| low <= arby && arby <= high), "Arbitrary doesn't generate numbers in {}..={}", low, high) } )*}; } #[test] fn arby_int() { arby_int!(true, i8, i16, i32, i64, isize, i128); } #[test] fn arby_uint() { arby_int!(false, u8, u16, u32, u64, usize, u128); } macro_rules! arby_float { ($($t:ty, $path:path),+) => {$({ use $path as p; let mut arbys = (0..1_000_000).map(|_| arby::<$t>()); //NaN != NaN assert!(arbys.any(|f| f.is_nan()), "Arbitrary does not generate the problematic value NaN" ); for p in float_problem_values!($path).iter().filter(|f| !f.is_nan()) { assert!(arbys.any(|arby| arby == *p), "Arbitrary does not generate the problematic value {}", p ); } // split full range of $t into chunks // Arbitrary must return some value in each chunk let double_chunks: i8 = 9; let chunks = double_chunks * 2; // chunks must be even let lim = (-double_chunks..=double_chunks) .map(|idx| <$t>::from(idx)) .map(|idx| p::MAX/(<$t>::from(chunks/2)) * idx); let mut lim = lim.peekable(); while let (Some(low), Some(&high)) = (lim.next(), lim.peek()) { assert!( arbys.any(|arby| low <= arby && arby <= high), "Arbitrary doesn't generate numbers in {:e}..={:e}", low, high, ) } })*}; } #[test] fn arby_float() { arby_float!(f32, std::f32, f64, std::f64); } fn arby() -> A { Arbitrary::arbitrary(&mut Gen::new(5)) } // Shrink testing. #[test] fn unit() { eq((), vec![]); } #[test] fn bools() { eq(false, vec![]); eq(true, vec![false]); } #[test] fn options() { eq(None::<()>, vec![]); eq(Some(false), vec![None]); eq(Some(true), vec![None, Some(false)]); } #[test] fn results() { // Result doesn't implement the Hash trait, so these tests // depends on the order of shrunk results. Ug. // TODO: Fix this. ordered_eq(Ok::(true), vec![Ok(false)]); ordered_eq(Err::<(), bool>(true), vec![Err(false)]); } #[test] fn tuples() { eq((false, false), vec![]); eq((true, false), vec![(false, false)]); eq((true, true), vec![(false, true), (true, false)]); } #[test] fn triples() { eq((false, false, false), vec![]); eq((true, false, false), vec![(false, false, false)]); eq( (true, true, false), vec![(false, true, false), (true, false, false)], ); } #[test] fn quads() { eq((false, false, false, false), vec![]); eq((true, false, false, false), vec![(false, false, false, false)]); eq( (true, true, false, false), vec![(false, true, false, false), (true, false, false, false)], ); } #[test] fn ints() { // TODO: Test overflow? eq(5isize, vec![0, 3, 4]); eq(-5isize, vec![5, 0, -3, -4]); eq(0isize, vec![]); } #[test] fn ints8() { eq(5i8, vec![0, 3, 4]); eq(-5i8, vec![5, 0, -3, -4]); eq(0i8, vec![]); } #[test] fn ints16() { eq(5i16, vec![0, 3, 4]); eq(-5i16, vec![5, 0, -3, -4]); eq(0i16, vec![]); } #[test] fn ints32() { eq(5i32, vec![0, 3, 4]); eq(-5i32, vec![5, 0, -3, -4]); eq(0i32, vec![]); } #[test] fn ints64() { eq(5i64, vec![0, 3, 4]); eq(-5i64, vec![5, 0, -3, -4]); eq(0i64, vec![]); } #[test] fn ints128() { eq(5i128, vec![0, 3, 4]); eq(-5i128, vec![5, 0, -3, -4]); eq(0i128, vec![]); } #[test] fn uints() { eq(5usize, vec![0, 3, 4]); eq(0usize, vec![]); } #[test] fn uints8() { eq(5u8, vec![0, 3, 4]); eq(0u8, vec![]); } #[test] fn uints16() { eq(5u16, vec![0, 3, 4]); eq(0u16, vec![]); } #[test] fn uints32() { eq(5u32, vec![0, 3, 4]); eq(0u32, vec![]); } #[test] fn uints64() { eq(5u64, vec![0, 3, 4]); eq(0u64, vec![]); } #[test] fn uints128() { eq(5u128, vec![0, 3, 4]); eq(0u128, vec![]); } macro_rules! define_float_eq { ($ty:ty) => { fn eq(s: $ty, v: Vec<$ty>) { let shrunk: Vec<$ty> = s.shrink().collect(); for n in v { let found = shrunk.iter().any(|&i| i == n); if !found { panic!(format!( "Element {:?} was not found \ in shrink results {:?}", n, shrunk )); } } } }; } #[test] fn floats32() { define_float_eq!(f32); eq(0.0, vec![]); eq(-0.0, vec![]); eq(1.0, vec![0.0]); eq(2.0, vec![0.0, 1.0]); eq(-2.0, vec![0.0, 2.0, -1.0]); eq(1.5, vec![0.0]); } #[test] fn floats64() { define_float_eq!(f64); eq(0.0, vec![]); eq(-0.0, vec![]); eq(1.0, vec![0.0]); eq(2.0, vec![0.0, 1.0]); eq(-2.0, vec![0.0, 2.0, -1.0]); eq(1.5, vec![0.0]); } #[test] fn wrapping_ints32() { eq(Wrapping(5i32), vec![Wrapping(0), Wrapping(3), Wrapping(4)]); eq( Wrapping(-5i32), vec![Wrapping(5), Wrapping(0), Wrapping(-3), Wrapping(-4)], ); eq(Wrapping(0i32), vec![]); } #[test] fn vecs() { eq( { let it: Vec = vec![]; it }, vec![], ); eq( { let it: Vec> = vec![vec![]]; it }, vec![vec![]], ); eq(vec![1isize], vec![vec![], vec![0]]); eq(vec![11isize], vec![vec![], vec![0], vec![6], vec![9], vec![10]]); eq( vec![3isize, 5], vec![ vec![], vec![5], vec![3], vec![0, 5], vec![2, 5], vec![3, 0], vec![3, 3], vec![3, 4], ], ); } macro_rules! map_tests { ($name:ident, $ctor:expr) => { #[test] fn $name() { ordered_eq($ctor, vec![]); { let mut map = $ctor; map.insert(1usize, 1isize); let shrinks = vec![ $ctor, { let mut m = $ctor; m.insert(0, 1); m }, { let mut m = $ctor; m.insert(1, 0); m }, ]; ordered_eq(map, shrinks); } } }; } map_tests!(btreemap, BTreeMap::::new()); map_tests!(hashmap, HashMap::::new()); macro_rules! list_tests { ($name:ident, $ctor:expr, $push:ident) => { #[test] fn $name() { ordered_eq($ctor, vec![]); { let mut list = $ctor; list.$push(2usize); let shrinks = vec![ $ctor, { let mut m = $ctor; m.$push(0); m }, { let mut m = $ctor; m.$push(1); m }, ]; ordered_eq(list, shrinks); } } }; } list_tests!(btreesets, BTreeSet::::new(), insert); list_tests!(hashsets, HashSet::::new(), insert); list_tests!(linkedlists, LinkedList::::new(), push_back); list_tests!(vecdeques, VecDeque::::new(), push_back); #[test] fn binaryheaps() { ordered_eq( BinaryHeap::::new().into_iter().collect::>(), vec![], ); { let mut heap = BinaryHeap::::new(); heap.push(2usize); let shrinks = vec![vec![], vec![0], vec![1]]; ordered_eq(heap.into_iter().collect::>(), shrinks); } } #[test] fn chars() { eq('\x00', vec![]); } // All this jazz is for testing set equality on the results of a shrinker. fn eq(s: A, v: Vec) { let (left, right) = (shrunk(s), set(v)); assert_eq!(left, right); } fn shrunk(s: A) -> HashSet { set(s.shrink()) } fn set>(xs: I) -> HashSet { xs.into_iter().collect() } fn ordered_eq(s: A, v: Vec) { let (left, right) = (s.shrink().collect::>(), v); assert_eq!(left, right); } #[test] fn bounds() { use std::ops::Bound::*; for i in -5..=5 { ordered_eq(Included(i), i.shrink().map(Included).collect()); ordered_eq(Excluded(i), i.shrink().map(Excluded).collect()); } eq(Unbounded::, vec![]); } #[test] fn ranges() { ordered_eq(0..0, vec![]); ordered_eq(1..1, vec![0..1, 1..0]); ordered_eq(3..5, vec![0..5, 2..5, 3..0, 3..3, 3..4]); ordered_eq(5..3, vec![0..3, 3..3, 4..3, 5..0, 5..2]); ordered_eq(3.., vec![0.., 2..]); ordered_eq(..3, vec![..0, ..2]); ordered_eq(.., vec![]); ordered_eq(3..=5, vec![0..=5, 2..=5, 3..=0, 3..=3, 3..=4]); ordered_eq(..=3, vec![..=0, ..=2]); } #[test] fn pathbuf() { ordered_eq( PathBuf::from("/home/foo//.././bar"), vec![ PathBuf::from("/home/foo//.."), PathBuf::from("/home/foo/../bar"), ], ); } }