| // Copyright © 2019 The Rust Fuzz Project Developers. |
| // |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| // option. This file may not be copied, modified, or distributed |
| // except according to those terms. |
| |
| //! The `Arbitrary` trait crate. |
| //! |
| //! This trait provides an [`Arbitrary`](./trait.Arbitrary.html) trait to |
| //! produce well-typed, structured values, from raw, byte buffers. It is |
| //! generally intended to be used with fuzzers like AFL or libFuzzer. See the |
| //! [`Arbitrary`](./trait.Arbitrary.html) trait's documentation for details on |
| //! automatically deriving, implementing, and/or using the trait. |
| |
| #![deny(bad_style)] |
| #![deny(missing_docs)] |
| #![deny(future_incompatible)] |
| #![deny(nonstandard_style)] |
| #![deny(rust_2018_compatibility)] |
| #![deny(rust_2018_idioms)] |
| #![deny(unused)] |
| |
| #[cfg(feature = "derive_arbitrary")] |
| pub use derive_arbitrary::*; |
| |
| mod error; |
| pub use error::*; |
| |
| pub mod unstructured; |
| #[doc(inline)] |
| pub use unstructured::Unstructured; |
| |
| pub mod size_hint; |
| |
| use std::borrow::{Cow, ToOwned}; |
| use std::cell::{Cell, RefCell, UnsafeCell}; |
| use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; |
| use std::ffi::{CString, OsString}; |
| use std::iter; |
| use std::mem; |
| use std::path::PathBuf; |
| use std::rc::Rc; |
| use std::str; |
| use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering}; |
| use std::sync::{Arc, Mutex}; |
| use std::time::Duration; |
| |
| fn empty<T: 'static>() -> Box<dyn Iterator<Item = T>> { |
| Box::new(iter::empty()) |
| } |
| |
| fn once<T: 'static>(val: T) -> Box<dyn Iterator<Item = T>> { |
| Box::new(iter::once(val)) |
| } |
| |
| /// Generate arbitrary structured values from raw, unstructured data. |
| /// |
| /// The `Arbitrary` trait allows you to generate valid structured values, like |
| /// `HashMap`s, or ASTs, or `MyTomlConfig`, or any other data structure from |
| /// raw, unstructured bytes provided by a fuzzer. It also features built-in |
| /// shrinking, so that if you find a test case that triggers a bug, you can find |
| /// the smallest, most easiest-to-understand test case that still triggers that |
| /// bug. |
| /// |
| /// # Deriving `Arbitrary` |
| /// |
| /// Automatically deriving the `Arbitrary` trait is the recommended way to |
| /// implement `Arbitrary` for your types. |
| /// |
| /// Using the custom derive requires that you enable the `"derive"` cargo |
| /// feature in your `Cargo.toml`: |
| /// |
| /// ```toml |
| /// [dependencies] |
| /// arbitrary = { version = "0.2.0", features = ["derive"] } |
| /// ``` |
| /// |
| /// Then, you add the `#[derive(Arbitrary)]` annotation to your `struct` or |
| /// `enum` type definition: |
| /// |
| /// ``` |
| /// # #[cfg(feature = "derive")] mod foo { |
| /// use arbitrary::Arbitrary; |
| /// use std::collections::HashSet; |
| /// |
| /// #[derive(Arbitrary)] |
| /// pub struct AddressBook { |
| /// friends: HashSet<Friend>, |
| /// } |
| /// |
| /// #[derive(Arbitrary, Hash, Eq, PartialEq)] |
| /// pub enum Friend { |
| /// Buddy { name: String }, |
| /// Pal { age: usize }, |
| /// } |
| /// # } |
| /// ``` |
| /// |
| /// Every member of the `struct` or `enum` must also implement `Arbitrary`. |
| /// |
| /// # Implementing `Arbitrary` By Hand |
| /// |
| /// Implementing `Arbitrary` mostly involves nested calls to other `Arbitrary` |
| /// arbitrary implementations for each of your `struct` or `enum`'s members. But |
| /// sometimes you need some amount of raw data, or you need to generate a |
| /// variably-sized collection type, or you something of that sort. The |
| /// [`Unstructured`][crate::Unstructured] type helps you with these tasks. |
| /// |
| /// ``` |
| /// # #[cfg(feature = "derive")] mod foo { |
| /// # pub struct MyCollection<T> { _t: std::marker::PhantomData<T> } |
| /// # impl<T> MyCollection<T> { |
| /// # pub fn with_capacity(capacity: usize) -> Self { MyCollection { _t: std::marker::PhantomData } } |
| /// # pub fn insert(&mut self, element: T) {} |
| /// # } |
| /// use arbitrary::{Arbitrary, Result, Unstructured}; |
| /// |
| /// impl<T> Arbitrary for MyCollection<T> |
| /// where |
| /// T: Arbitrary, |
| /// { |
| /// fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| /// // Get the number of `T`s we should insert into our collection. |
| /// let len = u.arbitrary_len::<T>()?; |
| /// |
| /// // And then create a collection of that length! |
| /// let mut my_collection = MyCollection::with_capacity(len); |
| /// for _ in 0..len { |
| /// let element = T::arbitrary(u)?; |
| /// my_collection.insert(element); |
| /// } |
| /// |
| /// Ok(my_collection) |
| /// } |
| /// } |
| /// # } |
| /// ``` |
| pub trait Arbitrary: Sized + 'static { |
| /// Generate an arbitrary value of `Self` from the given unstructured data. |
| /// |
| /// Calling `Arbitrary::arbitrary` requires that you have some raw data, |
| /// perhaps given to you by a fuzzer like AFL or libFuzzer. You wrap this |
| /// raw data in an `Unstructured`, and then you can call `<MyType as |
| /// Arbitrary>::arbitrary` to construct an arbitrary instance of `MyType` |
| /// from that unstuctured data. |
| /// |
| /// Implementation may return an error if there is not enough data to |
| /// construct a full instance of `Self`. This is generally OK: it is better |
| /// to exit early and get the fuzzer to provide more input data, than it is |
| /// to generate default values in place of the missing data, which would |
| /// bias the distribution of generated values, and ultimately make fuzzing |
| /// less efficient. |
| /// |
| /// ``` |
| /// # #[cfg(feature = "derive")] fn foo() { |
| /// use arbitrary::{Arbitrary, Unstructured}; |
| /// |
| /// #[derive(Arbitrary)] |
| /// pub struct MyType { |
| /// // ... |
| /// } |
| /// |
| /// // Get the raw data from the fuzzer or wherever else. |
| /// # let get_raw_data_from_fuzzer = || &[]; |
| /// let raw_data: &[u8] = get_raw_data_from_fuzzer(); |
| /// |
| /// // Wrap that raw data in an `Unstructured`. |
| /// let mut unstructured = Unstructured::new(raw_data); |
| /// |
| /// // Generate an arbitrary instance of `MyType` and do stuff with it. |
| /// if let Ok(value) = MyType::arbitrary(&mut unstructured) { |
| /// # let do_stuff = |_| {}; |
| /// do_stuff(value); |
| /// } |
| /// # } |
| /// ``` |
| /// |
| /// See also the documentation for [`Unstructured`][crate::Unstructured]. |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self>; |
| |
| /// Generate an arbitrary value of `Self` from the entirety of the given unstructured data. |
| /// |
| /// This is similar to Arbitrary::arbitrary, however it assumes that it is the |
| /// last consumer of the given data, and is thus able to consume it all if it needs. |
| /// See also the documentation for [`Unstructured`][crate::Unstructured]. |
| fn arbitrary_take_rest(mut u: Unstructured<'_>) -> Result<Self> { |
| Self::arbitrary(&mut u) |
| } |
| |
| /// Get a size hint for how many bytes out of an `Unstructured` this type |
| /// needs to construct itself. |
| /// |
| /// This is useful for determining how many elements we should insert when |
| /// creating an arbitrary collection. |
| /// |
| /// The return value is similar to |
| /// [`Iterator::size_hint`][iterator-size-hint]: it returns a tuple where |
| /// the first element is a lower bound on the number of bytes required, and |
| /// the second element is an optional upper bound. |
| /// |
| /// The default implementation return `(0, None)` which is correct for any |
| /// type, but not ultimately that useful. Using `#[derive(Arbitrary)]` will |
| /// create a better implementation. If you are writing an `Arbitrary` |
| /// implementation by hand, and your type can be part of a dynamically sized |
| /// collection (such as `Vec`), you are strongly encouraged to override this |
| /// default with a better implementation. The |
| /// [`size_hint`][crate::size_hint] module will help with this task. |
| /// |
| /// ## The `depth` Parameter |
| /// |
| /// If you 100% know that the type you are implementing `Arbitrary` for is |
| /// not a recursive type, or your implementation is not transitively calling |
| /// any other `size_hint` methods, you can ignore the `depth` parameter. |
| /// Note that if you are implementing `Arbitrary` for a generic type, you |
| /// cannot guarantee the lack of type recrusion! |
| /// |
| /// Otherwise, you need to use |
| /// [`arbitrary::size_hint::recursion_guard(depth)`][crate::size_hint::recursion_guard] |
| /// to prevent potential infinite recursion when calculating size hints for |
| /// potentially recursive types: |
| /// |
| /// ``` |
| /// use arbitrary::{Arbitrary, Unstructured, size_hint}; |
| /// |
| /// // This can potentially be a recursive type if `L` or `R` contain |
| /// // something like `Box<Option<MyEither<L, R>>>`! |
| /// enum MyEither<L, R> { |
| /// Left(L), |
| /// Right(R), |
| /// } |
| /// |
| /// impl<L, R> Arbitrary for MyEither<L, R> |
| /// where |
| /// L: Arbitrary, |
| /// R: Arbitrary, |
| /// { |
| /// fn arbitrary(u: &mut Unstructured) -> arbitrary::Result<Self> { |
| /// // ... |
| /// # unimplemented!() |
| /// } |
| /// |
| /// fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| /// // Protect against potential infinite recursion with |
| /// // `recursion_guard`. |
| /// size_hint::recursion_guard(depth, |depth| { |
| /// // If we aren't too deep, then `recursion_guard` calls |
| /// // this closure, which implements the natural size hint. |
| /// // Don't forget to use the new `depth` in all nested |
| /// // `size_hint` calls! We recommend shadowing the |
| /// // parameter, like what is done here, so that you can't |
| /// // accidentally use the wrong depth. |
| /// size_hint::or( |
| /// <L as Arbitrary>::size_hint(depth), |
| /// <R as Arbitrary>::size_hint(depth), |
| /// ) |
| /// }) |
| /// } |
| /// } |
| /// ``` |
| /// |
| /// [iterator-size-hint]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.size_hint |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| let _ = depth; |
| (0, None) |
| } |
| |
| /// Generate an iterator of derived values which are "smaller" than the |
| /// original `self` instance. |
| /// |
| /// You can use this to help find the smallest test case that reproduces a |
| /// bug. |
| /// |
| /// Using `#[derive(Arbitrary)]` will automatically implement shrinking for |
| /// your type. |
| /// |
| /// However, if you are implementing `Arbirary` by hand and you want support |
| /// for shrinking your type, you must override the default provided |
| /// implementation of `shrink`, which just returns an empty iterator. You |
| /// should try pretty hard to have your `shrink` implementation return a |
| /// *lazy* iterator: one that computes the next value as it is needed, |
| /// rather than computing them up front when `shrink` is first called. |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| empty() |
| } |
| } |
| |
| impl Arbitrary for () { |
| fn arbitrary(_: &mut Unstructured<'_>) -> Result<Self> { |
| Ok(()) |
| } |
| |
| #[inline] |
| fn size_hint(_depth: usize) -> (usize, Option<usize>) { |
| (0, Some(0)) |
| } |
| } |
| |
| impl Arbitrary for bool { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Ok(<u8 as Arbitrary>::arbitrary(u)? & 1 == 1) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <u8 as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| Box::new(if *self { once(false) } else { empty() }) |
| } |
| } |
| |
| macro_rules! impl_arbitrary_for_integers { |
| ( $( $ty:ty: $unsigned:ty; )* ) => { |
| $( |
| impl Arbitrary for $ty { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| let mut buf = [0; mem::size_of::<$ty>()]; |
| u.fill_buffer(&mut buf)?; |
| let mut x: $unsigned = 0; |
| for i in 0..mem::size_of::<$ty>() { |
| x |= buf[i] as $unsigned << (i * 8); |
| } |
| Ok(x as $ty) |
| } |
| |
| #[inline] |
| fn size_hint(_depth: usize) -> (usize, Option<usize>) { |
| let n = mem::size_of::<$ty>(); |
| (n, Some(n)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let mut x = *self; |
| if x == 0 { |
| return empty(); |
| } |
| Box::new(iter::once(0).chain(std::iter::from_fn(move || { |
| x = x / 2; |
| if x == 0 { |
| None |
| } else { |
| Some(x) |
| } |
| }))) |
| } |
| } |
| )* |
| } |
| } |
| |
| impl_arbitrary_for_integers! { |
| u8: u8; |
| u16: u16; |
| u32: u32; |
| u64: u64; |
| u128: u128; |
| usize: usize; |
| i8: u8; |
| i16: u16; |
| i32: u32; |
| i64: u64; |
| i128: u128; |
| isize: usize; |
| } |
| |
| macro_rules! impl_arbitrary_for_floats { |
| ( $( $ty:ident : $unsigned:ty; )* ) => { |
| $( |
| impl Arbitrary for $ty { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Ok(Self::from_bits(<$unsigned as Arbitrary>::arbitrary(u)?)) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <$unsigned as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| if *self == 0.0 { |
| empty() |
| } else if !self.is_finite() { |
| once(0.0) |
| } else { |
| let mut x = *self; |
| Box::new(iter::once(0.0).chain(iter::from_fn(move || { |
| // NB: do not test for zero like we do for integers |
| // because dividing by two until we reach a fixed |
| // point is NOT guaranteed to end at zero in |
| // non-default rounding modes of IEEE-754! |
| // |
| // For example, with 64-bit floats and the |
| // round-to-positive-infinity mode: |
| // |
| // 5e-324 / 2.0 == 5e-324 |
| // |
| // (5e-234 is the smallest postive number that can |
| // be precisely represented in a 64-bit float.) |
| let y = x; |
| x = x / 2.0; |
| if x == y { |
| None |
| } else { |
| Some(x) |
| } |
| }))) |
| } |
| } |
| } |
| )* |
| } |
| } |
| |
| impl_arbitrary_for_floats! { |
| f32: u32; |
| f64: u64; |
| } |
| |
| impl Arbitrary for char { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| use std::char; |
| const CHAR_END: u32 = 0x0011_000; |
| // The size of the surrogate blocks |
| const SURROGATES_START: u32 = 0xD800; |
| let mut c = <u32 as Arbitrary>::arbitrary(u)? % CHAR_END; |
| if let Some(c) = char::from_u32(c) { |
| return Ok(c); |
| } else { |
| // We found a surrogate, wrap and try again |
| c -= SURROGATES_START; |
| Ok(char::from_u32(c) |
| .expect("Generated character should be valid! This is a bug in arbitrary-rs")) |
| } |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <u32 as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let x = *self as u32; |
| Box::new(x.shrink().filter_map(|x| { |
| use std::convert::TryFrom; |
| char::try_from(x).ok() |
| })) |
| } |
| } |
| |
| impl Arbitrary for AtomicBool { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <bool as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| if self.load(Ordering::SeqCst) { |
| once(AtomicBool::new(false)) |
| } else { |
| empty() |
| } |
| } |
| } |
| |
| impl Arbitrary for AtomicIsize { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <isize as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let x = self.load(Ordering::SeqCst); |
| Box::new(x.shrink().map(Self::new)) |
| } |
| } |
| |
| impl Arbitrary for AtomicUsize { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <usize as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let x = self.load(Ordering::SeqCst); |
| Box::new(x.shrink().map(Self::new)) |
| } |
| } |
| |
| impl Arbitrary for Duration { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Ok(Self::new( |
| <u64 as Arbitrary>::arbitrary(u)?, |
| <u32 as Arbitrary>::arbitrary(u)? % 1_000_000_000, |
| )) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and( |
| <u64 as Arbitrary>::size_hint(depth), |
| <u32 as Arbitrary>::size_hint(depth), |
| ) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| Box::new( |
| (self.as_secs(), self.subsec_nanos()) |
| .shrink() |
| .map(|(secs, nanos)| Duration::new(secs, nanos % 1_000_000_000)), |
| ) |
| } |
| } |
| |
| impl<A: Arbitrary> Arbitrary for Option<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Ok(if <bool as Arbitrary>::arbitrary(u)? { |
| Some(Arbitrary::arbitrary(u)?) |
| } else { |
| None |
| }) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and( |
| <bool as Arbitrary>::size_hint(depth), |
| crate::size_hint::or((0, Some(0)), <A as Arbitrary>::size_hint(depth)), |
| ) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| if let Some(ref a) = *self { |
| Box::new(iter::once(None).chain(a.shrink().map(Some))) |
| } else { |
| empty() |
| } |
| } |
| } |
| |
| impl<A: Arbitrary, B: Arbitrary> Arbitrary for std::result::Result<A, B> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Ok(if <bool as Arbitrary>::arbitrary(u)? { |
| Ok(<A as Arbitrary>::arbitrary(u)?) |
| } else { |
| Err(<B as Arbitrary>::arbitrary(u)?) |
| }) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and( |
| <bool as Arbitrary>::size_hint(depth), |
| crate::size_hint::or( |
| <A as Arbitrary>::size_hint(depth), |
| <B as Arbitrary>::size_hint(depth), |
| ), |
| ) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| match *self { |
| Ok(ref a) => Box::new(a.shrink().map(Ok)), |
| Err(ref b) => Box::new(b.shrink().map(Err)), |
| } |
| } |
| } |
| |
| macro_rules! arbitrary_tuple { |
| () => {}; |
| ($last: ident $($xs: ident)*) => { |
| arbitrary_tuple!($($xs)*); |
| |
| impl<$($xs: Arbitrary,)* $last: Arbitrary> Arbitrary for ($($xs,)* $last,) { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Ok(($($xs::arbitrary(u)?,)* Arbitrary::arbitrary(u)?,)) |
| } |
| |
| #[allow(unused_mut, non_snake_case)] |
| fn arbitrary_take_rest(mut u: Unstructured<'_>) -> Result<Self> { |
| $(let $xs = $xs::arbitrary(&mut u)?;)* |
| let $last = $last::arbitrary_take_rest(u)?; |
| Ok(($($xs,)* $last,)) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and_all(&[ |
| <$last as Arbitrary>::size_hint(depth), |
| $( <$xs as Arbitrary>::size_hint(depth) ),* |
| ]) |
| } |
| |
| #[allow(non_snake_case)] |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let ( $( $xs, )* $last, ) = self; |
| let ( $( mut $xs, )* mut $last,) = ( $( $xs.shrink(), )* $last.shrink(),); |
| Box::new(iter::from_fn(move || { |
| Some(( $( $xs.next()? ,)* $last.next()?, )) |
| })) |
| } |
| } |
| }; |
| } |
| arbitrary_tuple!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z); |
| |
| macro_rules! arbitrary_array { |
| {$n:expr, ($t:ident, $a:ident) $(($ts:ident, $as:ident))*} => { |
| arbitrary_array!{($n - 1), $(($ts, $as))*} |
| |
| impl<T: Arbitrary> Arbitrary for [T; $n] { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<[T; $n]> { |
| Ok([ |
| Arbitrary::arbitrary(u)?, |
| $(<$ts as Arbitrary>::arbitrary(u)?),* |
| ]) |
| } |
| |
| #[allow(unused_mut)] |
| fn arbitrary_take_rest(mut u: Unstructured<'_>) -> Result<[T; $n]> { |
| $(let $as = $ts::arbitrary(&mut u)?;)* |
| let last = Arbitrary::arbitrary_take_rest(u)?; |
| |
| Ok([ |
| $($as,)* last |
| ]) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and_all(&[ |
| <$t as Arbitrary>::size_hint(depth), |
| $( <$ts as Arbitrary>::size_hint(depth) ),* |
| ]) |
| } |
| |
| #[allow(unused_mut)] // For the `[T; 1]` case. |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let mut i = 0; |
| let mut shrinkers = [ |
| self[i].shrink(), |
| $({ |
| i += 1; |
| let t: &$ts = &self[i]; |
| t.shrink() |
| }),* |
| ]; |
| Box::new(iter::from_fn(move || { |
| let mut i = 0; |
| Some([ |
| shrinkers[i].next()?, |
| $({ |
| i += 1; |
| let t: $ts = shrinkers[i].next()?; |
| t |
| }),* |
| ]) |
| })) |
| } |
| } |
| }; |
| ($n: expr,) => {}; |
| } |
| |
| arbitrary_array! { 32, (T, a) (T, b) (T, c) (T, d) (T, e) (T, f) (T, g) (T, h) |
| (T, i) (T, j) (T, k) (T, l) (T, m) (T, n) (T, o) (T, p) |
| (T, q) (T, r) (T, s) (T, u) (T, v) (T, w) (T, x) (T, y) |
| (T, z) (T, aa) (T, ab) (T, ac) (T, ad) (T, ae) (T, af) |
| (T, ag) } |
| |
| fn shrink_collection<'a, T, A: Arbitrary>( |
| entries: impl Iterator<Item = T>, |
| f: impl Fn(&T) -> Box<dyn Iterator<Item = A>>, |
| ) -> Box<dyn Iterator<Item = Vec<A>>> { |
| let entries: Vec<_> = entries.collect(); |
| if entries.is_empty() { |
| return empty(); |
| } |
| |
| let mut shrinkers: Vec<Vec<_>> = vec![]; |
| let mut i = entries.len(); |
| loop { |
| shrinkers.push(entries.iter().take(i).map(&f).collect()); |
| i = i / 2; |
| if i == 0 { |
| break; |
| } |
| } |
| Box::new(iter::once(vec![]).chain(iter::from_fn(move || loop { |
| let mut shrinker = shrinkers.pop()?; |
| let x: Option<Vec<A>> = shrinker.iter_mut().map(|s| s.next()).collect(); |
| if x.is_none() { |
| continue; |
| } |
| shrinkers.push(shrinker); |
| return x; |
| }))) |
| } |
| |
| impl<A: Arbitrary> Arbitrary for Vec<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_iter()?.collect() |
| } |
| |
| fn arbitrary_take_rest(u: Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_take_rest_iter()?.collect() |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| shrink_collection(self.iter(), |x| x.shrink()) |
| } |
| } |
| |
| impl<K: Arbitrary + Ord, V: Arbitrary> Arbitrary for BTreeMap<K, V> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_iter()?.collect() |
| } |
| |
| fn arbitrary_take_rest(u: Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_take_rest_iter()?.collect() |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = |
| shrink_collection(self.iter(), |(k, v)| Box::new(k.shrink().zip(v.shrink()))); |
| Box::new(collections.map(|entries| entries.into_iter().collect())) |
| } |
| } |
| |
| impl<A: Arbitrary + Ord> Arbitrary for BTreeSet<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_iter()?.collect() |
| } |
| |
| fn arbitrary_take_rest(u: Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_take_rest_iter()?.collect() |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = shrink_collection(self.iter(), |v| v.shrink()); |
| Box::new(collections.map(|entries| entries.into_iter().collect())) |
| } |
| } |
| |
| impl<A: Arbitrary + Ord> Arbitrary for BinaryHeap<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_iter()?.collect() |
| } |
| |
| fn arbitrary_take_rest(u: Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_take_rest_iter()?.collect() |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = shrink_collection(self.iter(), |v| v.shrink()); |
| Box::new(collections.map(|entries| entries.into_iter().collect())) |
| } |
| } |
| |
| impl<K: Arbitrary + Eq + ::std::hash::Hash, V: Arbitrary> Arbitrary for HashMap<K, V> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_iter()?.collect() |
| } |
| |
| fn arbitrary_take_rest(u: Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_take_rest_iter()?.collect() |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = |
| shrink_collection(self.iter(), |(k, v)| Box::new(k.shrink().zip(v.shrink()))); |
| Box::new(collections.map(|entries| entries.into_iter().collect())) |
| } |
| } |
| |
| impl<A: Arbitrary + Eq + ::std::hash::Hash> Arbitrary for HashSet<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_iter()?.collect() |
| } |
| |
| fn arbitrary_take_rest(u: Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_take_rest_iter()?.collect() |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = shrink_collection(self.iter(), |v| v.shrink()); |
| Box::new(collections.map(|entries| entries.into_iter().collect())) |
| } |
| } |
| |
| impl<A: Arbitrary> Arbitrary for LinkedList<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_iter()?.collect() |
| } |
| |
| fn arbitrary_take_rest(u: Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_take_rest_iter()?.collect() |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = shrink_collection(self.iter(), |v| v.shrink()); |
| Box::new(collections.map(|entries| entries.into_iter().collect())) |
| } |
| } |
| |
| impl<A: Arbitrary> Arbitrary for VecDeque<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_iter()?.collect() |
| } |
| |
| fn arbitrary_take_rest(u: Unstructured<'_>) -> Result<Self> { |
| u.arbitrary_take_rest_iter()?.collect() |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = shrink_collection(self.iter(), |v| v.shrink()); |
| Box::new(collections.map(|entries| entries.into_iter().collect())) |
| } |
| } |
| |
| impl<A> Arbitrary for Cow<'static, A> |
| where |
| A: ToOwned + ?Sized, |
| <A as ToOwned>::Owned: Arbitrary, |
| { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Cow::Owned) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::recursion_guard(depth, |depth| { |
| <<A as ToOwned>::Owned as Arbitrary>::size_hint(depth) |
| }) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| match *self { |
| Cow::Owned(ref o) => Box::new(o.shrink().map(Cow::Owned)), |
| Cow::Borrowed(b) => Box::new(b.to_owned().shrink().map(Cow::Owned)), |
| } |
| } |
| } |
| |
| impl Arbitrary for String { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| let size = u.arbitrary_len::<u8>()?; |
| let bytes = u.get_bytes(size)?; |
| str::from_utf8(bytes) |
| .map_err(|_| Error::IncorrectFormat) |
| .map(Into::into) |
| } |
| |
| fn arbitrary_take_rest(u: Unstructured<'_>) -> Result<Self> { |
| let bytes = u.take_rest(); |
| str::from_utf8(bytes) |
| .map_err(|_| Error::IncorrectFormat) |
| .map(Into::into) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = shrink_collection(self.chars(), |ch| ch.shrink()); |
| Box::new(collections.map(|chars| chars.into_iter().collect())) |
| } |
| } |
| |
| impl Arbitrary for CString { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| <Vec<u8> as Arbitrary>::arbitrary(u).map(|mut x| { |
| x.retain(|&c| c != 0); |
| Self::new(x).unwrap() |
| }) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <Vec<u8> as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = shrink_collection(self.as_bytes().iter(), |b| { |
| Box::new(b.shrink().filter(|&b| b != 0)) |
| }); |
| Box::new(collections.map(|bytes| Self::new(bytes).unwrap())) |
| } |
| } |
| |
| impl Arbitrary for OsString { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| <String as Arbitrary>::arbitrary(u).map(From::from) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <String as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| match self.clone().into_string() { |
| Err(_) if self.is_empty() => empty(), |
| Err(_) => once(OsString::from("".to_string())), |
| Ok(s) => Box::new(s.shrink().map(From::from)), |
| } |
| } |
| } |
| |
| impl Arbitrary for PathBuf { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| <OsString as Arbitrary>::arbitrary(u).map(From::from) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <OsString as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let s = self.clone().into_os_string(); |
| Box::new(s.shrink().map(From::from)) |
| } |
| } |
| |
| impl<A: Arbitrary> Arbitrary for Box<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::recursion_guard(depth, |depth| <A as Arbitrary>::size_hint(depth)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| Box::new((&**self).shrink().map(Self::new)) |
| } |
| } |
| |
| impl<A: Arbitrary> Arbitrary for Box<[A]> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| <Vec<A> as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_slice()) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <Vec<A> as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| Box::new(shrink_collection(self.iter(), |x| x.shrink()).map(|v| v.into_boxed_slice())) |
| } |
| } |
| |
| impl Arbitrary for Box<str> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| <String as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_str()) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <String as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let collections = shrink_collection(self.chars(), |ch| ch.shrink()); |
| Box::new(collections.map(|chars| chars.into_iter().collect::<String>().into_boxed_str())) |
| } |
| } |
| |
| // impl Arbitrary for Box<CStr> { |
| // fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| // <CString as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_c_str()) |
| // } |
| // } |
| |
| // impl Arbitrary for Box<OsStr> { |
| // fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| // <OsString as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_osstr()) |
| // |
| // } |
| // } |
| |
| impl<A: Arbitrary> Arbitrary for Arc<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::recursion_guard(depth, |depth| <A as Arbitrary>::size_hint(depth)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| Box::new((&**self).shrink().map(Self::new)) |
| } |
| } |
| |
| impl<A: Arbitrary> Arbitrary for Rc<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| crate::size_hint::recursion_guard(depth, |depth| <A as Arbitrary>::size_hint(depth)) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| Box::new((&**self).shrink().map(Self::new)) |
| } |
| } |
| |
| impl<A: Arbitrary> Arbitrary for Cell<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <A as Arbitrary>::size_hint(depth) |
| } |
| |
| // Note: can't implement `shrink` without either more trait bounds on `A` |
| // (copy or default) or `Cell::update`: |
| // https://github.com/rust-lang/rust/issues/50186 |
| } |
| |
| impl<A: Arbitrary> Arbitrary for RefCell<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <A as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let x = self.borrow(); |
| Box::new(x.shrink().map(Self::new)) |
| } |
| } |
| |
| impl<A: Arbitrary> Arbitrary for UnsafeCell<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <A as Arbitrary>::size_hint(depth) |
| } |
| |
| // We can't non-trivially (i.e. not an empty iterator) implement `shrink` in |
| // a safe way, since we don't have a safe way to get the inner value. |
| } |
| |
| impl<A: Arbitrary> Arbitrary for Mutex<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(Self::new) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <A as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| match self.lock() { |
| Err(_) => empty(), |
| Ok(g) => Box::new(g.shrink().map(Self::new)), |
| } |
| } |
| } |
| |
| impl<A: Arbitrary> Arbitrary for iter::Empty<A> { |
| fn arbitrary(_: &mut Unstructured<'_>) -> Result<Self> { |
| Ok(iter::empty()) |
| } |
| |
| #[inline] |
| fn size_hint(_depth: usize) -> (usize, Option<usize>) { |
| (0, Some(0)) |
| } |
| |
| // Nothing to shrink here. |
| } |
| |
| impl<A: Arbitrary> Arbitrary for ::std::marker::PhantomData<A> { |
| fn arbitrary(_: &mut Unstructured<'_>) -> Result<Self> { |
| Ok(::std::marker::PhantomData) |
| } |
| |
| #[inline] |
| fn size_hint(_depth: usize) -> (usize, Option<usize>) { |
| (0, Some(0)) |
| } |
| |
| // Nothing to shrink here. |
| } |
| |
| impl<A: Arbitrary> Arbitrary for ::std::num::Wrapping<A> { |
| fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { |
| Arbitrary::arbitrary(u).map(::std::num::Wrapping) |
| } |
| |
| #[inline] |
| fn size_hint(depth: usize) -> (usize, Option<usize>) { |
| <A as Arbitrary>::size_hint(depth) |
| } |
| |
| fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { |
| let ref x = self.0; |
| Box::new(x.shrink().map(::std::num::Wrapping)) |
| } |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use super::*; |
| |
| #[test] |
| fn finite_buffer_fill_buffer() { |
| let x = [1, 2, 3, 4]; |
| let mut rb = Unstructured::new(&x); |
| let mut z = [0; 2]; |
| rb.fill_buffer(&mut z).unwrap(); |
| assert_eq!(z, [1, 2]); |
| rb.fill_buffer(&mut z).unwrap(); |
| assert_eq!(z, [3, 4]); |
| assert!(rb.fill_buffer(&mut z).is_err()); |
| } |
| |
| #[test] |
| fn arbitrary_for_integers() { |
| let x = [1, 2, 3, 4]; |
| let mut buf = Unstructured::new(&x); |
| let expected = 1 | (2 << 8) | (3 << 16) | (4 << 24); |
| let actual = i32::arbitrary(&mut buf).unwrap(); |
| assert_eq!(expected, actual); |
| } |
| |
| #[test] |
| fn arbitrary_collection() { |
| let x = [ |
| 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, |
| ]; |
| assert_eq!( |
| Vec::<u8>::arbitrary(&mut Unstructured::new(&x)).unwrap(), |
| &[1, 2, 3, 4, 5, 6, 7, 8] |
| ); |
| assert_eq!( |
| Vec::<u32>::arbitrary(&mut Unstructured::new(&x)).unwrap(), |
| &[0x4030201, 0x8070605] |
| ); |
| assert_eq!( |
| String::arbitrary(&mut Unstructured::new(&x)).unwrap(), |
| "\x01\x02\x03\x04\x05\x06\x07\x08" |
| ); |
| } |
| |
| #[test] |
| fn arbitrary_take_rest() { |
| let x = [1, 2, 3, 4]; |
| assert_eq!( |
| Vec::<u8>::arbitrary_take_rest(Unstructured::new(&x)).unwrap(), |
| &[1, 2, 3, 4] |
| ); |
| assert_eq!( |
| Vec::<u32>::arbitrary_take_rest(Unstructured::new(&x)).unwrap(), |
| &[0x4030201] |
| ); |
| assert_eq!( |
| String::arbitrary_take_rest(Unstructured::new(&x)).unwrap(), |
| "\x01\x02\x03\x04" |
| ); |
| } |
| |
| #[test] |
| fn shrink_tuple() { |
| let tup = (10, 20, 30); |
| assert_eq!( |
| tup.shrink().collect::<Vec<_>>(), |
| [(0, 0, 0), (5, 10, 15), (2, 5, 7), (1, 2, 3)] |
| ); |
| } |
| |
| #[test] |
| fn shrink_array() { |
| let tup = [10, 20, 30]; |
| assert_eq!( |
| tup.shrink().collect::<Vec<_>>(), |
| [[0, 0, 0], [5, 10, 15], [2, 5, 7], [1, 2, 3]] |
| ); |
| } |
| |
| #[test] |
| fn shrink_vec() { |
| let v = vec![4, 4, 4, 4]; |
| assert_eq!( |
| v.shrink().collect::<Vec<_>>(), |
| [ |
| vec![], |
| vec![0], |
| vec![2], |
| vec![1], |
| vec![0, 0], |
| vec![2, 2], |
| vec![1, 1], |
| vec![0, 0, 0, 0], |
| vec![2, 2, 2, 2], |
| vec![1, 1, 1, 1] |
| ] |
| ); |
| } |
| |
| #[test] |
| fn shrink_string() { |
| let s = "aaaa".to_string(); |
| assert_eq!( |
| s.shrink().collect::<Vec<_>>(), |
| [ |
| "", |
| "\u{0}", |
| "0", |
| "\u{18}", |
| "\u{c}", |
| "\u{6}", |
| "\u{3}", |
| "\u{1}", |
| "\u{0}\u{0}", |
| "00", |
| "\u{18}\u{18}", |
| "\u{c}\u{c}", |
| "\u{6}\u{6}", |
| "\u{3}\u{3}", |
| "\u{1}\u{1}", |
| "\u{0}\u{0}\u{0}\u{0}", |
| "0000", |
| "\u{18}\u{18}\u{18}\u{18}", |
| "\u{c}\u{c}\u{c}\u{c}", |
| "\u{6}\u{6}\u{6}\u{6}", |
| "\u{3}\u{3}\u{3}\u{3}", |
| "\u{1}\u{1}\u{1}\u{1}" |
| ] |
| .iter() |
| .map(|s| s.to_string()) |
| .collect::<Vec<_>>(), |
| ); |
| } |
| |
| #[test] |
| fn shrink_cstring() { |
| let s = CString::new(b"aaaa".to_vec()).unwrap(); |
| assert_eq!( |
| s.shrink().collect::<Vec<_>>(), |
| [ |
| &[][..], |
| &[b'0'][..], |
| &[0x18][..], |
| &[0x0c][..], |
| &[0x06][..], |
| &[0x03][..], |
| &[0x01][..], |
| &[b'0', b'0'][..], |
| &[0x18, 0x18][..], |
| &[0x0c, 0x0c][..], |
| &[0x06, 0x06][..], |
| &[0x03, 0x03][..], |
| &[0x01, 0x01][..], |
| &[b'0', b'0', b'0', b'0'][..], |
| &[0x18, 0x18, 0x18, 0x18][..], |
| &[0x0c, 0x0c, 0x0c, 0x0c][..], |
| &[0x06, 0x06, 0x06, 0x06][..], |
| &[0x03, 0x03, 0x03, 0x03][..], |
| &[0x01, 0x01, 0x01, 0x01][..], |
| ] |
| .iter() |
| .map(|s| CString::new(s.to_vec()).unwrap()) |
| .collect::<Vec<_>>(), |
| ); |
| } |
| |
| #[test] |
| fn size_hint_for_tuples() { |
| assert_eq!((7, Some(7)), <(bool, u16, i32) as Arbitrary>::size_hint(0)); |
| assert_eq!( |
| (1 + mem::size_of::<usize>(), None), |
| <(u8, Vec<u8>) as Arbitrary>::size_hint(0) |
| ); |
| } |
| } |