summaryrefslogtreecommitdiffstats
path: root/vendor/proptest/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/proptest/src
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/proptest/src')
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/alloc.rs59
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/borrow.rs27
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/boxed.rs19
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/char.rs89
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/collections.rs304
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/hash.rs32
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/mod.rs22
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/ops.rs104
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/rc.rs21
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/str.rs49
-rw-r--r--vendor/proptest/src/arbitrary/_alloc/sync.rs76
-rw-r--r--vendor/proptest/src/arbitrary/_core/ascii.rs23
-rw-r--r--vendor/proptest/src/arbitrary/_core/cell.rs48
-rw-r--r--vendor/proptest/src/arbitrary/_core/cmp.rs33
-rw-r--r--vendor/proptest/src/arbitrary/_core/convert.rs16
-rw-r--r--vendor/proptest/src/arbitrary/_core/fmt.rs18
-rw-r--r--vendor/proptest/src/arbitrary/_core/iter.rs188
-rw-r--r--vendor/proptest/src/arbitrary/_core/marker.rs19
-rw-r--r--vendor/proptest/src/arbitrary/_core/mem.rs42
-rw-r--r--vendor/proptest/src/arbitrary/_core/mod.rs22
-rw-r--r--vendor/proptest/src/arbitrary/_core/num.rs55
-rw-r--r--vendor/proptest/src/arbitrary/_core/option.rs57
-rw-r--r--vendor/proptest/src/arbitrary/_core/result.rs108
-rw-r--r--vendor/proptest/src/arbitrary/_std/env.rs141
-rw-r--r--vendor/proptest/src/arbitrary/_std/ffi.rs100
-rw-r--r--vendor/proptest/src/arbitrary/_std/fs.rs30
-rw-r--r--vendor/proptest/src/arbitrary/_std/io.rs164
-rw-r--r--vendor/proptest/src/arbitrary/_std/mod.rs22
-rw-r--r--vendor/proptest/src/arbitrary/_std/net.rs117
-rw-r--r--vendor/proptest/src/arbitrary/_std/panic.rs19
-rw-r--r--vendor/proptest/src/arbitrary/_std/path.rs23
-rw-r--r--vendor/proptest/src/arbitrary/_std/string.rs318
-rw-r--r--vendor/proptest/src/arbitrary/_std/sync.rs166
-rw-r--r--vendor/proptest/src/arbitrary/_std/thread.rs81
-rw-r--r--vendor/proptest/src/arbitrary/_std/time.rs50
-rw-r--r--vendor/proptest/src/arbitrary/arrays.rs34
-rw-r--r--vendor/proptest/src/arbitrary/functor.rs220
-rw-r--r--vendor/proptest/src/arbitrary/macros.rs115
-rw-r--r--vendor/proptest/src/arbitrary/mod.rs69
-rw-r--r--vendor/proptest/src/arbitrary/non_zero.rs66
-rw-r--r--vendor/proptest/src/arbitrary/primitives.rs46
-rw-r--r--vendor/proptest/src/arbitrary/sample.rs31
-rw-r--r--vendor/proptest/src/arbitrary/traits.rs295
-rw-r--r--vendor/proptest/src/arbitrary/tuples.rs45
-rw-r--r--vendor/proptest/src/array.rs264
-rw-r--r--vendor/proptest/src/bits.rs677
-rw-r--r--vendor/proptest/src/bool.rs144
-rw-r--r--vendor/proptest/src/char.rs409
-rw-r--r--vendor/proptest/src/collection.rs779
-rw-r--r--vendor/proptest/src/file-preamble8
-rw-r--r--vendor/proptest/src/lib.rs102
-rw-r--r--vendor/proptest/src/macros.rs93
-rw-r--r--vendor/proptest/src/num.rs1388
-rw-r--r--vendor/proptest/src/num/float_samplers.rs463
-rw-r--r--vendor/proptest/src/option.rs271
-rw-r--r--vendor/proptest/src/prelude.rs53
-rw-r--r--vendor/proptest/src/product_frunk.rs49
-rw-r--r--vendor/proptest/src/product_tuple.rs49
-rw-r--r--vendor/proptest/src/regex-contrib/README.md3
-rw-r--r--vendor/proptest/src/regex-contrib/crates_regex.rs3129
-rw-r--r--vendor/proptest/src/result.rs326
-rw-r--r--vendor/proptest/src/sample.rs566
-rw-r--r--vendor/proptest/src/std_facade.rs74
-rw-r--r--vendor/proptest/src/strategy/filter.rs147
-rw-r--r--vendor/proptest/src/strategy/filter_map.rs209
-rw-r--r--vendor/proptest/src/strategy/flatten.rs359
-rw-r--r--vendor/proptest/src/strategy/fuse.rs228
-rw-r--r--vendor/proptest/src/strategy/just.rs145
-rw-r--r--vendor/proptest/src/strategy/lazy.rs175
-rw-r--r--vendor/proptest/src/strategy/map.rs301
-rw-r--r--vendor/proptest/src/strategy/mod.rs37
-rw-r--r--vendor/proptest/src/strategy/recursive.rs209
-rw-r--r--vendor/proptest/src/strategy/shuffle.rs287
-rw-r--r--vendor/proptest/src/strategy/statics.rs266
-rw-r--r--vendor/proptest/src/strategy/traits.rs1054
-rw-r--r--vendor/proptest/src/strategy/unions.rs697
-rw-r--r--vendor/proptest/src/string.rs560
-rw-r--r--vendor/proptest/src/sugar.rs1637
-rw-r--r--vendor/proptest/src/test_runner/config.rs516
-rw-r--r--vendor/proptest/src/test_runner/errors.rs135
-rw-r--r--vendor/proptest/src/test_runner/failure_persistence/file.rs536
-rw-r--r--vendor/proptest/src/test_runner/failure_persistence/map.rs99
-rw-r--r--vendor/proptest/src/test_runner/failure_persistence/mod.rs156
-rw-r--r--vendor/proptest/src/test_runner/failure_persistence/noop.rs76
-rw-r--r--vendor/proptest/src/test_runner/mod.rs31
-rw-r--r--vendor/proptest/src/test_runner/reason.rs54
-rw-r--r--vendor/proptest/src/test_runner/replay.rs189
-rw-r--r--vendor/proptest/src/test_runner/result_cache.rs120
-rw-r--r--vendor/proptest/src/test_runner/rng.rs724
-rw-r--r--vendor/proptest/src/test_runner/runner.rs1538
-rw-r--r--vendor/proptest/src/tuple.rs181
91 files changed, 23096 insertions, 0 deletions
diff --git a/vendor/proptest/src/arbitrary/_alloc/alloc.rs b/vendor/proptest/src/arbitrary/_alloc/alloc.rs
new file mode 100644
index 000000000..598c80ff0
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/alloc.rs
@@ -0,0 +1,59 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::hash`.
+
+use core::cmp;
+use core::ops::Range;
+use core::usize;
+
+multiplex_alloc!(::alloc::alloc, ::std::alloc);
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+arbitrary!(self::alloc::Global; self::alloc::Global);
+
+// Not Debug.
+//lazy_just!(System, || System);
+
+arbitrary!(self::alloc::Layout, SFnPtrMap<(Range<u8>, StrategyFor<usize>), Self>;
+ // 1. align must be a power of two and <= (1 << 31):
+ // 2. "when rounded up to the nearest multiple of align, must not overflow".
+ static_map((0u8..32u8, any::<usize>()), |(align_power, size)| {
+ let align = 1usize << align_power;
+ // TODO: This may only work on 64 bit processors, but previously it was broken
+ // even on 64 bit so still an improvement. 63 -> uint size - 1.
+ let max_size = (1usize << 63) - (1 << usize::from(align_power));
+ // Not quite a uniform distribution due to clamping,
+ // but probably good enough
+ self::alloc::Layout::from_size_align(cmp::min(max_size, size), align).unwrap()
+ })
+);
+
+arbitrary!(self::alloc::AllocError, Just<Self>; Just(self::alloc::AllocError));
+/* 2018-07-28 CollectionAllocErr is not currently available outside of using
+ * the `alloc` crate, which would require a different nightly feature. For now,
+ * disable.
+arbitrary!(alloc::collections::CollectionAllocErr, TupleUnion<(WA<Just<Self>>, WA<Just<Self>>)>;
+ prop_oneof![Just(alloc::collections::CollectionAllocErr::AllocErr),
+ Just(alloc::collections::CollectionAllocErr::CapacityOverflow)]);
+ */
+
+#[cfg(test)]
+mod test {
+ multiplex_alloc!(::alloc::alloc, ::std::alloc);
+
+ no_panic_test!(
+ layout => self::alloc::Layout,
+ alloc_err => self::alloc::AllocError
+ //collection_alloc_err => alloc::collections::CollectionAllocErr
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_alloc/borrow.rs b/vendor/proptest/src/arbitrary/_alloc/borrow.rs
new file mode 100644
index 000000000..153115e18
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/borrow.rs
@@ -0,0 +1,27 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for std::borrow.
+
+use crate::std_facade::fmt;
+use crate::std_facade::{Cow, ToOwned};
+use core::borrow::Borrow;
+
+use crate::arbitrary::{any_with, Arbitrary, SMapped};
+use crate::strategy::statics::static_map;
+
+arbitrary!(
+ [A: Arbitrary + Borrow<B>, B: ToOwned<Owned = A> + fmt::Debug + ?Sized]
+ Cow<'static, B>, SMapped<A, Self>, A::Parameters;
+ args => static_map(any_with::<A>(args), Cow::Owned)
+);
+
+lift1!([Borrow<B> + 'static, B: ToOwned<Owned = A> + fmt::Debug + ?Sized]
+ Cow<'static, B>; base => static_map(base, Cow::Owned)
+);
diff --git a/vendor/proptest/src/arbitrary/_alloc/boxed.rs b/vendor/proptest/src/arbitrary/_alloc/boxed.rs
new file mode 100644
index 000000000..222362504
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/boxed.rs
@@ -0,0 +1,19 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::boxed`.
+
+use crate::std_facade::Box;
+
+wrap_from!(Box);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(boxed => Box<u8>);
+}
diff --git a/vendor/proptest/src/arbitrary/_alloc/char.rs b/vendor/proptest/src/arbitrary/_alloc/char.rs
new file mode 100644
index 000000000..fab9dd824
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/char.rs
@@ -0,0 +1,89 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::char`.
+
+use crate::std_facade::Vec;
+use core::char::*;
+use core::iter::once;
+use core::ops::Range;
+
+use crate::collection::vec;
+
+multiplex_alloc! {
+ core::char::DecodeUtf16, std::char::DecodeUtf16,
+ core::char::DecodeUtf16Error, std::char::DecodeUtf16Error,
+ core::char::decode_utf16, std::char::decode_utf16
+}
+
+const VEC_MAX: usize = ::core::u16::MAX as usize;
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+macro_rules! impl_wrap_char {
+ ($type: ty, $mapper: expr) => {
+ arbitrary!($type, SMapped<char, Self>;
+ static_map(any::<char>(), $mapper));
+ };
+}
+
+impl_wrap_char!(EscapeDebug, char::escape_debug);
+impl_wrap_char!(EscapeDefault, char::escape_default);
+impl_wrap_char!(EscapeUnicode, char::escape_unicode);
+#[cfg(feature = "unstable")]
+impl_wrap_char!(ToLowercase, char::to_lowercase);
+#[cfg(feature = "unstable")]
+impl_wrap_char!(ToUppercase, char::to_uppercase);
+
+#[cfg(feature = "break-dead-code")]
+arbitrary!(DecodeUtf16<<Vec<u16> as IntoIterator>::IntoIter>,
+ SMapped<Vec<u16>, Self>;
+ static_map(vec(any::<u16>(), ..VEC_MAX), decode_utf16)
+);
+
+arbitrary!(ParseCharError, IndFlatten<Mapped<bool, Just<Self>>>;
+ any::<bool>().prop_ind_flat_map(|is_two|
+ Just((if is_two { "__" } else { "" }).parse::<char>().unwrap_err()))
+);
+
+#[cfg(feature = "unstable")]
+arbitrary!(CharTryFromError; {
+ use core::convert::TryFrom;
+ char::try_from(0xD800 as u32).unwrap_err()
+});
+
+arbitrary!(DecodeUtf16Error, SFnPtrMap<Range<u16>, Self>;
+ static_map(0xD800..0xE000, |x|
+ decode_utf16(once(x)).next().unwrap().unwrap_err())
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ escape_debug => EscapeDebug,
+ escape_default => EscapeDefault,
+ escape_unicode => EscapeUnicode,
+ parse_char_error => ParseCharError,
+ decode_utf16_error => DecodeUtf16Error
+ );
+
+ #[cfg(feature = "break-dead-code")]
+ no_panic_test!(
+ decode_utf16 => DecodeUtf16<<Vec<u16> as IntoIterator>::IntoIter>
+ );
+
+ #[cfg(feature = "unstable")]
+ no_panic_test!(
+ to_lowercase => ToLowercase,
+ to_uppercase => ToUppercase,
+ char_try_from_error => CharTryFromError
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_alloc/collections.rs b/vendor/proptest/src/arbitrary/_alloc/collections.rs
new file mode 100644
index 000000000..20f3a9292
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/collections.rs
@@ -0,0 +1,304 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::collections`.
+
+//#![cfg_attr(feature="cargo-clippy", allow(implicit_hasher))]
+
+//==============================================================================
+// Imports:
+//==============================================================================
+
+use crate::std_facade::{
+ binary_heap, btree_map, btree_set, fmt, linked_list, vec, vec_deque, Arc,
+ BTreeMap, BTreeSet, BinaryHeap, Box, LinkedList, Rc, Vec, VecDeque,
+};
+use core::hash::Hash;
+use core::ops::{Bound, RangeInclusive};
+
+#[cfg(feature = "std")]
+use crate::std_facade::{hash_map, hash_set, HashMap, HashSet};
+
+use crate::arbitrary::*;
+use crate::collection::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+//==============================================================================
+// Macros:
+//==============================================================================
+
+/// Parameters for configuring the generation of `StrategyFor<...<A>>`.
+type RangedParams1<A> = product_type![SizeRange, A];
+
+/// Parameters for configuring the generation of `StrategyFor<...<A, B>>`.
+type RangedParams2<A, B> = product_type![SizeRange, A, B];
+
+macro_rules! impl_1 {
+ ($typ: ident, $strat: ident, $($bound : path),* => $fun: ident) => {
+ arbitrary!([A: Arbitrary $(+ $bound)*] $typ<A>,
+ $strat<A::Strategy>, RangedParams1<A::Parameters>;
+ args => {
+ let product_unpack![range, a] = args;
+ $fun(any_with::<A>(a), range)
+ });
+
+ lift1!([$($bound+)*] $typ<A>, SizeRange;
+ base, args => $fun(base, args));
+ };
+}
+
+arbitrary!(SizeRange, MapInto<StrategyFor<RangeInclusive<usize>>, Self>;
+ any::<RangeInclusive<usize>>().prop_map_into()
+);
+
+//==============================================================================
+// Vec, VecDeque, LinkedList, BTreeSet, BinaryHeap, HashSet, HashMap:
+//==============================================================================
+
+macro_rules! dst_wrapped {
+ ($($w: ident),*) => {
+ $(arbitrary!([A: Arbitrary] $w<[A]>,
+ MapInto<StrategyFor<Vec<A>>, Self>,
+ <Vec<A> as Arbitrary>::Parameters;
+ a => any_with::<Vec<A>>(a).prop_map_into()
+ );)*
+ };
+}
+
+impl_1!(Vec, VecStrategy, => vec);
+dst_wrapped!(Box, Rc, Arc);
+impl_1!(VecDeque, VecDequeStrategy, => vec_deque);
+impl_1!(LinkedList, LinkedListStrategy, => linked_list);
+impl_1!(BTreeSet, BTreeSetStrategy, Ord => btree_set);
+impl_1!(BinaryHeap, BinaryHeapStrategy, Ord => binary_heap);
+#[cfg(feature = "std")]
+impl_1!(HashSet, HashSetStrategy, Hash, Eq => hash_set);
+
+//==============================================================================
+// IntoIterator:
+//==============================================================================
+
+macro_rules! into_iter_1 {
+ ($module: ident, $type: ident $(, $bound : path)*) => {
+ arbitrary!([A: Arbitrary $(+ $bound)*]
+ $module::IntoIter<A>,
+ SMapped<$type<A>, Self>,
+ <$type<A> as Arbitrary>::Parameters;
+ args => static_map(any_with::<$type<A>>(args), $type::into_iter));
+
+ lift1!(['static + $($bound+)*] $module::IntoIter<A>, SizeRange;
+ base, args =>
+ $module(base, args).prop_map($type::into_iter));
+ };
+}
+
+into_iter_1!(vec, Vec);
+into_iter_1!(vec_deque, VecDeque);
+into_iter_1!(linked_list, LinkedList);
+into_iter_1!(btree_set, BTreeSet, Ord);
+into_iter_1!(binary_heap, BinaryHeap, Ord);
+#[cfg(feature = "std")]
+into_iter_1!(hash_set, HashSet, Hash, Eq);
+
+//==============================================================================
+// HashMap:
+//==============================================================================
+
+#[cfg(feature = "std")]
+arbitrary!([A: Arbitrary + Hash + Eq, B: Arbitrary] HashMap<A, B>,
+HashMapStrategy<A::Strategy, B::Strategy>,
+RangedParams2<A::Parameters, B::Parameters>;
+args => {
+ let product_unpack![range, a, b] = args;
+ hash_map(any_with::<A>(a), any_with::<B>(b), range)
+});
+
+#[cfg(feature = "std")]
+arbitrary!([A: Arbitrary + Hash + Eq, B: Arbitrary] hash_map::IntoIter<A, B>,
+ SMapped<HashMap<A, B>, Self>,
+ <HashMap<A, B> as Arbitrary>::Parameters;
+ args => static_map(any_with::<HashMap<A, B>>(args), HashMap::into_iter));
+
+#[cfg(feature = "std")]
+lift1!([, K: Hash + Eq + Arbitrary + 'static] HashMap<K, A>,
+ RangedParams1<K::Parameters>;
+ base, args => {
+ let product_unpack![range, k] = args;
+ hash_map(any_with::<K>(k), base, range)
+ }
+);
+
+#[cfg(feature = "std")]
+lift1!(['static, K: Hash + Eq + Arbitrary + 'static] hash_map::IntoIter<K, A>,
+ RangedParams1<K::Parameters>;
+ base, args => {
+ let product_unpack![range, k] = args;
+ static_map(hash_map(any_with::<K>(k), base, range), HashMap::into_iter)
+ }
+);
+
+#[cfg(feature = "std")]
+impl<A: fmt::Debug + Eq + Hash, B: fmt::Debug> functor::ArbitraryF2<A, B>
+ for HashMap<A, B>
+{
+ type Parameters = SizeRange;
+
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ hash_map(fst, snd, args).boxed()
+ }
+}
+
+#[cfg(feature = "std")]
+impl<A: fmt::Debug + Eq + Hash + 'static, B: fmt::Debug + 'static>
+ functor::ArbitraryF2<A, B> for hash_map::IntoIter<A, B>
+{
+ type Parameters = SizeRange;
+
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ static_map(hash_map(fst, snd, args), HashMap::into_iter).boxed()
+ }
+}
+
+//==============================================================================
+// BTreeMap:
+//==============================================================================
+
+arbitrary!([A: Arbitrary + Ord, B: Arbitrary] BTreeMap<A, B>,
+BTreeMapStrategy<A::Strategy, B::Strategy>,
+RangedParams2<A::Parameters, B::Parameters>;
+args => {
+ let product_unpack![range, a, b] = args;
+ btree_map(any_with::<A>(a), any_with::<B>(b), range)
+});
+
+lift1!([, K: Ord + Arbitrary + 'static] BTreeMap<K, A>,
+ RangedParams1<K::Parameters>;
+ base, args => {
+ let product_unpack![range, k] = args;
+ btree_map(any_with::<K>(k), base, range)
+ }
+);
+
+impl<A: fmt::Debug + Ord, B: fmt::Debug> functor::ArbitraryF2<A, B>
+ for BTreeMap<A, B>
+{
+ type Parameters = SizeRange;
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ btree_map(fst, snd, args).boxed()
+ }
+}
+
+arbitrary!([A: Arbitrary + Ord, B: Arbitrary] btree_map::IntoIter<A, B>,
+ SMapped<BTreeMap<A, B>, Self>,
+ <BTreeMap<A, B> as Arbitrary>::Parameters;
+ args => static_map(any_with::<BTreeMap<A, B>>(args), BTreeMap::into_iter));
+
+impl<A: fmt::Debug + Ord + 'static, B: fmt::Debug + 'static>
+ functor::ArbitraryF2<A, B> for btree_map::IntoIter<A, B>
+{
+ type Parameters = SizeRange;
+
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ static_map(btree_map(fst, snd, args), BTreeMap::into_iter).boxed()
+ }
+}
+
+//==============================================================================
+// Bound:
+//==============================================================================
+
+arbitrary!([A: Arbitrary] Bound<A>,
+ TupleUnion<(
+ WA<SFnPtrMap<Arc<A::Strategy>, Self>>,
+ WA<SFnPtrMap<Arc<A::Strategy>, Self>>,
+ WA<LazyJustFn<Self>>
+ )>,
+ A::Parameters;
+ args => {
+ let base = Arc::new(any_with::<A>(args));
+ prop_oneof![
+ 2 => static_map(base.clone(), Bound::Included),
+ 2 => static_map(base, Bound::Excluded),
+ 1 => LazyJust::new(|| Bound::Unbounded),
+ ]
+ }
+);
+
+lift1!(['static] Bound<A>; base => {
+ let base = Rc::new(base);
+ prop_oneof![
+ 2 => base.clone().prop_map(Bound::Included),
+ 2 => base.prop_map(Bound::Excluded),
+ 1 => LazyJustFn::new(|| Bound::Unbounded),
+ ]
+});
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ size_bounds => SizeRange,
+ vec => Vec<u8>,
+ box_slice => Box<[u8]>,
+ rc_slice => Rc<[u8]>,
+ arc_slice => Arc<[u8]>,
+ vec_deque => VecDeque<u8>,
+ linked_list => LinkedList<u8>,
+ btree_set => BTreeSet<u8>,
+ btree_map => BTreeMap<u8, u8>,
+ bound => Bound<u8>,
+ binary_heap => BinaryHeap<u8>,
+ into_iter_vec => vec::IntoIter<u8>,
+ into_iter_vec_deque => vec_deque::IntoIter<u8>,
+ into_iter_linked_list => linked_list::IntoIter<u8>,
+ into_iter_binary_heap => binary_heap::IntoIter<u8>,
+ into_iter_btree_set => btree_set::IntoIter<u8>,
+ into_iter_btree_map => btree_map::IntoIter<u8, u8>
+ );
+
+ #[cfg(feature = "std")]
+ no_panic_test!(
+ hash_set => HashSet<u8>,
+ hash_map => HashMap<u8, u8>,
+ into_iter_hash_set => hash_set::IntoIter<u8>,
+ into_iter_hash_map => hash_map::IntoIter<u8, u8>
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_alloc/hash.rs b/vendor/proptest/src/arbitrary/_alloc/hash.rs
new file mode 100644
index 000000000..8979bafca
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/hash.rs
@@ -0,0 +1,32 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::hash`.
+
+#[cfg(feature = "std")]
+use crate::std_facade::hash_map::{DefaultHasher, RandomState};
+use core::hash::{BuildHasherDefault, Hasher};
+
+// NOTE: don't impl for std::hash::SipHasher.. since deprecated!
+
+// over-constrain on purpose!
+arbitrary!([H: Default + Hasher] BuildHasherDefault<H>; Default::default());
+
+#[cfg(feature = "std")]
+lazy_just!(DefaultHasher, Default::default; RandomState, Default::default);
+
+#[cfg(test)]
+mod test {
+ #[cfg(feature = "std")]
+ no_panic_test!(
+ default_hasher => DefaultHasher,
+ random_state => RandomState,
+ build_hasher_default => BuildHasherDefault<DefaultHasher>
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_alloc/mod.rs b/vendor/proptest/src/arbitrary/_alloc/mod.rs
new file mode 100644
index 000000000..f286cab6d
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/mod.rs
@@ -0,0 +1,22 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for liballoc.
+
+#[cfg(feature = "unstable")]
+mod alloc;
+mod borrow;
+mod boxed;
+mod char;
+mod collections;
+mod hash;
+mod ops;
+mod rc;
+mod str;
+mod sync;
diff --git a/vendor/proptest/src/arbitrary/_alloc/ops.rs b/vendor/proptest/src/arbitrary/_alloc/ops.rs
new file mode 100644
index 000000000..338f52c50
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/ops.rs
@@ -0,0 +1,104 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::ops`.
+
+use crate::std_facade::Arc;
+use core::ops::*;
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+arbitrary!(RangeFull; ..);
+wrap_ctor!(RangeFrom, |a| a..);
+wrap_ctor!(RangeTo, |a| ..a);
+
+wrap_ctor!(RangeToInclusive, |a| ..=a);
+
+arbitrary!(
+ [A: PartialOrd + Arbitrary] RangeInclusive<A>,
+ SMapped<(A, A), Self>, product_type![A::Parameters, A::Parameters];
+ args => static_map(any_with::<(A, A)>(args),
+ |(a, b)| if b < a { b..=a } else { a..=b })
+);
+
+lift1!([PartialOrd] RangeInclusive<A>; base => {
+ let base = Arc::new(base);
+ (base.clone(), base).prop_map(|(a, b)| if b < a { b..=a } else { a..=b })
+});
+
+arbitrary!(
+ [A: PartialOrd + Arbitrary] Range<A>,
+ SMapped<(A, A), Self>, product_type![A::Parameters, A::Parameters];
+ args => static_map(any_with::<(A, A)>(args),
+ |(a, b)| if b < a { b..a } else { a..b })
+);
+
+lift1!([PartialOrd] Range<A>; base => {
+ let base = Arc::new(base);
+ (base.clone(), base).prop_map(|(a, b)| if b < a { b..a } else { a..b })
+});
+
+#[cfg(feature = "unstable")]
+arbitrary!(
+ [Y: Arbitrary, R: Arbitrary] GeneratorState<Y, R>,
+ TupleUnion<(WA<SMapped<Y, Self>>, WA<SMapped<R, Self>>)>,
+ product_type![Y::Parameters, R::Parameters];
+ args => {
+ let product_unpack![y, r] = args;
+ prop_oneof![
+ static_map(any_with::<Y>(y), GeneratorState::Yielded),
+ static_map(any_with::<R>(r), GeneratorState::Complete)
+ ]
+ }
+);
+
+#[cfg(feature = "unstable")]
+use core::fmt;
+
+#[cfg(feature = "unstable")]
+impl<A: fmt::Debug + 'static, B: fmt::Debug + 'static>
+ functor::ArbitraryF2<A, B> for GeneratorState<A, B>
+{
+ type Parameters = ();
+
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ _args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ prop_oneof![
+ fst.prop_map(GeneratorState::Yielded),
+ snd.prop_map(GeneratorState::Complete)
+ ]
+ .boxed()
+ }
+}
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ range_full => RangeFull,
+ range_from => RangeFrom<usize>,
+ range_to => RangeTo<usize>,
+ range => Range<usize>,
+ range_inclusive => RangeInclusive<usize>,
+ range_to_inclusive => RangeToInclusive<usize>
+ );
+
+ #[cfg(feature = "unstable")]
+ no_panic_test!(
+ generator_state => GeneratorState<u32, u64>
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_alloc/rc.rs b/vendor/proptest/src/arbitrary/_alloc/rc.rs
new file mode 100644
index 000000000..1ddb6aa00
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/rc.rs
@@ -0,0 +1,21 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::rc`.
+
+use crate::std_facade::Rc;
+
+// Weak would always give None on upgrade since there's no owned Rc.
+
+wrap_from!(Rc);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(rc => Rc<u8>);
+}
diff --git a/vendor/proptest/src/arbitrary/_alloc/str.rs b/vendor/proptest/src/arbitrary/_alloc/str.rs
new file mode 100644
index 000000000..72ba248da
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/str.rs
@@ -0,0 +1,49 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::str`.
+
+use crate::std_facade::Vec;
+use core::iter::repeat;
+use core::str::{from_utf8, ParseBoolError, Utf8Error};
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+arbitrary!(ParseBoolError; "".parse::<bool>().unwrap_err());
+
+type ELSeq = WA<Just<&'static [u8]>>;
+type ELSeqs = TupleUnion<(ELSeq, ELSeq, ELSeq, ELSeq)>;
+
+fn gen_el_seqs() -> ELSeqs {
+ prop_oneof![
+ Just(&[0xC2]), // None
+ Just(&[0x80]), // Some(1)
+ Just(&[0xE0, 0xA0, 0x00]), // Some(2)
+ Just(&[0xF0, 0x90, 0x80, 0x00]) // Some(3)
+ ]
+}
+
+arbitrary!(Utf8Error, SFnPtrMap<(StrategyFor<u16>, ELSeqs), Utf8Error>;
+ static_map((any::<u16>(), gen_el_seqs()), |(vut, elseq)| {
+ let v = repeat(b'_').take(vut as usize)
+ .chain(elseq.iter().cloned())
+ .collect::<Vec<u8>>();
+ from_utf8(&v).unwrap_err()
+ })
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ parse_bool_errror => ParseBoolError,
+ utf8_error => Utf8Error
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_alloc/sync.rs b/vendor/proptest/src/arbitrary/_alloc/sync.rs
new file mode 100644
index 000000000..ebc222581
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_alloc/sync.rs
@@ -0,0 +1,76 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::sync`.
+
+use crate::std_facade::Arc;
+use core::sync::atomic::*;
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+wrap_from!(Arc);
+
+macro_rules! atomic {
+ ($($type: ident, $base: ty);+) => {
+ $(arbitrary!($type, SMapped<$base, Self>;
+ static_map(any::<$base>(), $type::new)
+ );)+
+ };
+}
+
+// impl_wrap_gen!(AtomicPtr); // We don't have impl Arbitrary for *mut T yet.
+atomic!(AtomicBool, bool; AtomicIsize, isize; AtomicUsize, usize);
+
+#[cfg(feature = "unstable")]
+atomic!(AtomicI8, i8; AtomicI16, i16; AtomicI32, i32;
+ AtomicU8, u8; AtomicU16, u16; AtomicU32, u32);
+
+#[cfg(all(feature = "unstable", feature = "atomic64bit"))]
+atomic!(AtomicI64, i64; AtomicU64, u64);
+
+arbitrary!(Ordering,
+ TupleUnion<(WA<Just<Self>>, WA<Just<Self>>, WA<Just<Self>>,
+ WA<Just<Self>>, WA<Just<Self>>)>;
+ prop_oneof![
+ Just(Ordering::Relaxed),
+ Just(Ordering::Release),
+ Just(Ordering::Acquire),
+ Just(Ordering::AcqRel),
+ Just(Ordering::SeqCst)
+ ]
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ arc => Arc<u8>,
+ atomic_bool => AtomicBool,
+ atomic_isize => AtomicIsize,
+ atomic_usize => AtomicUsize,
+ ordering => Ordering
+ );
+
+ #[cfg(feature = "unstable")]
+ no_panic_test!(
+ atomic_i8 => AtomicI8,
+ atomic_i16 => AtomicI16,
+ atomic_i32 => AtomicI32,
+ atomic_u8 => AtomicU8,
+ atomic_u16 => AtomicU16,
+ atomic_u32 => AtomicU32
+ );
+
+ #[cfg(all(feature = "unstable", feature = "atomic64bit"))]
+ no_panic_test!(
+ atomic_i64 => AtomicI64,
+ atomic_u64 => AtomicU64
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_core/ascii.rs b/vendor/proptest/src/arbitrary/_core/ascii.rs
new file mode 100644
index 000000000..ded19289b
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/ascii.rs
@@ -0,0 +1,23 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::ascii`.
+
+use core::ascii::{escape_default, EscapeDefault};
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+
+arbitrary!(EscapeDefault, SMapped<u8, Self>;
+ static_map(any::<u8>(), escape_default));
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(escape_default => EscapeDefault);
+}
diff --git a/vendor/proptest/src/arbitrary/_core/cell.rs b/vendor/proptest/src/arbitrary/_core/cell.rs
new file mode 100644
index 000000000..c10148fb9
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/cell.rs
@@ -0,0 +1,48 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::cell`.
+
+use core::cell::{BorrowError, BorrowMutError, Cell, RefCell, UnsafeCell};
+
+wrap_from!([Copy] Cell);
+wrap_from!(RefCell);
+wrap_from!(UnsafeCell);
+
+lazy_just!(BorrowError, || {
+ // False positive:
+ #[cfg_attr(feature = "cargo-clippy", allow(let_and_return))]
+ {
+ let _rc = RefCell::new(());
+ let _bm = _rc.borrow_mut();
+ let _tb = _rc.try_borrow();
+ let ret = _rc.try_borrow().expect_err("reborrowed RefCell");
+ ret
+ }
+});
+lazy_just!(BorrowMutError, || {
+ // False positive:
+ #[cfg_attr(feature = "cargo-clippy", allow(let_and_return))]
+ {
+ let _rc = RefCell::new(());
+ let _bm = _rc.borrow_mut();
+ let _tb = _rc.try_borrow();
+ let ret = _rc.try_borrow_mut().expect_err("reborrowed RefCell");
+ ret
+ }
+});
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ cell => Cell<u8>,
+ ref_cell => RefCell<u8>,
+ unsafe_cell => UnsafeCell<u8>
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_core/cmp.rs b/vendor/proptest/src/arbitrary/_core/cmp.rs
new file mode 100644
index 000000000..75637d45c
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/cmp.rs
@@ -0,0 +1,33 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::cmp`.
+
+use core::cmp::{Ordering, Reverse};
+
+use crate::strategy::{Just, TupleUnion, WA};
+
+wrap_ctor!(Reverse, Reverse);
+
+type WAJO = WA<Just<Ordering>>;
+arbitrary!(Ordering, TupleUnion<(WAJO, WAJO, WAJO)>;
+ prop_oneof![
+ Just(Ordering::Equal),
+ Just(Ordering::Less),
+ Just(Ordering::Greater)
+ ]
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ reverse => Reverse<u8>,
+ ordering => Ordering
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_core/convert.rs b/vendor/proptest/src/arbitrary/_core/convert.rs
new file mode 100644
index 000000000..b74d78620
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/convert.rs
@@ -0,0 +1,16 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::convert`.
+
+// No sensible Arbitrary impl exists for void-like types like
+// std::convert::Infallible.
+//
+// Auto-deriving should take care to simply not include such
+// types in generation instead!
diff --git a/vendor/proptest/src/arbitrary/_core/fmt.rs b/vendor/proptest/src/arbitrary/_core/fmt.rs
new file mode 100644
index 000000000..b16b8968c
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/fmt.rs
@@ -0,0 +1,18 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::fmt`.
+
+use core::fmt::Error;
+arbitrary!(Error; Error);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(error => Error);
+}
diff --git a/vendor/proptest/src/arbitrary/_core/iter.rs b/vendor/proptest/src/arbitrary/_core/iter.rs
new file mode 100644
index 000000000..d9d5364f6
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/iter.rs
@@ -0,0 +1,188 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::iter`.
+
+use core::fmt;
+use core::iter::Fuse;
+use core::iter::*;
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+// TODO: Filter, FilterMap, FlatMap, Map, Inspect, Scan, SkipWhile
+// Might be possible with CoArbitrary
+
+wrap_ctor!(Once, once);
+wrap_ctor!([Clone] Repeat, repeat);
+wrap_ctor!([Iterator + Clone] Cycle, Iterator::cycle);
+wrap_ctor!([Iterator] Enumerate, Iterator::enumerate);
+wrap_ctor!([Iterator] Fuse, Iterator::fuse);
+wrap_ctor!([Iterator<Item = T>, T: fmt::Debug] Peekable, Iterator::peekable);
+wrap_ctor!([DoubleEndedIterator] Rev, Iterator::rev);
+
+arbitrary!(['a, T: 'a + Clone, A: Arbitrary + Iterator<Item = &'a T>]
+ Cloned<A>, SMapped<A, Self>, A::Parameters;
+ args => static_map(any_with::<A>(args), Iterator::cloned));
+
+impl<
+ T: 'static + Clone,
+ A: fmt::Debug + 'static + Iterator<Item = &'static T>,
+ > functor::ArbitraryF1<A> for Cloned<A>
+{
+ type Parameters = ();
+
+ fn lift1_with<S>(base: S, _args: Self::Parameters) -> BoxedStrategy<Self>
+ where
+ S: Strategy<Value = A> + 'static,
+ {
+ base.prop_map(Iterator::cloned).boxed()
+ }
+}
+
+arbitrary!([A] Empty<A>; empty());
+
+arbitrary!(
+ [A: Arbitrary + Iterator, B: Arbitrary + Iterator]
+ Zip<A, B>, SMapped<(A, B), Self>,
+ product_type![A::Parameters, B::Parameters];
+ args => static_map(any_with::<(A, B)>(args), |(a, b)| a.zip(b))
+);
+
+lift1!(
+ [fmt::Debug + 'static + Iterator, B: 'static + Arbitrary + Iterator]
+ Zip<B, A>,
+ B::Parameters;
+ base, args =>
+ (any_with::<B>(args), base).prop_map(|(b, a)| b.zip(a)).boxed()
+);
+
+impl<A: fmt::Debug + Iterator, B: fmt::Debug + Iterator>
+ functor::ArbitraryF2<A, B> for Zip<A, B>
+{
+ type Parameters = ();
+
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ _args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ (fst, snd).prop_map(|(a, b)| a.zip(b)).boxed()
+ }
+}
+
+arbitrary!(
+ [T,
+ A: Arbitrary + Iterator<Item = T>,
+ B: Arbitrary + Iterator<Item = T>]
+ Chain<A, B>, SMapped<(A, B), Self>,
+ product_type![A::Parameters, B::Parameters];
+ args => static_map(any_with::<(A, B)>(args), |(a, b)| a.chain(b))
+);
+
+lift1!([fmt::Debug + 'static + Iterator<Item = T>,
+ B: 'static + Arbitrary + Iterator<Item = T>,
+ T]
+ Chain<B, A>,
+ B::Parameters;
+ base, args =>
+ (any_with::<B>(args), base).prop_map(|(b, a)| b.chain(a)).boxed()
+);
+
+impl<
+ T,
+ A: fmt::Debug + Iterator<Item = T>,
+ B: fmt::Debug + Iterator<Item = T>,
+ > functor::ArbitraryF2<A, B> for Chain<A, B>
+{
+ type Parameters = ();
+
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ _args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ (fst, snd).prop_map(|(a, b)| a.chain(b)).boxed()
+ }
+}
+
+macro_rules! usize_mod {
+ ($type: ident, $mapper: ident) => {
+ arbitrary!([A: Arbitrary + Iterator] $type<A>,
+ SMapped<(A, usize), Self>, A::Parameters;
+ a => static_map(
+ any_with::<(A, usize)>(product_pack![a, ()]),
+ |(a, b)| a.$mapper(b)
+ )
+ );
+
+ lift1!([Iterator] $type<A>;
+ base => (base, any::<usize>()).prop_map(|(a, b)| a.$mapper(b))
+ );
+ };
+}
+
+usize_mod!(Skip, skip);
+usize_mod!(Take, take);
+
+#[cfg(feature = "unstable")]
+usize_mod!(StepBy, step_by);
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ use std::ops::Range;
+ const DUMMY: &'static [u8] = &[0, 1, 2, 3, 4];
+ #[derive(Debug)]
+ struct Dummy(u8);
+ arbitrary!(Dummy, SFnPtrMap<Range<u8>, Self>; static_map(0..5, Dummy));
+ impl Iterator for Dummy {
+ type Item = &'static u8;
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.0 < 5 {
+ let r = &DUMMY[self.0 as usize];
+ self.0 += 1;
+ Some(r)
+ } else {
+ None
+ }
+ }
+ }
+
+ no_panic_test!(
+ empty => Empty<u8>,
+ once => Once<u8>,
+ repeat => Repeat<u8>,
+ cloned => Cloned<super::Dummy>,
+ cycle => Cycle<Once<u8>>,
+ enumerate => Enumerate<Repeat<u8>>,
+ fuse => Fuse<Once<u8>>,
+ peekable => Peekable<Repeat<u8>>,
+ rev => Rev<::std::vec::IntoIter<u8>>,
+ zip => Zip<Repeat<u8>, Repeat<u16>>,
+ chain => Chain<Once<u8>, Once<u8>>,
+ skip => Skip<Repeat<u8>>,
+ take => Take<Repeat<u8>>
+ );
+
+ #[cfg(feature = "unstable")]
+ no_panic_test!(
+ step_by => StepBy<Repeat<u8>>
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_core/marker.rs b/vendor/proptest/src/arbitrary/_core/marker.rs
new file mode 100644
index 000000000..6558f57ab
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/marker.rs
@@ -0,0 +1,19 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::marker`.
+
+use core::marker::PhantomData;
+
+arbitrary!([T: ?Sized] PhantomData<T>; PhantomData);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(phantom_data => PhantomData<u8>);
+}
diff --git a/vendor/proptest/src/arbitrary/_core/mem.rs b/vendor/proptest/src/arbitrary/_core/mem.rs
new file mode 100644
index 000000000..700e40fbe
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/mem.rs
@@ -0,0 +1,42 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::mem`.
+
+use core::mem::*;
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+
+arbitrary!([A: Arbitrary] Discriminant<A>,
+ SMapped<A, Self>, A::Parameters;
+ args => static_map(any_with::<A>(args), |x| discriminant(&x))
+);
+
+lift1!(['static] Discriminant<A>;
+ base => static_map(base, |x| discriminant(&x))
+);
+
+// Not supported at the moment since the user won't be able to call
+// https://doc.rust-lang.org/nightly/std/mem/union.ManuallyDrop.html#method.drop
+// in any case so the use case is not great for this.
+//wrap_ctor!(ManuallyDrop);
+
+#[cfg(test)]
+mod test {
+ #[derive(Copy, Clone, Debug)]
+ struct DummyStruct;
+ arbitrary!(DummyStruct; DummyStruct);
+
+ no_panic_test!(
+ //manually_drop => ManuallyDrop<u8>, // Trivial destructor.
+ discriminant_struct => Discriminant<super::DummyStruct>,
+ discriminant_enum => Discriminant<::std::num::FpCategory>
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_core/mod.rs b/vendor/proptest/src/arbitrary/_core/mod.rs
new file mode 100644
index 000000000..5fc3742e4
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/mod.rs
@@ -0,0 +1,22 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for libcore.
+
+mod ascii;
+mod cell;
+mod cmp;
+mod convert;
+mod fmt;
+mod iter;
+mod marker;
+mod mem;
+mod num;
+mod option;
+mod result;
diff --git a/vendor/proptest/src/arbitrary/_core/num.rs b/vendor/proptest/src/arbitrary/_core/num.rs
new file mode 100644
index 000000000..f2988ecf0
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/num.rs
@@ -0,0 +1,55 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::num`.
+
+use core::num::*;
+
+use crate::strategy::*;
+
+arbitrary!(ParseFloatError; "".parse::<f32>().unwrap_err());
+arbitrary!(ParseIntError; "".parse::<u32>().unwrap_err());
+
+#[cfg(feature = "unstable")]
+arbitrary!(TryFromIntError; {
+ use core::convert::TryFrom;
+ u8::try_from(-1).unwrap_err()
+});
+
+wrap_ctor!(Wrapping, Wrapping);
+
+arbitrary!(FpCategory,
+ TupleUnion<(WA<Just<Self>>, WA<Just<Self>>, WA<Just<Self>>,
+ WA<Just<Self>>, WA<Just<Self>>)>;
+ {
+ use core::num::FpCategory::*;
+ prop_oneof![
+ Just(Nan),
+ Just(Infinite),
+ Just(Zero),
+ Just(Subnormal),
+ Just(Normal),
+ ]
+ }
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ parse_float_error => ParseFloatError,
+ parse_int_error => ParseIntError,
+ wrapping => Wrapping<u8>,
+ fp_category => FpCategory
+ );
+
+ #[cfg(feature = "unstable")]
+ no_panic_test!(
+ try_from_int_error => TryFromIntError
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_core/option.rs b/vendor/proptest/src/arbitrary/_core/option.rs
new file mode 100644
index 000000000..8b93545c8
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/option.rs
@@ -0,0 +1,57 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::option`.
+
+use crate::std_facade::string;
+use core::ops::RangeInclusive;
+use core::option as opt;
+
+use crate::arbitrary::*;
+use crate::option::{weighted, OptionStrategy, Probability};
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+arbitrary!(Probability, MapInto<RangeInclusive<f64>, Self>;
+ (0.0..=1.0).prop_map_into()
+);
+
+// These are Option<AnUninhabitedType> impls:
+
+arbitrary!(Option<string::ParseError>; None);
+#[cfg(feature = "unstable")]
+arbitrary!(Option<!>; None);
+
+arbitrary!([A: Arbitrary] opt::Option<A>, OptionStrategy<A::Strategy>,
+ product_type![Probability, A::Parameters];
+ args => {
+ let product_unpack![prob, a] = args;
+ weighted(prob, any_with::<A>(a))
+ }
+);
+
+lift1!([] Option<A>, Probability; base, prob => weighted(prob, base));
+
+arbitrary!([A: Arbitrary] opt::IntoIter<A>, SMapped<Option<A>, Self>,
+ <Option<A> as Arbitrary>::Parameters;
+ args => static_map(any_with::<Option<A>>(args), Option::into_iter));
+
+lift1!(['static] opt::IntoIter<A>, Probability;
+ base, prob => weighted(prob, base).prop_map(Option::into_iter)
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ probability => Probability,
+ option => Option<u8>,
+ option_iter => opt::IntoIter<u8>,
+ option_parse_error => Option<string::ParseError>
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_core/result.rs b/vendor/proptest/src/arbitrary/_core/result.rs
new file mode 100644
index 000000000..147a60309
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_core/result.rs
@@ -0,0 +1,108 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::result`.
+
+use crate::std_facade::string;
+use core::fmt;
+use core::result::IntoIter;
+
+use crate::arbitrary::*;
+use crate::result::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+// These are Result with uninhabited type in some variant:
+arbitrary!([A: Arbitrary] Result<A, string::ParseError>,
+ SMapped<A, Self>, A::Parameters;
+ args => static_map(any_with::<A>(args), Result::Ok)
+);
+arbitrary!([A: Arbitrary] Result<string::ParseError, A>,
+ SMapped<A, Self>, A::Parameters;
+ args => static_map(any_with::<A>(args), Result::Err)
+);
+#[cfg(feature = "unstable")]
+arbitrary!([A: Arbitrary] Result<A, !>,
+ SMapped<A, Self>, A::Parameters;
+ args => static_map(any_with::<A>(args), Result::Ok)
+);
+#[cfg(feature = "unstable")]
+arbitrary!([A: Arbitrary] Result<!, A>,
+ SMapped<A, Self>, A::Parameters;
+ args => static_map(any_with::<A>(args), Result::Err)
+);
+
+lift1!([] Result<A, string::ParseError>; Result::Ok);
+#[cfg(feature = "unstable")]
+lift1!([] Result<A, !>; Result::Ok);
+
+// We assume that `MaybeOk` is canonical as it's the most likely Strategy
+// a user wants.
+
+arbitrary!([A: Arbitrary, B: Arbitrary] Result<A, B>,
+ MaybeOk<A::Strategy, B::Strategy>,
+ product_type![Probability, A::Parameters, B::Parameters];
+ args => {
+ let product_unpack![prob, a, b] = args;
+ let (p, a, b) = (prob, any_with::<A>(a), any_with::<B>(b));
+ maybe_ok_weighted(p, a, b)
+ }
+);
+
+impl<A: fmt::Debug, E: Arbitrary> functor::ArbitraryF1<A> for Result<A, E>
+where
+ E::Strategy: 'static,
+{
+ type Parameters = product_type![Probability, E::Parameters];
+
+ fn lift1_with<AS>(base: AS, args: Self::Parameters) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ {
+ let product_unpack![prob, e] = args;
+ let (p, a, e) = (prob, base, any_with::<E>(e));
+ maybe_ok_weighted(p, a, e).boxed()
+ }
+}
+
+impl<A: fmt::Debug, B: fmt::Debug> functor::ArbitraryF2<A, B> for Result<A, B> {
+ type Parameters = Probability;
+
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ maybe_ok_weighted(args, fst, snd).boxed()
+ }
+}
+
+arbitrary!([A: Arbitrary] IntoIter<A>,
+ SMapped<Result<A, ()>, Self>,
+ <Result<A, ()> as Arbitrary>::Parameters;
+ args => static_map(any_with::<Result<A, ()>>(args), Result::into_iter)
+);
+
+lift1!(['static] IntoIter<A>, Probability; base, args => {
+ maybe_ok_weighted(args, base, Just(())).prop_map(Result::into_iter)
+});
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ result => Result<u8, u16>,
+ into_iter => IntoIter<u8>,
+ result_a_parse_error => Result<u8, ::std::string::ParseError>,
+ result_parse_error_a => Result<::std::string::ParseError, u8>
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_std/env.rs b/vendor/proptest/src/arbitrary/_std/env.rs
new file mode 100644
index 000000000..49bbc2f2f
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/env.rs
@@ -0,0 +1,141 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::env`.
+
+use std::env::*;
+use std::ffi::OsString;
+use std::iter::once;
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+// FIXME: SplitPaths when lifetimes in strategies are possible.
+
+lazy_just!(
+ Args, args;
+ ArgsOs, args_os;
+ Vars, vars;
+ VarsOs, vars_os;
+ JoinPathsError, jpe
+);
+
+#[cfg(not(target_os = "windows"))]
+fn jpe() -> JoinPathsError {
+ join_paths(once(":")).unwrap_err()
+}
+
+#[cfg(target_os = "windows")]
+fn jpe() -> JoinPathsError {
+ join_paths(once("\"")).unwrap_err()
+}
+
+// Algorithm from: https://stackoverflow.com/questions/47749164
+#[cfg(any(target_os = "windows", test))]
+fn make_utf16_invalid(buf: &mut [u16], p: usize) {
+ // Verify that length is non-empty.
+ // An empty string is always valid UTF-16.
+ assert!(buf.len() > 0);
+
+ // If first elem or previous entry is not a leading surrogate.
+ let gen_trail = 0 == p || 0xd800 != (buf[p - 1] & 0xfc00);
+ // If last element or succeeding entry is not a traililng surrogate.
+ let gen_lead = p == buf.len() - 1 || 0xdc00 != (buf[p + 1] & 0xfc00);
+ let (force_bits_mask, force_bits_value) = if gen_trail {
+ if gen_lead {
+ // Trailing or leading surrogate.
+ (0xf800, 0xd800)
+ } else {
+ // Trailing surrogate.
+ (0xfc00, 0xdc00)
+ }
+ } else {
+ // Leading surrogate.
+ // Note that `gen_lead` and `gen_trail` could both be false here if `p`
+ // lies exactly between a leading and a trailing surrogate. In this
+ // case, it doesn't matter what we do because the UTF-16 will be
+ // invalid regardless, so just always force a leading surrogate.
+ (0xfc00, 0xd800)
+ };
+ debug_assert_eq!(0, (force_bits_value & !force_bits_mask));
+ buf[p] = (buf[p] & !force_bits_mask) | force_bits_value;
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+mod var_error {
+ use super::*;
+
+ /// Generates the set of `WTF-16 \ UTF-16` and makes
+ /// an `OsString` that is not a valid String from it.
+ #[cfg(target_os = "windows")]
+ fn osstring_invalid_string() -> impl Strategy<Value = OsString> {
+ use std::os::windows::ffi::OsStringExt;
+ let size = 1..::std::u16::MAX as usize;
+ let vec_gen = crate::collection::vec(..::std::u16::MAX, size.clone());
+ (size, vec_gen).prop_map(|(p, mut sbuf)| {
+ // Not quite a uniform distribution due to clamping,
+ // but probably good enough
+ let p = ::std::cmp::min(p, sbuf.len() - 1);
+ make_utf16_invalid(&mut sbuf, p);
+ OsString::from_wide(sbuf.as_slice())
+ .into_string()
+ .unwrap_err()
+ })
+ }
+
+ #[cfg(not(target_os = "windows"))]
+ fn osstring_invalid_string() -> impl Strategy<Value = OsString> {
+ use crate::arbitrary::_std::string::not_utf8_bytes;
+ use std::os::unix::ffi::OsStringExt;
+ static_map(not_utf8_bytes(true), OsString::from_vec)
+ }
+
+ arbitrary!(VarError,
+ TupleUnion<(
+ WA<Just<Self>>,
+ WA<SFnPtrMap<BoxedStrategy<OsString>, Self>>
+ )>;
+ prop_oneof![
+ Just(VarError::NotPresent),
+ static_map(osstring_invalid_string().boxed(), VarError::NotUnicode)
+ ]
+ );
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use crate::num;
+ use crate::test_runner::Config;
+
+ no_panic_test!(
+ args => Args,
+ args_os => ArgsOs,
+ vars => Vars,
+ vars_os => VarsOs,
+ join_paths_error => JoinPathsError,
+ var_error => VarError
+ );
+
+ proptest! {
+ #![proptest_config(Config {
+ cases: 65536,
+ .. Config::default()
+ })]
+
+ #[test]
+ fn make_utf16_invalid_doesnt_panic(
+ mut buf in [num::u16::ANY; 3],
+ p in 0usize..3
+ ) {
+ make_utf16_invalid(&mut buf, p);
+ }
+ }
+}
diff --git a/vendor/proptest/src/arbitrary/_std/ffi.rs b/vendor/proptest/src/arbitrary/_std/ffi.rs
new file mode 100644
index 000000000..288b3947a
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/ffi.rs
@@ -0,0 +1,100 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::ffi`.
+
+use crate::std_facade::{Box, String, Vec};
+use std::ffi::*;
+use std::ops::RangeInclusive;
+
+use crate::arbitrary::*;
+use crate::collection::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+use super::string::not_utf8_bytes;
+
+arbitrary!(CString,
+ SFnPtrMap<VecStrategy<RangeInclusive<u8>>, Self>, SizeRange;
+ args => static_map(vec(1..=::std::u8::MAX, args + 1), |mut vec| {
+ vec.pop().unwrap();
+ // Could use: Self::from_vec_unchecked(vec) safely.
+ Self::new(vec).unwrap()
+ })
+);
+
+arbitrary!(OsString, MapInto<StrategyFor<String>, Self>,
+ <String as Arbitrary>::Parameters;
+ a => any_with::<String>(a).prop_map_into()
+);
+
+macro_rules! dst_wrapped {
+ ($($w: ident),*) => {
+ $(arbitrary!($w<CStr>, MapInto<StrategyFor<CString>, Self>, SizeRange;
+ a => any_with::<CString>(a).prop_map_into()
+ );)*
+ $(arbitrary!($w<OsStr>, MapInto<StrategyFor<OsString>, Self>,
+ <String as Arbitrary>::Parameters;
+ a => any_with::<OsString>(a).prop_map_into()
+ );)*
+ };
+}
+
+dst_wrapped!(Box);
+
+#[cfg(feature = "unstable")]
+use std::rc::Rc;
+#[cfg(feature = "unstable")]
+use std::sync::Arc;
+#[cfg(feature = "unstable")]
+dst_wrapped!(Rc, Arc);
+
+arbitrary!(FromBytesWithNulError, SMapped<Option<u16>, Self>; {
+ static_map(any::<Option<u16>>(), |opt_pos| {
+ // We make some assumptions about the internal structure of
+ // FromBytesWithNulError. However, these assumptions do not
+ // involve any non-public API.
+ if let Some(pos) = opt_pos {
+ let pos = pos as usize;
+ // Allocate pos + 2 so that we never reallocate:
+ let mut v = Vec::<u8>::with_capacity(pos + 2);
+ v.extend(::std::iter::repeat(1).take(pos));
+ v.push(0);
+ v.push(1);
+ CStr::from_bytes_with_nul(v.as_slice()).unwrap_err()
+ } else {
+ CStr::from_bytes_with_nul(b"").unwrap_err()
+ }
+ })
+});
+
+arbitrary!(IntoStringError, SFnPtrMap<BoxedStrategy<Vec<u8>>, Self>;
+ static_map(not_utf8_bytes(false).boxed(), |bytes|
+ CString::new(bytes).unwrap().into_string().unwrap_err()
+ )
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ c_string => CString,
+ os_string => OsString,
+ box_c_str => Box<CStr>,
+ box_os_str => Box<OsStr>,
+ into_string_error => IntoStringError,
+ from_bytes_with_nul => FromBytesWithNulError
+ );
+ #[cfg(feature = "unstable")]
+ no_panic_test!(
+ rc_c_str => Rc<CStr>,
+ rc_os_str => Rc<OsStr>,
+ arc_c_str => Arc<CStr>,
+ arc_os_str => Arc<OsStr>
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_std/fs.rs b/vendor/proptest/src/arbitrary/_std/fs.rs
new file mode 100644
index 000000000..66d18ca1a
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/fs.rs
@@ -0,0 +1,30 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::fs`.
+
+use std::fs::DirBuilder;
+
+use crate::arbitrary::{any, SMapped};
+use crate::strategy::statics::static_map;
+
+// TODO: other parts (figure out workable semantics).
+
+arbitrary!(DirBuilder, SMapped<bool, Self>; {
+ static_map(any::<bool>(), |recursive| {
+ let mut db = DirBuilder::new();
+ db.recursive(recursive);
+ db
+ })
+});
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(dir_builder => DirBuilder);
+}
diff --git a/vendor/proptest/src/arbitrary/_std/io.rs b/vendor/proptest/src/arbitrary/_std/io.rs
new file mode 100644
index 000000000..34ee9da32
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/io.rs
@@ -0,0 +1,164 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::io`.
+
+use crate::std_facade::String;
+#[cfg(test)]
+use crate::std_facade::Vec;
+use std::io::ErrorKind::*;
+use std::io::*;
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+// TODO: IntoInnerError
+// Consider: std::io::Initializer
+
+macro_rules! buffer {
+ ($type: ident, $bound: path) => {
+ arbitrary!(
+ [A: Arbitrary + $bound] $type<A>,
+ SMapped<(A, Option<u16>), Self>, A::Parameters;
+ args => static_map(
+ arbitrary_with(product_pack![args, Default::default()]),
+ |(inner, cap)| {
+ if let Some(cap) = cap {
+ $type::with_capacity(cap as usize, inner)
+ } else {
+ $type::new(inner)
+ }
+ }
+ )
+ );
+
+ lift1!([$bound] $type<A>; base =>
+ (base, any::<Option<u16>>()).prop_map(|(inner, cap)| {
+ if let Some(cap) = cap {
+ $type::with_capacity(cap as usize, inner)
+ } else {
+ $type::new(inner)
+ }
+ })
+ );
+ };
+}
+
+buffer!(BufReader, Read);
+buffer!(BufWriter, Write);
+buffer!(LineWriter, Write);
+
+arbitrary!(
+ [A: Read + Arbitrary, B: Read + Arbitrary] Chain<A, B>,
+ SMapped<(A, B), Self>, product_type![A::Parameters, B::Parameters];
+ args => static_map(arbitrary_with(args), |(a, b)| a.chain(b))
+);
+
+wrap_ctor!(Cursor);
+
+lazy_just!(
+ Empty, empty
+ ; Sink, sink
+ ; Stderr, stderr
+ ; Stdin, stdin
+ ; Stdout, stdout
+);
+
+wrap_ctor!([BufRead] Lines, BufRead::lines);
+
+arbitrary!(Repeat, SMapped<u8, Self>; static_map(any::<u8>(), repeat));
+
+arbitrary!(
+ [A: BufRead + Arbitrary] Split<A>, SMapped<(A, u8), Self>, A::Parameters;
+ args => static_map(
+ arbitrary_with(product_pack![args, Default::default()]),
+ |(a, b)| a.split(b)
+ )
+);
+lift1!(['static + BufRead] Split<A>;
+ base => (base, any::<u8>()).prop_map(|(a, b)| a.split(b)));
+
+arbitrary!(
+ [A: Read + Arbitrary] Take<A>, SMapped<(A, u64), Self>, A::Parameters;
+ args => static_map(
+ arbitrary_with(product_pack![args, Default::default()]),
+ |(a, b)| a.take(b)
+ )
+);
+lift1!(['static + Read] Take<A>;
+ base => (base, any::<u64>()).prop_map(|(a, b)| a.take(b)));
+
+arbitrary!(ErrorKind, Union<Just<Self>>;
+ Union::new(
+ [ NotFound
+ , PermissionDenied
+ , ConnectionRefused
+ , ConnectionReset
+ , ConnectionAborted
+ , NotConnected
+ , AddrInUse
+ , AddrNotAvailable
+ , BrokenPipe
+ , AlreadyExists
+ , WouldBlock
+ , InvalidInput
+ , InvalidData
+ , TimedOut
+ , WriteZero
+ , Interrupted
+ , Other
+ , UnexpectedEof
+ // TODO: watch this type for variant-additions.
+ ].iter().cloned().map(Just))
+);
+
+arbitrary!(
+ SeekFrom,
+ TupleUnion<(
+ WA<SMapped<u64, SeekFrom>>,
+ WA<SMapped<i64, SeekFrom>>,
+ WA<SMapped<i64, SeekFrom>>,
+ )>;
+ prop_oneof![
+ static_map(any::<u64>(), SeekFrom::Start),
+ static_map(any::<i64>(), SeekFrom::End),
+ static_map(any::<i64>(), SeekFrom::Current)
+ ]
+);
+
+arbitrary!(Error, SMapped<(ErrorKind, Option<String>), Self>;
+ static_map(arbitrary(), |(k, os)|
+ if let Some(s) = os { Error::new(k, s) } else { k.into() }
+ )
+);
+
+#[cfg(test)]
+mod test {
+
+ no_panic_test!(
+ buf_reader => BufReader<Repeat>,
+ buf_writer => BufWriter<Sink>,
+ line_writer => LineWriter<Sink>,
+ chain => Chain<Empty, BufReader<Repeat>>,
+ cursor => Cursor<Empty>,
+ empty => Empty,
+ sink => Sink,
+ stderr => Stderr,
+ stdin => Stdin,
+ stdout => Stdout,
+ lines => Lines<Empty>,
+ repeat => Repeat,
+ split => Split<Cursor<Vec<u8>>>,
+ take => Take<Repeat>,
+ error_kind => ErrorKind,
+ seek_from => SeekFrom,
+ error => Error
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_std/mod.rs b/vendor/proptest/src/arbitrary/_std/mod.rs
new file mode 100644
index 000000000..4360f5e07
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/mod.rs
@@ -0,0 +1,22 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for libstd.
+
+mod env;
+mod ffi;
+mod fs;
+mod io;
+mod net;
+mod panic;
+mod path;
+mod string;
+mod sync;
+mod thread;
+mod time;
diff --git a/vendor/proptest/src/arbitrary/_std/net.rs b/vendor/proptest/src/arbitrary/_std/net.rs
new file mode 100644
index 000000000..fcbec4d61
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/net.rs
@@ -0,0 +1,117 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::net`.
+
+use std::net::*;
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+// TODO: Can we design a workable semantic for PBT wrt. actual networking
+// connections?
+
+arbitrary!(AddrParseError; "".parse::<Ipv4Addr>().unwrap_err());
+
+arbitrary!(Ipv4Addr,
+ TupleUnion<(
+ WA<Just<Self>>,
+ WA<Just<Self>>,
+ WA<MapInto<StrategyFor<u32>, Self>>
+ )>;
+ prop_oneof![
+ 1 => Just(Self::new(0, 0, 0, 0)),
+ 4 => Just(Self::new(127, 0, 0, 1)),
+ 10 => any::<u32>().prop_map_into()
+ ]
+);
+
+arbitrary!(Ipv6Addr,
+ TupleUnion<(
+ WA<SMapped<Ipv4Addr, Self>>,
+ WA<MapInto<StrategyFor<[u16; 8]>, Self>>
+ )>;
+ prop_oneof![
+ 2 => static_map(any::<Ipv4Addr>(), |ip| ip.to_ipv6_mapped()),
+ 1 => any::<[u16; 8]>().prop_map_into()
+ ]
+);
+
+arbitrary!(SocketAddrV4, SMapped<(Ipv4Addr, u16), Self>;
+ static_map(any::<(Ipv4Addr, u16)>(), |(a, b)| Self::new(a, b))
+);
+
+arbitrary!(SocketAddrV6, SMapped<(Ipv6Addr, u16, u32, u32), Self>;
+ static_map(any::<(Ipv6Addr, u16, u32, u32)>(),
+ |(a, b, c, d)| Self::new(a, b, c, d))
+);
+
+arbitrary!(IpAddr,
+ TupleUnion<(WA<MapInto<StrategyFor<Ipv4Addr>, Self>>,
+ WA<MapInto<StrategyFor<Ipv6Addr>, Self>>)>;
+ prop_oneof![
+ any::<Ipv4Addr>().prop_map_into(),
+ any::<Ipv6Addr>().prop_map_into()
+ ]
+);
+
+arbitrary!(Shutdown,
+ TupleUnion<(WA<Just<Self>>, WA<Just<Self>>, WA<Just<Self>>)>;
+ {
+ use std::net::Shutdown::*;
+ prop_oneof![Just(Both), Just(Read), Just(Write)]
+ }
+);
+arbitrary!(SocketAddr,
+ TupleUnion<(WA<MapInto<StrategyFor<SocketAddrV4>, Self>>,
+ WA<MapInto<StrategyFor<SocketAddrV6>, Self>>)>;
+ prop_oneof![
+ any::<SocketAddrV4>().prop_map_into(),
+ any::<SocketAddrV6>().prop_map_into()
+ ]
+);
+
+#[cfg(feature = "unstable")]
+arbitrary!(Ipv6MulticastScope,
+ TupleUnion<(WA<Just<Self>>, WA<Just<Self>>, WA<Just<Self>>,
+ WA<Just<Self>>, WA<Just<Self>>, WA<Just<Self>>,
+ WA<Just<Self>>)>;
+ {
+ use std::net::Ipv6MulticastScope::*;
+ prop_oneof![
+ Just(InterfaceLocal),
+ Just(LinkLocal),
+ Just(RealmLocal),
+ Just(AdminLocal),
+ Just(SiteLocal),
+ Just(OrganizationLocal),
+ Just(Global),
+ ]
+ }
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ addr_parse_error => AddrParseError,
+ ipv4_addr => Ipv4Addr,
+ ipv6_addr => Ipv6Addr,
+ socket_addr_v4 => SocketAddrV4,
+ socket_addr_v6 => SocketAddrV6,
+ ip_addr => IpAddr,
+ shutdown => Shutdown,
+ socket_addr => SocketAddr
+ );
+
+ #[cfg(feature = "unstable")]
+ no_panic_test!(
+ ipv6_multicast_scope => Ipv6MulticastScope
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_std/panic.rs b/vendor/proptest/src/arbitrary/_std/panic.rs
new file mode 100644
index 000000000..c2bd40cd4
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/panic.rs
@@ -0,0 +1,19 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::panic`.
+
+use std::panic::AssertUnwindSafe;
+
+wrap_ctor!(AssertUnwindSafe, AssertUnwindSafe);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(assert_unwind_safe => AssertUnwindSafe<u8>);
+}
diff --git a/vendor/proptest/src/arbitrary/_std/path.rs b/vendor/proptest/src/arbitrary/_std/path.rs
new file mode 100644
index 000000000..e7d063c17
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/path.rs
@@ -0,0 +1,23 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::path`.
+
+use std::path::*;
+
+// TODO: Figure out PathBuf and then Box/Rc/Box<Path>.
+
+arbitrary!(StripPrefixError; Path::new("").strip_prefix("a").unwrap_err());
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ strip_prefix_error => StripPrefixError
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_std/string.rs b/vendor/proptest/src/arbitrary/_std/string.rs
new file mode 100644
index 000000000..fd8138a39
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/string.rs
@@ -0,0 +1,318 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::string`.
+
+use crate::std_facade::{Box, String, Vec};
+use std::iter;
+use std::rc::Rc;
+use std::slice;
+use std::sync::Arc;
+
+multiplex_alloc! {
+ alloc::string::FromUtf8Error, ::std::string::FromUtf8Error,
+ alloc::string::FromUtf16Error, ::std::string::FromUtf16Error
+}
+
+use crate::arbitrary::*;
+use crate::collection;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+use crate::string::StringParam;
+
+impl Arbitrary for String {
+ type Parameters = StringParam;
+ type Strategy = &'static str;
+
+ /// ## Panics
+ ///
+ /// This implementation panics if the input is not a valid regex proptest
+ /// can handle.
+ fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
+ args.into()
+ }
+}
+
+macro_rules! dst_wrapped {
+ ($($w: ident),*) => {
+ $(arbitrary!($w<str>, MapInto<StrategyFor<String>, Self>, StringParam;
+ a => any_with::<String>(a).prop_map_into()
+ );)*
+ };
+}
+
+dst_wrapped!(Box, Rc, Arc);
+
+lazy_just!(FromUtf16Error, || String::from_utf16(&[0xD800])
+ .unwrap_err());
+
+// This is a void-like type, it needs to be handled by the user of
+// the type by simply never constructing the variant in an enum or for
+// structs by inductively not generating the struct.
+// The same applies to ! and Infallible.
+// generator!(ParseError, || panic!());
+
+arbitrary!(FromUtf8Error, SFnPtrMap<BoxedStrategy<Vec<u8>>, Self>;
+ static_map(not_utf8_bytes(true).boxed(),
+ |bs| String::from_utf8(bs).unwrap_err())
+);
+
+/// This strategy produces sequences of bytes that are guaranteed to be illegal
+/// wrt. UTF-8 with the goal of producing a suffix of bytes in the end of
+/// an otherwise legal UTF-8 string that causes the string to be illegal.
+/// This is used primarily to generate the `Utf8Error` type and similar.
+pub(crate) fn not_utf8_bytes(
+ allow_null: bool,
+) -> impl Strategy<Value = Vec<u8>> {
+ let prefix = collection::vec(any::<char>(), ..::std::u16::MAX as usize);
+ let suffix = gen_el_bytes(allow_null);
+ (prefix, suffix).prop_map(move |(prefix_bytes, el_bytes)| {
+ let iter = prefix_bytes.iter();
+ let string: String = if allow_null {
+ iter.collect()
+ } else {
+ iter.filter(|&&x| x != '\u{0}').collect()
+ };
+ let mut bytes = string.into_bytes();
+ bytes.extend(el_bytes.into_iter());
+ bytes
+ })
+}
+
+/// Stands for "error_length" bytes and contains a suffix of bytes that
+/// will cause the whole string to become invalid UTF-8.
+/// See `gen_el_bytes` for more details.
+#[derive(Debug)]
+enum ELBytes {
+ B1([u8; 1]),
+ B2([u8; 2]),
+ B3([u8; 3]),
+ B4([u8; 4]),
+}
+
+impl<'a> IntoIterator for &'a ELBytes {
+ type Item = u8;
+ type IntoIter = iter::Cloned<slice::Iter<'a, u8>>;
+ fn into_iter(self) -> Self::IntoIter {
+ use self::ELBytes::*;
+ (match *self {
+ B1(ref a) => a.iter(),
+ B2(ref a) => a.iter(),
+ B3(ref a) => a.iter(),
+ B4(ref a) => a.iter(),
+ })
+ .cloned()
+ }
+}
+
+// By analysis of run_utf8_validation defined at:
+// https://doc.rust-lang.org/nightly/src/core/str/mod.rs.html#1429
+// we know that .error_len() \in {None, Some(1), Some(2), Some(3)}.
+// We represent this with the range [0..4) and generate a valid
+// sequence from that.
+fn gen_el_bytes(allow_null: bool) -> impl Strategy<Value = ELBytes> {
+ fn b1(a: u8) -> ELBytes {
+ ELBytes::B1([a])
+ }
+ fn b2(a: (u8, u8)) -> ELBytes {
+ ELBytes::B2([a.0, a.1])
+ }
+ fn b3(a: ((u8, u8), u8)) -> ELBytes {
+ ELBytes::B3([(a.0).0, (a.0).1, a.1])
+ }
+ fn b4(a: ((u8, u8), u8, u8)) -> ELBytes {
+ ELBytes::B4([(a.0).0, (a.0).1, a.1, a.2])
+ }
+
+ /*
+ // https://tools.ietf.org/html/rfc3629
+ static UTF8_CHAR_WIDTH: [u8; 256] = [
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
+ 0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
+ 4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
+ ];
+
+ /// Mask of the value bits of a continuation byte.
+ const CONT_MASK: u8 = 0b0011_1111;
+ /// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte.
+ const TAG_CONT_U8: u8 = 0b1000_0000;
+ */
+
+ // Continuation byte:
+ let succ_byte = 0x80u8..0xC0u8;
+
+ // Do we allow the nul byte or not?
+ let start_byte = if allow_null { 0x00u8 } else { 0x01u8 };
+
+ // Invalid continuation byte:
+ let fail_byte = prop_oneof![start_byte..0x7Fu8, 0xC1u8..];
+
+ // Matches zero in the UTF8_CHAR_WIDTH table above.
+ let byte0_w0 = prop_oneof![0x80u8..0xC0u8, 0xF5u8..];
+
+ // Start of a 3 (width) byte sequence:
+ // Leads here: https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1479
+ let byte0_w2 = 0xC2u8..0xE0u8;
+
+ // Start of a 3 (width) byte sequence:
+ // https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1484
+ // See the left column in the match.
+ let byte0_w3 = 0xE0u8..0xF0u8;
+
+ // Start of a 4 (width) byte sequence:
+ // https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1495
+ // See the left column in the match.
+ let byte0_w4 = 0xF0u8..0xF5u8;
+
+ // The 2 first (valid) bytes of a 3 (width) byte sequence:
+ // The first byte is byte0_w3. The second is the ones produced on the right.
+ let byte01_w3 = byte0_w3.clone().prop_flat_map(|x| {
+ (
+ Just(x),
+ match x {
+ 0xE0u8 => 0xA0u8..0xC0u8,
+ 0xE1u8..=0xECu8 => 0x80u8..0xC0u8,
+ 0xEDu8 => 0x80u8..0xA0u8,
+ 0xEEu8..=0xEFu8 => 0x80u8..0xA0u8,
+ _ => panic!(),
+ },
+ )
+ });
+
+ // In a 3 (width) byte sequence, an invalid second byte is chosen such that
+ // it will yield an error length of Some(1). The second byte is on
+ // the right of the match arms.
+ let byte01_w3_e1 = byte0_w3.clone().prop_flat_map(move |x| {
+ (
+ Just(x),
+ match x {
+ 0xE0u8 => prop_oneof![start_byte..0xA0u8, 0xC0u8..],
+ 0xE1u8..=0xECu8 => prop_oneof![start_byte..0x80u8, 0xC0u8..],
+ 0xEDu8 => prop_oneof![start_byte..0x80u8, 0xA0u8..],
+ 0xEEu8..=0xEFu8 => prop_oneof![start_byte..0x80u8, 0xA0u8..],
+ _ => panic!(),
+ },
+ )
+ });
+
+ // In a 4 (width) byte sequence, an invalid second byte is chosen such that
+ // it will yield an error length of Some(1). The second byte is on
+ // the right of the match arms.
+ let byte01_w4_e1 = byte0_w4.clone().prop_flat_map(move |x| {
+ (
+ Just(x),
+ match x {
+ 0xF0u8 => prop_oneof![start_byte..0x90u8, 0xA0u8..],
+ 0xF1u8..=0xF3u8 => prop_oneof![start_byte..0x80u8, 0xA0u8..],
+ 0xF4u8 => prop_oneof![start_byte..0x80u8, 0x90u8..],
+ _ => panic!(),
+ },
+ )
+ });
+
+ // The 2 first (valid) bytes of a 4 (width) byte sequence:
+ // The first byte is byte0_w4. The second is the ones produced on the right.
+ let byte01_w4 = byte0_w4.clone().prop_flat_map(|x| {
+ (
+ Just(x),
+ match x {
+ 0xF0u8 => 0x90u8..0xA0u8,
+ 0xF1u8..=0xF3u8 => 0x80u8..0xA0u8,
+ 0xF4u8 => 0x80u8..0x90u8,
+ _ => panic!(),
+ },
+ )
+ });
+
+ prop_oneof![
+ // error_len = None
+ // These are all happen when next!() fails to provide a byte.
+ prop_oneof![
+ // width = 2
+ // lacking 1 bytes:
+ static_map(byte0_w2.clone(), b1),
+ // width = 3
+ // lacking 2 bytes:
+ static_map(byte0_w3, b1),
+ // lacking 1 bytes:
+ static_map(byte01_w3.clone(), b2),
+ // width = 4
+ // lacking 3 bytes:
+ static_map(byte0_w4, b1),
+ // lacking 2 bytes:
+ static_map(byte01_w4.clone(), b2),
+ // lacking 1 byte:
+ static_map((byte01_w4.clone(), succ_byte.clone()), b3),
+ ],
+ // error_len = Some(1)
+ prop_oneof![
+ // width = 1 is not represented.
+ // width = 0
+ // path taken:
+ // https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1508
+ static_map(byte0_w0, b1),
+ // width = 2
+ // path taken:
+ // https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1480
+ static_map((byte0_w2, fail_byte.clone()), b2),
+ // width = 3
+ // path taken:
+ // https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1488
+ static_map(byte01_w3_e1, b2),
+ // width = 4
+ // path taken:
+ // https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1499
+ static_map(byte01_w4_e1, b2),
+ ],
+ // error_len = Some(2)
+ static_map(
+ prop_oneof![
+ // width = 3
+ // path taken:
+ // https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1491
+ (byte01_w3, fail_byte.clone()),
+ // width = 4
+ // path taken:
+ // https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1502
+ (byte01_w4.clone(), fail_byte.clone())
+ ],
+ b3
+ ),
+ // error_len = Some(3), width = 4
+ // path taken:
+ // https://doc.rust-lang.org/1.23.0/src/core/str/mod.rs.html#1505
+ static_map((byte01_w4, succ_byte, fail_byte), b4),
+ ]
+ .boxed()
+}
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ string => String,
+ str_box => Box<str>,
+ str_rc => Rc<str>,
+ str_arc => Arc<str>,
+ from_utf16_error => FromUtf16Error,
+ from_utf8_error => FromUtf8Error
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_std/sync.rs b/vendor/proptest/src/arbitrary/_std/sync.rs
new file mode 100644
index 000000000..e372b2544
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/sync.rs
@@ -0,0 +1,166 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::sync`.
+
+use std::fmt;
+use std::sync::mpsc::*;
+use std::sync::*;
+use std::thread;
+use std::time::Duration;
+
+use crate::arbitrary::*;
+use crate::strategy::statics::static_map;
+use crate::strategy::*;
+
+// OnceState can not escape Once::call_once_force.
+// PoisonError depends implicitly on the lifetime on MutexGuard, etc.
+// This transitively applies to TryLockError.
+
+// Not doing Weak because .upgrade() would always return None.
+
+#[cfg(not(feature = "unstable"))]
+wrap_ctor!(Mutex);
+#[cfg(feature = "unstable")]
+wrap_from!(Mutex);
+
+#[cfg(not(feature = "unstable"))]
+wrap_ctor!(RwLock);
+#[cfg(feature = "unstable")]
+wrap_from!(RwLock);
+
+arbitrary!(Barrier, SMapped<u16, Self>; // usize would be extreme!
+ static_map(any::<u16>(), |n| Barrier::new(n as usize))
+);
+
+arbitrary!(BarrierWaitResult,
+ TupleUnion<(WA<LazyJustFn<Self>>, WA<LazyJustFn<Self>>)>;
+ prop_oneof![LazyJust::new(bwr_true), LazyJust::new(bwr_false)]
+);
+
+lazy_just!(
+ Condvar, Default::default;
+ Once, Once::new
+);
+
+arbitrary!(WaitTimeoutResult, TupleUnion<(WA<Just<Self>>, WA<Just<Self>>)>;
+ prop_oneof![Just(wtr_true()), Just(wtr_false())]
+);
+
+fn bwr_true() -> BarrierWaitResult {
+ Barrier::new(1).wait()
+}
+
+fn bwr_false() -> BarrierWaitResult {
+ let barrier = Arc::new(Barrier::new(2));
+ let b2 = barrier.clone();
+ let jh = thread::spawn(move || b2.wait());
+ let bwr1 = barrier.wait();
+ let bwr2 = jh.join().unwrap();
+ if bwr1.is_leader() {
+ bwr2
+ } else {
+ bwr1
+ }
+}
+
+fn wtr_false() -> WaitTimeoutResult {
+ let cvar = Arc::new(Condvar::new());
+ let cvar2 = cvar.clone();
+ thread::spawn(move || {
+ cvar2.notify_one();
+ });
+ let lock = Mutex::new(());
+ let wt = cvar.wait_timeout(lock.lock().unwrap(), Duration::from_millis(1));
+ let (_, wtr) = wt.unwrap();
+ wtr
+}
+
+fn wtr_true() -> WaitTimeoutResult {
+ let cvar = Condvar::new();
+ let lock = Mutex::new(());
+ let wt = cvar.wait_timeout(lock.lock().unwrap(), Duration::from_millis(0));
+ let (_, wtr) = wt.unwrap();
+ wtr
+}
+
+arbitrary!(RecvError; RecvError);
+
+arbitrary!([T: Arbitrary] SendError<T>, SMapped<T, Self>, T::Parameters;
+ args => static_map(any_with::<T>(args), SendError)
+);
+
+arbitrary!(RecvTimeoutError, TupleUnion<(WA<Just<Self>>, WA<Just<Self>>)>;
+ prop_oneof![
+ Just(RecvTimeoutError::Disconnected),
+ Just(RecvTimeoutError::Timeout)
+ ]
+);
+
+arbitrary!(TryRecvError, TupleUnion<(WA<Just<Self>>, WA<Just<Self>>)>;
+ prop_oneof![
+ Just(TryRecvError::Disconnected),
+ Just(TryRecvError::Empty)
+ ]
+);
+
+arbitrary!(
+ [P: Clone + Default, T: Arbitrary<Parameters = P>] TrySendError<T>,
+ TupleUnion<(WA<SMapped<T, Self>>, WA<SMapped<T, Self>>)>, P;
+ args => prop_oneof![
+ static_map(any_with::<T>(args.clone()), TrySendError::Disconnected),
+ static_map(any_with::<T>(args), TrySendError::Full),
+ ]
+);
+
+// If only half of a pair is generated then you will get a hang-up.
+// Thus the only meaningful impls are in pairs.
+arbitrary!([A] (Sender<A>, Receiver<A>), LazyJustFn<Self>;
+ LazyJust::new(channel)
+);
+
+arbitrary!([A: fmt::Debug] (Sender<A>, IntoIter<A>), LazyJustFn<Self>;
+ LazyJust::new(|| {
+ let (rx, tx) = channel();
+ (rx, tx.into_iter())
+ })
+);
+
+arbitrary!([A] (SyncSender<A>, Receiver<A>), SMapped<u16, Self>;
+ static_map(any::<u16>(), |size| sync_channel(size as usize))
+);
+
+arbitrary!([A: fmt::Debug] (SyncSender<A>, IntoIter<A>), SMapped<u16, Self>;
+ static_map(any::<u16>(), |size| {
+ let (rx, tx) = sync_channel(size as usize);
+ (rx, tx.into_iter())
+ })
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ mutex => Mutex<u8>,
+ rw_lock => RwLock<u8>,
+ barrier => Barrier,
+ barrier_wait_result => BarrierWaitResult,
+ condvar => Condvar,
+ once => Once,
+ wait_timeout_result => WaitTimeoutResult,
+ recv_error => RecvError,
+ send_error => SendError<u8>,
+ recv_timeout_error => RecvTimeoutError,
+ try_recv_error => TryRecvError,
+ try_send_error => TrySendError<u8>,
+ rx_tx => (Sender<u8>, Receiver<u8>),
+ rx_txiter => (Sender<u8>, IntoIter<u8>),
+ syncrx_tx => (SyncSender<u8>, Receiver<u8>),
+ syncrx_txiter => (SyncSender<u8>, IntoIter<u8>)
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/_std/thread.rs b/vendor/proptest/src/arbitrary/_std/thread.rs
new file mode 100644
index 000000000..3a9b2b3fe
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/thread.rs
@@ -0,0 +1,81 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::thread`.
+
+use crate::std_facade::String;
+use std::thread::*;
+
+use crate::arbitrary::*;
+use crate::option::prob;
+use crate::strategy::statics::static_map;
+
+arbitrary!(Builder, SMapped<(Option<usize>, Option<String>), Self>; {
+ let prob = prob(0.7);
+ let args = product_pack![
+ product_pack![prob, Default::default()],
+ product_pack![prob, Default::default()]
+ ];
+ static_map(arbitrary_with(args), |(os, on)| {
+ let mut b = Builder::new();
+ b = if let Some(size) = os { b.stack_size(size) } else { b };
+ if let Some(name) = on { b.name(name) } else { b }
+ })
+});
+
+/*
+ * The usefulness of this impl is debatable - as are its semantics.
+ * Perhaps a CoArbitrary-based solution is preferable.
+
+arbitrary!([A: 'static + Send + Arbitrary<'a>] JoinHandle<A>,
+ SMapped<'a, (A, Option<()>, u8), Self>, A::Parameters;
+ args => {
+ let prob = prob(0.1);
+ let args2 = product_pack![
+ args,
+ product_pack![prob, default()],
+ default()
+ ];
+ any_with_smap(args2, |(val, panic, sleep)| thread::spawn(move || {
+ // Sleep a random amount:
+ use std::time::Duration;
+ thread::sleep(Duration::from_millis(sleep as u64));
+
+ // Randomly panic:
+ if panic.is_some() {
+ panic!("Arbitrary for JoinHandle randomly paniced!");
+ }
+
+ // Move value into thread and then just return it:
+ val
+ }))
+ }
+);
+*/
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ builder => Builder
+ );
+
+ /*
+ use super::*;
+ proptest! {
+ #[test]
+ fn join_handle_works(ref jh in any::<JoinHandle<u8>>()) {
+ use std::panic::catch_unwind;
+ catch_unwind(|| {
+ jh.join();
+ ()
+ })
+ }
+ }
+ */
+}
diff --git a/vendor/proptest/src/arbitrary/_std/time.rs b/vendor/proptest/src/arbitrary/_std/time.rs
new file mode 100644
index 000000000..7d940439a
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/_std/time.rs
@@ -0,0 +1,50 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for `std::time`.
+
+use core::ops::Range;
+use std::time::*;
+
+use crate::arbitrary::*;
+use crate::num;
+use crate::strategy::statics::{self, static_map};
+
+arbitrary!(Duration, SMapped<(u64, u32), Self>;
+ static_map(any::<(u64, u32)>(), |(a, b)| Duration::new(a, b))
+);
+
+// Instant::now() "never" returns the same Instant, so no shrinking may occur!
+arbitrary!(Instant; Self::now());
+
+arbitrary!(
+ // We can't use `any::<Duration>()` because the addition to `SystemTime`
+ // can overflow and panic. To be conservative, we only allow seconds to go
+ // to i32::MAX since a certain popular OS still uses `i32` to represent the
+ // seconds counter.
+ SystemTime, statics::Map<(num::i32::Any, Range<u32>),
+ fn ((i32, u32)) -> SystemTime>;
+ static_map((num::i32::ANY, 0..1_000_000_000u32),
+ |(sec, ns)| {
+ if sec >= 0 {
+ UNIX_EPOCH + Duration::new(sec as u64, ns)
+ } else {
+ UNIX_EPOCH - Duration::new((-(sec as i64)) as u64, ns)
+ }
+ })
+);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ duration => Duration,
+ instant => Instant,
+ system_time => SystemTime
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/arrays.rs b/vendor/proptest/src/arbitrary/arrays.rs
new file mode 100644
index 000000000..85a13321c
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/arrays.rs
@@ -0,0 +1,34 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for arrays.
+
+use crate::arbitrary::{any_with, Arbitrary};
+use crate::array::UniformArrayStrategy;
+
+impl<A: Arbitrary, const N: usize> Arbitrary for [A; N] {
+ type Parameters = A::Parameters;
+ type Strategy = UniformArrayStrategy<A::Strategy, [A; N]>;
+
+ fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
+ let base = any_with::<A>(args);
+ UniformArrayStrategy::new(base)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ array_16 => [u8; 16]
+ );
+
+ no_panic_test!(
+ array_1024 => [u8; 1024]
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/functor.rs b/vendor/proptest/src/arbitrary/functor.rs
new file mode 100644
index 000000000..153ce9949
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/functor.rs
@@ -0,0 +1,220 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Provides higher order `Arbitrary` traits.
+//! This is mainly for use by `proptest_derive`.
+//!
+//! ## Stability note
+//!
+//! This trait is mainly defined for `proptest_derive` to simplify the
+//! mechanics of deriving recursive types. If you have custom containers
+//! and want to support recursive for those, it is a good idea to implement
+//! this trait.
+//!
+//! There are clearer and terser ways that work better with
+//! inference such as using `proptest::collection::vec(..)`
+//! to achieve the same result.
+//!
+//! For these reasons, the traits here are deliberately
+//! not exported in a convenient way.
+
+use crate::std_facade::fmt;
+
+use crate::strategy::{BoxedStrategy, Strategy};
+
+/// `ArbitraryF1` lets you lift a [`Strategy`] to unary
+/// type constructors such as `Box`, `Vec`, and `Option`.
+///
+/// The trait corresponds to
+/// [Haskell QuickCheck's `Arbitrary1` type class][HaskellQC].
+///
+/// [HaskellQC]:
+/// https://hackage.haskell.org/package/QuickCheck-2.10.1/docs/Test-QuickCheck-Arbitrary.html#t:Arbitrary1
+///
+/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+pub trait ArbitraryF1<A: fmt::Debug>: fmt::Debug + Sized {
+ //==========================================================================
+ // Implementation note #1
+ //==========================================================================
+ // It might be better to do this with generic associated types by
+ // having an associated type:
+ //
+ // `type Strategy<A>: Strategy<Value = Self>;`
+ //
+ // But with this setup we will likely loose the ability to add bounds
+ // such as `Hash + Eq` on `A` which is needed for `HashSet`. We might
+ // be able to regain this ability with a ConstraintKinds feature.
+ //
+ // This alternate formulation will likely work better with type inference.
+ //
+ //==========================================================================
+ // Implementation note #2
+ //==========================================================================
+ //
+ // Until `-> impl Trait` has been stabilized, `BoxedStrategy` must be
+ // used. This incurs an unfortunate performance penalty - but since
+ // we are dealing with testing, it is better to provide slowed down and
+ // somewhat less general functionality than no functionality at all.
+ // Implementations should just use `.boxed()` in the end.
+ //==========================================================================
+
+ /// The type of parameters that [`lift1_with`] accepts for
+ /// configuration of the lifted and generated [`Strategy`]. Parameters
+ /// must implement [`Default`].
+ ///
+ /// [`lift1_with`]:
+ /// trait.ArbitraryF1.html#tymethod.lift1_with
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ /// [`Default`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ type Parameters: Default;
+
+ /// Lifts a given [`Strategy`] to a new [`Strategy`] for the (presumably)
+ /// bigger type. This is useful for lifting a `Strategy` for `SomeType`
+ /// to a container such as `Vec<SomeType>`.
+ ///
+ /// Calling this for the type `X` is the equivalent of using
+ /// [`X::lift1_with(base, Default::default())`].
+ ///
+ /// This method is defined in the trait for optimization for the
+ /// default if you want to do that. It is a logic error to not
+ /// preserve the semantics when overriding.
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`X::lift1_with(base, Default::default())`]:
+ /// trait.ArbitraryF1.html#tymethod.lift1_with
+ fn lift1<AS>(base: AS) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ {
+ Self::lift1_with(base, Self::Parameters::default())
+ }
+
+ /// Lifts a given [`Strategy`] to a new [`Strategy`] for the (presumably)
+ /// bigger type. This is useful for lifting a `Strategy` for `SomeType`
+ /// to a container such as `Vec` of `SomeType`. The composite strategy is
+ /// passed the arguments given in `args`.
+ ///
+ /// If you wish to use the [`default()`] arguments,
+ /// use [`lift1`] instead.
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`lift1`]: trait.ArbitraryF1.html#method.lift1
+ ///
+ /// [`default()`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ fn lift1_with<AS>(base: AS, args: Self::Parameters) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static;
+}
+
+/// `ArbitraryF2` lets you lift [`Strategy`] to binary
+/// type constructors such as `Result`, `HashMap`.
+///
+/// The trait corresponds to
+/// [Haskell QuickCheck's `Arbitrary2` type class][HaskellQC].
+///
+/// [HaskellQC]:
+/// https://hackage.haskell.org/package/QuickCheck-2.10.1/docs/Test-QuickCheck-Arbitrary.html#t:Arbitrary2
+///
+/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+pub trait ArbitraryF2<A: fmt::Debug, B: fmt::Debug>:
+ fmt::Debug + Sized
+{
+ /// The type of parameters that [`lift2_with`] accepts for
+ /// configuration of the lifted and generated [`Strategy`]. Parameters
+ /// must implement [`Default`].
+ ///
+ /// [`lift2_with`]: trait.ArbitraryF2.html#tymethod.lift2_with
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`Default`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ type Parameters: Default;
+
+ /// Lifts two given strategies to a new [`Strategy`] for the (presumably)
+ /// bigger type. This is useful for lifting a `Strategy` for `Type1`
+ /// and one for `Type2` to a container such as `HashMap<Type1, Type2>`.
+ ///
+ /// Calling this for the type `X` is the equivalent of using
+ /// [`X::lift2_with(base, Default::default())`].
+ ///
+ /// This method is defined in the trait for optimization for the
+ /// default if you want to do that. It is a logic error to not
+ /// preserve the semantics when overriding.
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`X::lift2_with(base, Default::default())`]:
+ /// trait.Arbitrary.html#tymethod.lift2_with
+ fn lift2<AS, BS>(fst: AS, snd: BS) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static,
+ {
+ Self::lift2_with(fst, snd, Self::Parameters::default())
+ }
+
+ /// Lifts two given strategies to a new [`Strategy`] for the (presumably)
+ /// bigger type. This is useful for lifting a `Strategy` for `Type1`
+ /// and one for `Type2` to a container such as `HashMap<Type1, Type2>`.
+ /// The composite strategy is passed the arguments given in `args`.
+ ///
+ /// If you wish to use the [`default()`] arguments,
+ /// use [`lift2`] instead.
+ ///
+ /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
+ ///
+ /// [`lift2`]: trait.ArbitraryF2.html#method.lift2
+ ///
+ /// [`default()`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ fn lift2_with<AS, BS>(
+ fst: AS,
+ snd: BS,
+ args: Self::Parameters,
+ ) -> BoxedStrategy<Self>
+ where
+ AS: Strategy<Value = A> + 'static,
+ BS: Strategy<Value = B> + 'static;
+}
+
+macro_rules! lift1 {
+ ([$($bounds : tt)*] $typ: ty, $params: ty;
+ $base: ident, $args: ident => $logic: expr) => {
+ impl<A: ::core::fmt::Debug + $($bounds)*>
+ $crate::arbitrary::functor::ArbitraryF1<A>
+ for $typ {
+ type Parameters = $params;
+
+ fn lift1_with<S>($base: S, $args: Self::Parameters)
+ -> $crate::strategy::BoxedStrategy<Self>
+ where
+ S: $crate::strategy::Strategy<Value = A> + 'static
+ {
+ $crate::strategy::Strategy::boxed($logic)
+ }
+ }
+ };
+ ([$($bounds : tt)*] $typ: ty; $base: ident => $logic: expr) => {
+ lift1!([$($bounds)*] $typ, (); $base, _args => $logic);
+ };
+ ([$($bounds : tt)*] $typ: ty; $mapper: expr) => {
+ lift1!(['static + $($bounds)*] $typ; base =>
+ $crate::strategy::Strategy::prop_map(base, $mapper));
+ };
+ ([$($bounds : tt)*] $typ: ty) => {
+ lift1!(['static + $($bounds)*] $typ; base =>
+ $crate::strategy::Strategy::prop_map_into(base));
+ };
+}
diff --git a/vendor/proptest/src/arbitrary/macros.rs b/vendor/proptest/src/arbitrary/macros.rs
new file mode 100644
index 000000000..8edf2a6ea
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/macros.rs
@@ -0,0 +1,115 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+#![cfg_attr(not(feature = "std"), allow(unused_macros))]
+
+//==============================================================================
+// Macros for quick implementing:
+//==============================================================================
+
+macro_rules! arbitrary {
+ ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty;
+ $args: ident => $logic: expr) => {
+ impl<$($bounds)*> $crate::arbitrary::Arbitrary for $typ {
+ type Parameters = $params;
+ type Strategy = $strat;
+ fn arbitrary_with($args: Self::Parameters) -> Self::Strategy {
+ $logic
+ }
+ }
+ };
+ ([$($bounds : tt)*] $typ: ty, $strat: ty; $logic: expr) => {
+ arbitrary!([$($bounds)*] $typ, $strat, (); _args => $logic);
+ };
+ ([$($bounds : tt)*] $typ: ty; $logic: expr) => {
+ arbitrary!([$($bounds)*] $typ,
+ $crate::strategy::Just<Self>, ();
+ _args => $crate::strategy::Just($logic)
+ );
+ };
+ ($typ: ty, $strat: ty, $params: ty; $args: ident => $logic: expr) => {
+ arbitrary!([] $typ, $strat, $params; $args => $logic);
+ };
+ ($typ: ty, $strat: ty; $logic: expr) => {
+ arbitrary!([] $typ, $strat; $logic);
+ };
+ ($strat: ty; $logic: expr) => {
+ arbitrary!([] $strat; $logic);
+ };
+ ($($typ: ident),*) => {
+ $(arbitrary!($typ, $typ::Any; $typ::ANY);)*
+ };
+}
+
+macro_rules! wrap_ctor {
+ ($wrap: ident) => {
+ wrap_ctor!([] $wrap);
+ };
+ ($wrap: ident, $maker: expr) => {
+ wrap_ctor!([] $wrap, $maker);
+ };
+ ([$($bound : tt)*] $wrap: ident) => {
+ wrap_ctor!([$($bound)*] $wrap, $wrap::new);
+ };
+ ([$($bound : tt)*] $wrap: ident, $maker: expr) => {
+ arbitrary!([A: $crate::arbitrary::Arbitrary + $($bound)*] $wrap<A>,
+ $crate::arbitrary::SMapped<A, Self>, A::Parameters;
+ args => $crate::strategy::statics::static_map(
+ $crate::arbitrary::any_with::<A>(args), $maker));
+
+ lift1!([$($bound)*] $wrap<A>; $maker);
+ };
+}
+
+macro_rules! wrap_from {
+ ($wrap: ident) => {
+ wrap_from!([] $wrap);
+ };
+ ([$($bound : tt)*] $wrap: ident) => {
+ arbitrary!([A: $crate::arbitrary::Arbitrary + $($bound)*] $wrap<A>,
+ $crate::strategy::MapInto<A::Strategy, Self>, A::Parameters;
+ args => $crate::strategy::Strategy::prop_map_into(
+ $crate::arbitrary::any_with::<A>(args)));
+
+ lift1!([$($bound)*] $wrap<A>);
+ };
+}
+
+macro_rules! lazy_just {
+ ($($self: ty, $fun: expr);+) => {
+ $(
+ arbitrary!($self, $crate::strategy::LazyJust<Self, fn() -> Self>;
+ $crate::strategy::LazyJust::new($fun));
+ )+
+ };
+}
+
+//==============================================================================
+// Macros for testing:
+//==============================================================================
+
+/// We are mostly interested in ensuring that generating input from our
+/// strategies is able to construct a value, therefore ensuring that
+/// no panic occurs is mostly sufficient. Shrinking for strategies that
+/// use special shrinking methods can be handled separately.
+#[cfg(test)]
+macro_rules! no_panic_test {
+ ($($module: ident => $self: ty),+) => {
+ $(
+ mod $module {
+ #[allow(unused_imports)]
+ use super::super::*;
+ proptest! {
+ #[test]
+ fn no_panic(_ in $crate::arbitrary::any::<$self>()) {}
+ }
+ }
+ )+
+ };
+}
diff --git a/vendor/proptest/src/arbitrary/mod.rs b/vendor/proptest/src/arbitrary/mod.rs
new file mode 100644
index 000000000..51ac48bae
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/mod.rs
@@ -0,0 +1,69 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Defines the `Arbitrary` trait and related free functions
+//! and type aliases.
+//!
+//! See the [`Arbitrary`] trait for more information.
+//!
+//! [`Arbitrary`]: trait.Arbitrary.html
+
+use crate::strategy::statics;
+use crate::strategy::{Map, Strategy};
+
+//==============================================================================
+// Trait and impls
+//==============================================================================
+
+mod traits;
+
+#[macro_use]
+pub mod functor;
+
+#[macro_use]
+mod macros;
+
+mod arrays;
+mod non_zero;
+mod primitives;
+mod sample;
+mod tuples;
+
+mod _core;
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+mod _alloc;
+
+#[cfg(feature = "std")]
+mod _std;
+
+pub use self::traits::*;
+
+//==============================================================================
+// SMapped + Mapped aliases to make documentation clearer.
+//==============================================================================
+
+pub(crate) type SFnPtrMap<S, O> =
+ statics::Map<S, fn(<S as Strategy>::Value) -> O>;
+
+/// A static map from a strategy of `I` to `O`.
+///
+/// # Stability
+///
+/// This is provided to make documentation more readable.
+/// Do not rely on it existing in your own code.
+pub type SMapped<I, O> = statics::Map<StrategyFor<I>, fn(I) -> O>;
+
+/// A normal map from a strategy of `I` to `O`.
+///
+/// # Stability
+///
+/// This is provided to make documentation more readable.
+/// Do not rely on it existing in your own code.
+pub type Mapped<I, O> = Map<StrategyFor<I>, fn(I) -> O>;
diff --git a/vendor/proptest/src/arbitrary/non_zero.rs b/vendor/proptest/src/arbitrary/non_zero.rs
new file mode 100644
index 000000000..55a775beb
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/non_zero.rs
@@ -0,0 +1,66 @@
+//-
+// Copyright 2018 The proptest 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.
+
+use core::convert::TryFrom;
+use core::num::{
+ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize,
+ NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
+};
+
+use crate::strategy::{FilterMap, Strategy};
+
+use super::{any, Arbitrary, StrategyFor};
+
+macro_rules! non_zero_impl {
+ ($nz:ty, $prim:ty) => {
+ impl Arbitrary for $nz {
+ type Parameters = ();
+ type Strategy =
+ FilterMap<StrategyFor<$prim>, fn($prim) -> Option<Self>>;
+
+ fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
+ any::<$prim>().prop_filter_map("must be non zero", |i| {
+ Self::try_from(i).ok()
+ })
+ }
+ }
+ };
+}
+
+non_zero_impl!(NonZeroU8, u8);
+non_zero_impl!(NonZeroU16, u16);
+non_zero_impl!(NonZeroU32, u32);
+non_zero_impl!(NonZeroU64, u64);
+non_zero_impl!(NonZeroU128, u128);
+non_zero_impl!(NonZeroUsize, usize);
+
+non_zero_impl!(NonZeroI8, i8);
+non_zero_impl!(NonZeroI16, i16);
+non_zero_impl!(NonZeroI32, i32);
+non_zero_impl!(NonZeroI64, i64);
+non_zero_impl!(NonZeroI128, i128);
+non_zero_impl!(NonZeroIsize, isize);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ u8 => core::num::NonZeroU8,
+ u16 => core::num::NonZeroU16,
+ u32 => core::num::NonZeroU32,
+ u64 => core::num::NonZeroU64,
+ u128 => core::num::NonZeroU128,
+ usize => core::num::NonZeroUsize,
+ i8 => core::num::NonZeroI8,
+ i16 => core::num::NonZeroI16,
+ i32 => core::num::NonZeroI32,
+ i64 => core::num::NonZeroI64,
+ i128 => core::num::NonZeroI128,
+ isize => core::num::NonZeroIsize
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/primitives.rs b/vendor/proptest/src/arbitrary/primitives.rs
new file mode 100644
index 000000000..cea57f4c9
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/primitives.rs
@@ -0,0 +1,46 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for primitive types.
+
+use crate::bool;
+use crate::char;
+use crate::num::{
+ f32, f64, i16, i32, i64, i8, isize, u16, u32, u64, u8, usize,
+};
+#[cfg(not(target_arch = "wasm32"))]
+use crate::num::{i128, u128};
+
+arbitrary!(bool, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
+
+#[cfg(not(target_arch = "wasm32"))]
+arbitrary!(i128, u128);
+
+// Note that for floating point types we limit the space since a lot of code
+// isn't prepared for (and is not intended to be) things like NaN and infinity.
+arbitrary!(f32, f32::Any; {
+ f32::POSITIVE | f32::NEGATIVE | f32::ZERO | f32::SUBNORMAL | f32::NORMAL
+});
+arbitrary!(f64, f64::Any; {
+ f64::POSITIVE | f64::NEGATIVE | f64::ZERO | f64::SUBNORMAL | f64::NORMAL
+});
+
+arbitrary!(char, char::CharStrategy<'static>; char::any());
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ bool => bool,
+ char => char,
+ f32 => f32, f64 => f64,
+ isize => isize, usize => usize,
+ i8 => i8, i16 => i16, i32 => i32, i64 => i64, i128 => i128,
+ u8 => u8, u16 => u16, u32 => u32, u64 => u64, u128 => u128
+ );
+}
diff --git a/vendor/proptest/src/arbitrary/sample.rs b/vendor/proptest/src/arbitrary/sample.rs
new file mode 100644
index 000000000..81758213d
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/sample.rs
@@ -0,0 +1,31 @@
+//-
+// Copyright 2018 The proptest 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.
+
+use crate::arbitrary::Arbitrary;
+use crate::sample::{Index, IndexStrategy, Selector, SelectorStrategy};
+
+impl Arbitrary for Index {
+ type Parameters = ();
+
+ type Strategy = IndexStrategy;
+
+ fn arbitrary_with(_: ()) -> IndexStrategy {
+ IndexStrategy::new()
+ }
+}
+
+impl Arbitrary for Selector {
+ type Parameters = ();
+
+ type Strategy = SelectorStrategy;
+
+ fn arbitrary_with(_: ()) -> SelectorStrategy {
+ SelectorStrategy::new()
+ }
+}
diff --git a/vendor/proptest/src/arbitrary/traits.rs b/vendor/proptest/src/arbitrary/traits.rs
new file mode 100644
index 000000000..83f021425
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/traits.rs
@@ -0,0 +1,295 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+use core::fmt;
+
+use crate::strategy::Strategy;
+
+//==============================================================================
+// Arbitrary trait
+//==============================================================================
+
+/// Arbitrary determines a canonical [`Strategy`] for the implementing type.
+///
+/// It provides the method `arbitrary_with` which generates a `Strategy` for
+/// producing arbitrary values of the implementing type *(`Self`)*. In general,
+/// these strategies will produce the entire set of values possible for the
+/// type, up to some size limitation or constraints set by their parameters.
+/// When this is not desired, strategies to produce the desired values can be
+/// built by combining [`Strategy`]s as described in the crate documentation.
+///
+/// This trait analogous to
+/// [Haskell QuickCheck's implementation of `Arbitrary`][HaskellQC].
+/// In this interpretation of `Arbitrary`, `Strategy` is the equivalent of
+/// the `Gen` monad. Unlike in QuickCheck, `Arbitrary` is not a core component;
+/// types do not need to implement `Arbitrary` unless one wants to use
+/// [`any`](fn.any.html) or other free functions in this module.
+///
+/// `Arbitrary` currently only works for types which represent owned data as
+/// opposed to borrowed data. This is a fundamental restriction of `proptest`
+/// which may be lifted in the future as the [generic associated types (GAT)]
+/// feature of Rust is implemented and stabilized.
+///
+/// [generic associated types (GAT)]: https://github.com/rust-lang/rust/issues/44265
+///
+/// [`Strategy`]: ../strategy/trait.Strategy.html
+///
+/// [HaskellQC]:
+/// https://hackage.haskell.org/package/QuickCheck/docs/Test-QuickCheck-Arbitrary.html
+pub trait Arbitrary: Sized + fmt::Debug {
+ /// The type of parameters that [`arbitrary_with`] accepts for configuration
+ /// of the generated [`Strategy`]. Parameters must implement [`Default`].
+ ///
+ /// [`arbitrary_with`]: trait.Arbitrary.html#tymethod.arbitrary_with
+ ///
+ /// [`Strategy`]: ../strategy/trait.Strategy.html
+ /// [`Default`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ type Parameters: Default;
+
+ /// Generates a [`Strategy`] for producing arbitrary values
+ /// of type the implementing type (`Self`).
+ ///
+ /// Calling this for the type `X` is the equivalent of using
+ /// [`X::arbitrary_with(Default::default())`].
+ ///
+ /// This method is defined in the trait for optimization for the
+ /// default if you want to do that. It is a logic error to not
+ /// preserve the semantics when overriding.
+ ///
+ /// [`Strategy`]: ../strategy/trait.Strategy.html
+ /// [`X::arbitrary_with(Default::default())`]:
+ /// trait.Arbitrary.html#tymethod.arbitrary_with
+ fn arbitrary() -> Self::Strategy {
+ Self::arbitrary_with(Default::default())
+ }
+
+ /// Generates a [`Strategy`] for producing arbitrary values of type the
+ /// implementing type (`Self`). The strategy is passed the arguments given
+ /// in args.
+ ///
+ /// If you wish to use the [`default()`] arguments,
+ /// use [`arbitrary`] instead.
+ ///
+ /// [`Strategy`]: ../strategy/trait.Strategy.html
+ ///
+ /// [`arbitrary`]: trait.Arbitrary.html#method.arbitrary
+ ///
+ /// [`default()`]:
+ /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
+ fn arbitrary_with(args: Self::Parameters) -> Self::Strategy;
+
+ /// The type of [`Strategy`] used to generate values of type `Self`.
+ ///
+ /// [`Strategy`]: ../strategy/trait.Strategy.html
+ type Strategy: Strategy<Value = Self>;
+}
+
+//==============================================================================
+// Type aliases for associated types
+//==============================================================================
+
+/// `StrategyFor` allows you to mention the type of [`Strategy`] for the input
+/// type `A` without directly using associated types or without resorting to
+/// existential types. This way, if implementation of [`Arbitrary`] changes,
+/// your tests should not break. This can be especially beneficial when the
+/// type of `Strategy` that you are dealing with is very long in name
+/// (the case with generics).
+///
+/// [`Arbitrary`]: trait.Arbitrary.html
+/// [`Strategy`]: ../strategy/trait.Strategy.html
+pub type StrategyFor<A> = <A as Arbitrary>::Strategy;
+
+/// `ParamsFor` allows you to mention the type of [`Parameters`] for the input
+/// type `A` without directly using associated types or without resorting to
+/// existential types. This way, if implementation of [`Arbitrary`] changes,
+/// your tests should not break.
+///
+/// [`Parameters`]: trait.Arbitrary.html#associatedtype.Parameters
+/// [`Arbitrary`]: trait.Arbitrary.html
+/// [`Strategy`]: ../strategy/trait.Strategy.html
+pub type ParamsFor<A> = <A as Arbitrary>::Parameters;
+
+//==============================================================================
+// Free functions that people should use
+//==============================================================================
+
+/// Generates a [`Strategy`] producing [`Arbitrary`][trait Arbitrary] values of
+/// `A`. Unlike [`arbitrary`][fn arbitrary], it should be used for being
+/// explicit on what `A` is. For clarity, this may be a good idea.
+///
+/// Use this version instead of [`arbitrary`][fn arbitrary] if you want to be
+/// clear which type you want to generate a `Strategy` for, or if you don't
+/// have an anchoring type for type inference to work with.
+///
+/// If you want to customize how the strategy is generated, use
+/// [`any_with::<A>(args)`] where `args` are any arguments accepted by
+/// the `Arbitrary` impl in question.
+///
+/// # Example
+///
+/// The function can be used as:
+///
+/// ```rust
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// fn reverse_reverse_is_identity(ref vec in any::<Vec<u32>>()) {
+/// let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
+/// prop_assert_eq!(vec, &vec2);
+/// }
+/// }
+///
+/// fn main() {
+/// reverse_reverse_is_identity();
+/// }
+/// ```
+///
+/// [`any_with::<A>(args)`]: fn.any_with.html
+/// [fn arbitrary]: fn.arbitrary.html
+/// [trait Arbitrary]: trait.Arbitrary.html
+/// [`Strategy`]: ../strategy/trait.Strategy.html
+#[must_use = "strategies do nothing unless used"]
+pub fn any<A: Arbitrary>() -> StrategyFor<A> {
+ // ^-- We use a shorter name so that turbofish becomes more ergonomic.
+ A::arbitrary()
+}
+
+/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
+/// given configuration arguments passed in `args`. Unlike [`arbitrary_with`],
+/// it should be used for being explicit on what `A` is.
+/// For clarity, this may be a good idea.
+///
+/// Use this version instead of [`arbitrary_with`] if you want to be clear which
+/// type you want to generate a `Strategy` for, or if you don't have an anchoring
+/// type for type inference to work with.
+///
+/// If you don't want to specify any arguments and instead use the default
+/// behavior, you should use [`any::<A>()`].
+///
+/// # Example
+///
+/// The function can be used as:
+///
+/// ```rust
+/// use proptest::prelude::*;
+/// use proptest::collection::size_range;
+///
+/// proptest! {
+/// fn reverse_reverse_is_identity
+/// (ref vec in any_with::<Vec<u32>>(size_range(1000).lift()))
+/// {
+/// let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
+/// prop_assert_eq!(vec, &vec2);
+/// }
+/// }
+///
+/// fn main() {
+/// reverse_reverse_is_identity();
+/// }
+/// ```
+///
+/// [`any::<A>()`]: fn.any.html
+/// [`arbitrary_with`]: fn.arbitrary_with.html
+/// [`Arbitrary`]: trait.Arbitrary.html
+/// [`Strategy`]: ../strategy/trait.Strategy.html
+#[must_use = "strategies do nothing unless used"]
+pub fn any_with<A: Arbitrary>(args: ParamsFor<A>) -> StrategyFor<A> {
+ // ^-- We use a shorter name so that turbofish becomes more ergonomic.
+ A::arbitrary_with(args)
+}
+
+/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A`.
+/// Works better with type inference than [`any::<A>()`].
+///
+/// With this version, you shouldn't need to specify any of the (many) type
+/// parameters explicitly. This can have a positive effect on type inference.
+/// However, if you want specify `A`, you should use [`any::<A>()`] instead.
+///
+/// For clarity, it is often a good idea to specify the type generated, and
+/// so using [`any::<A>()`] can be a good idea.
+///
+/// If you want to customize how the strategy is generated, use
+/// [`arbitrary_with(args)`] where `args` is of type
+/// `<A as Arbitrary>::Parameters`.
+///
+/// # Example
+///
+/// The function can be used as:
+///
+/// ```rust
+/// extern crate proptest;
+/// use proptest::arbitrary::{arbitrary, StrategyFor};
+///
+/// fn gen_vec_usize() -> StrategyFor<Vec<usize>> {
+/// arbitrary()
+/// }
+///
+/// # fn main() {}
+/// ```
+///
+/// [`arbitrary_with(args)`]: fn.arbitrary_with.html
+/// [`any::<A>()`]: fn.any.html
+/// [`Arbitrary`]: trait.Arbitrary.html
+/// [`Strategy`]: ../strategy/trait.Strategy.html
+#[must_use = "strategies do nothing unless used"]
+pub fn arbitrary<A, S>() -> S
+where
+ // The backlinking here cause an injection which helps type inference.
+ S: Strategy<Value = A>,
+ A: Arbitrary<Strategy = S>,
+{
+ A::arbitrary()
+}
+
+/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
+/// given configuration arguments passed in `args`.
+/// Works better with type inference than [`any_with::<A>(args)`].
+///
+/// With this version, you shouldn't need to specify any of the (many) type
+/// parameters explicitly. This can have a positive effect on type inference.
+/// However, if you want specify `A`, you should use
+/// [`any_with::<A>(args)`] instead.
+///
+/// For clarity, it is often a good idea to specify the type generated, and
+/// so using [`any_with::<A>(args)`] can be a good idea.
+///
+/// If you don't want to specify any arguments and instead use the default
+/// behavior, you should use [`arbitrary()`].
+///
+/// # Example
+///
+/// The function can be used as:
+///
+/// ```rust
+/// extern crate proptest;
+/// use proptest::arbitrary::{arbitrary_with, StrategyFor};
+/// use proptest::collection::size_range;
+///
+/// fn gen_vec_10_u32() -> StrategyFor<Vec<u32>> {
+/// arbitrary_with(size_range(10).lift())
+/// }
+///
+/// # fn main() {}
+/// ```
+///
+/// [`any_with::<A>(args)`]: fn.any_with.html
+/// [`arbitrary()`]: fn.arbitrary.html
+/// [`Arbitrary`]: trait.Arbitrary.html
+/// [`Strategy`]: ../strategy/trait.Strategy.html
+#[must_use = "strategies do nothing unless used"]
+pub fn arbitrary_with<A, S, P>(args: P) -> S
+where
+ P: Default,
+ // The backlinking here cause an injection which helps type inference.
+ S: Strategy<Value = A>,
+ A: Arbitrary<Strategy = S, Parameters = P>,
+{
+ A::arbitrary_with(args)
+}
diff --git a/vendor/proptest/src/arbitrary/tuples.rs b/vendor/proptest/src/arbitrary/tuples.rs
new file mode 100644
index 000000000..5df3088a3
--- /dev/null
+++ b/vendor/proptest/src/arbitrary/tuples.rs
@@ -0,0 +1,45 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Arbitrary implementations for tuples.
+
+use crate::arbitrary::{any_with, Arbitrary};
+
+macro_rules! impl_tuple {
+ ($($typ: ident),*) => {
+ impl<$($typ : Arbitrary),*> Arbitrary for ($($typ,)*) {
+ type Parameters = product_type![$($typ::Parameters,)*];
+ type Strategy = ($($typ::Strategy,)*);
+ fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
+ #[allow(non_snake_case)]
+ let product_unpack![$($typ),*] = args;
+ ($(any_with::<$typ>($typ)),*,)
+ }
+ }
+ };
+}
+
+arbitrary!((); ());
+impl_tuple!(T0);
+impl_tuple!(T0, T1);
+impl_tuple!(T0, T1, T2);
+impl_tuple!(T0, T1, T2, T3);
+impl_tuple!(T0, T1, T2, T3, T4);
+impl_tuple!(T0, T1, T2, T3, T4, T5);
+impl_tuple!(T0, T1, T2, T3, T4, T5, T6);
+impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7);
+impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
+impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
+
+#[cfg(test)]
+mod test {
+ no_panic_test!(
+ tuple_n10 => ((), bool, u8, u16, u32, u64, i8, i16, i32, i64)
+ );
+}
diff --git a/vendor/proptest/src/array.rs b/vendor/proptest/src/array.rs
new file mode 100644
index 000000000..2edce4608
--- /dev/null
+++ b/vendor/proptest/src/array.rs
@@ -0,0 +1,264 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+//! Support for strategies producing fixed-length arrays.
+//!
+//! An array of strategies (but only length 1 to 32 for now) is itself a
+//! strategy which generates arrays of that size drawing elements from the
+//! corresponding input strategies.
+//!
+//! See also [`UniformArrayStrategy`](struct.UniformArrayStrategy.html) for
+//! easily making a strategy for an array drawn from one strategy.
+//!
+//! General implementations are available for sizes 1 through 32.
+
+use core::marker::PhantomData;
+
+use crate::strategy::*;
+use crate::test_runner::*;
+
+/// A `Strategy` which generates fixed-size arrays containing values drawn from
+/// an inner strategy.
+///
+/// `T` must be an array type of length 1 to 32 whose values are produced by
+/// strategy `S`. Instances of this type are normally created by the various
+/// `uniformXX` functions in this module.
+///
+/// This is mainly useful when the inner strategy is not `Copy`, precluding
+/// expressing the strategy as `[myStrategy; 32]`, for example.
+///
+/// ## Example
+///
+/// ```
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// #[test]
+/// fn test_something(a in prop::array::uniform32(1u32..)) {
+/// let unexpected = [0u32;32];
+/// // `a` is also a [u32;32], so we can compare them directly
+/// assert_ne!(unexpected, a);
+/// }
+/// }
+/// # fn main() { }
+/// ```
+#[must_use = "strategies do nothing unless used"]
+#[derive(Clone, Copy, Debug)]
+pub struct UniformArrayStrategy<S, T> {
+ strategy: S,
+ _marker: PhantomData<T>,
+}
+
+impl<S, T> UniformArrayStrategy<S, T> {
+ /// Directly create a `UniformArrayStrategy`.
+ ///
+ /// This is only intended for advanced use, since the only way to specify
+ /// the array size is with the turbofish operator and explicitly naming the
+ /// type of the values in the array and the strategy itself.
+ ///
+ /// Prefer the `uniformXX` functions at module-level unless something
+ /// precludes their use.
+ pub fn new(strategy: S) -> Self {
+ UniformArrayStrategy {
+ strategy,
+ _marker: PhantomData,
+ }
+ }
+}
+
+/// A `ValueTree` operating over a fixed-size array.
+#[derive(Clone, Copy, Debug)]
+pub struct ArrayValueTree<T> {
+ tree: T,
+ shrinker: usize,
+ last_shrinker: Option<usize>,
+}
+
+/// Create a strategy to generate fixed-length arrays.
+///
+/// All values within the new strategy are generated using the given
+/// strategy.
+///
+/// See [`UniformArrayStrategy`](struct.UniformArrayStrategy.html) for
+/// example usage.
+pub fn uniform<S: Strategy, const N: usize>(
+ strategy: S,
+) -> UniformArrayStrategy<S, [S::Value; N]> {
+ UniformArrayStrategy {
+ strategy,
+ _marker: PhantomData,
+ }
+}
+
+macro_rules! small_array {
+ ($n:tt $uni:ident) => {
+ /// Create a strategy to generate fixed-length arrays.
+ ///
+ /// All values within the new strategy are generated using the given
+ /// strategy. The length of the array corresponds to the suffix of the
+ /// name of this function.
+ ///
+ /// See [`UniformArrayStrategy`](struct.UniformArrayStrategy.html) for
+ /// example usage.
+ pub fn $uni<S: Strategy>(
+ strategy: S,
+ ) -> UniformArrayStrategy<S, [S::Value; $n]> {
+ UniformArrayStrategy {
+ strategy,
+ _marker: PhantomData,
+ }
+ }
+ };
+}
+
+impl<S: Strategy, const N: usize> Strategy for [S; N] {
+ type Tree = ArrayValueTree<[S::Tree; N]>;
+ type Value = [S::Value; N];
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(ArrayValueTree {
+ tree: unarray::build_array_result(|i| self[i].new_tree(runner))?,
+ shrinker: 0,
+ last_shrinker: None,
+ })
+ }
+}
+impl<S: Strategy, const N: usize> Strategy
+ for UniformArrayStrategy<S, [S::Value; N]>
+{
+ type Tree = ArrayValueTree<[S::Tree; N]>;
+ type Value = [S::Value; N];
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(ArrayValueTree {
+ tree: unarray::build_array_result(|_| {
+ self.strategy.new_tree(runner)
+ })?,
+ shrinker: 0,
+ last_shrinker: None,
+ })
+ }
+}
+impl<T: ValueTree, const N: usize> ValueTree for ArrayValueTree<[T; N]> {
+ type Value = [T::Value; N];
+
+ fn current(&self) -> [T::Value; N] {
+ unarray::build_array(|i| self.tree[i].current())
+ }
+
+ fn simplify(&mut self) -> bool {
+ while self.shrinker < N {
+ if self.tree[self.shrinker].simplify() {
+ self.last_shrinker = Some(self.shrinker);
+ return true;
+ } else {
+ self.shrinker += 1;
+ }
+ }
+ false
+ }
+
+ fn complicate(&mut self) -> bool {
+ if let Some(shrinker) = self.last_shrinker {
+ self.shrinker = shrinker;
+ if self.tree[shrinker].complicate() {
+ true
+ } else {
+ self.last_shrinker = None;
+ false
+ }
+ } else {
+ false
+ }
+ }
+}
+
+small_array!(1 uniform1);
+small_array!(2 uniform2);
+small_array!(3 uniform3);
+small_array!(4 uniform4);
+small_array!(5 uniform5);
+small_array!(6 uniform6);
+small_array!(7 uniform7);
+small_array!(8 uniform8);
+small_array!(9 uniform9);
+small_array!(10 uniform10);
+small_array!(11 uniform11);
+small_array!(12 uniform12);
+small_array!(13 uniform13);
+small_array!(14 uniform14);
+small_array!(15 uniform15);
+small_array!(16 uniform16);
+small_array!(17 uniform17);
+small_array!(18 uniform18);
+small_array!(19 uniform19);
+small_array!(20 uniform20);
+small_array!(21 uniform21);
+small_array!(22 uniform22);
+small_array!(23 uniform23);
+small_array!(24 uniform24);
+small_array!(25 uniform25);
+small_array!(26 uniform26);
+small_array!(27 uniform27);
+small_array!(28 uniform28);
+small_array!(29 uniform29);
+small_array!(30 uniform30);
+small_array!(31 uniform31);
+small_array!(32 uniform32);
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn shrinks_fully_ltr() {
+ fn pass(a: [i32; 2]) -> bool {
+ a[0] * a[1] <= 9
+ }
+
+ let input = [0..32, 0..32];
+ let mut runner = TestRunner::deterministic();
+
+ let mut cases_tested = 0;
+ for _ in 0..256 {
+ // Find a failing test case
+ let mut case = input.new_tree(&mut runner).unwrap();
+ if pass(case.current()) {
+ continue;
+ }
+
+ loop {
+ if pass(case.current()) {
+ if !case.complicate() {
+ break;
+ }
+ } else {
+ if !case.simplify() {
+ break;
+ }
+ }
+ }
+
+ let last = case.current();
+ assert!(!pass(last));
+ // Maximally shrunken
+ assert!(pass([last[0] - 1, last[1]]));
+ assert!(pass([last[0], last[1] - 1]));
+
+ cases_tested += 1;
+ }
+
+ assert!(cases_tested > 32, "Didn't find enough test cases");
+ }
+
+ #[test]
+ fn test_sanity() {
+ check_strategy_sanity([(0i32..1000), (1i32..1000)], None);
+ }
+}
diff --git a/vendor/proptest/src/bits.rs b/vendor/proptest/src/bits.rs
new file mode 100644
index 000000000..49de83085
--- /dev/null
+++ b/vendor/proptest/src/bits.rs
@@ -0,0 +1,677 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Strategies for working with bit sets.
+//!
+//! Besides `BitSet` itself, this also defines strategies for all the primitive
+//! integer types. These strategies are appropriate for integers which are used
+//! as bit flags, etc; e.g., where the most reasonable simplification of `64`
+//! is `0` (clearing one bit) and not `63` (clearing one bit but setting 6
+//! others). For integers treated as numeric values, see the corresponding
+//! modules of the `num` module instead.
+
+use crate::std_facade::{fmt, Vec};
+use core::marker::PhantomData;
+use core::mem;
+
+#[cfg(feature = "bit-set")]
+use bit_set::BitSet;
+use rand::{self, seq::IteratorRandom, Rng};
+
+use crate::collection::SizeRange;
+use crate::num::sample_uniform_incl;
+use crate::strategy::*;
+use crate::test_runner::*;
+
+/// Trait for types which can be handled with `BitSetStrategy`.
+#[cfg_attr(feature = "cargo-clippy", allow(len_without_is_empty))]
+pub trait BitSetLike: Clone + fmt::Debug {
+ /// Create a new value of `Self` with space for up to `max` bits, all
+ /// initialised to zero.
+ fn new_bitset(max: usize) -> Self;
+ /// Return an upper bound on the greatest bit set _plus one_.
+ fn len(&self) -> usize;
+ /// Test whether the given bit is set.
+ fn test(&self, ix: usize) -> bool;
+ /// Set the given bit.
+ fn set(&mut self, ix: usize);
+ /// Clear the given bit.
+ fn clear(&mut self, ix: usize);
+ /// Return the number of bits set.
+ ///
+ /// This has a default for backwards compatibility, which simply does a
+ /// linear scan through the bits. Implementations are strongly encouraged
+ /// to override this.
+ fn count(&self) -> usize {
+ let mut n = 0;
+ for i in 0..self.len() {
+ if self.test(i) {
+ n += 1;
+ }
+ }
+ n
+ }
+}
+
+macro_rules! int_bitset {
+ ($typ:ty) => {
+ impl BitSetLike for $typ {
+ fn new_bitset(_: usize) -> Self {
+ 0
+ }
+ fn len(&self) -> usize {
+ mem::size_of::<$typ>() * 8
+ }
+ fn test(&self, ix: usize) -> bool {
+ 0 != (*self & ((1 as $typ) << ix))
+ }
+ fn set(&mut self, ix: usize) {
+ *self |= (1 as $typ) << ix;
+ }
+ fn clear(&mut self, ix: usize) {
+ *self &= !((1 as $typ) << ix);
+ }
+ fn count(&self) -> usize {
+ self.count_ones() as usize
+ }
+ }
+ };
+}
+int_bitset!(u8);
+int_bitset!(u16);
+int_bitset!(u32);
+int_bitset!(u64);
+int_bitset!(usize);
+int_bitset!(i8);
+int_bitset!(i16);
+int_bitset!(i32);
+int_bitset!(i64);
+int_bitset!(isize);
+
+#[cfg(feature = "bit-set")]
+impl BitSetLike for BitSet {
+ fn new_bitset(max: usize) -> Self {
+ BitSet::with_capacity(max)
+ }
+
+ fn len(&self) -> usize {
+ self.capacity()
+ }
+
+ fn test(&self, bit: usize) -> bool {
+ self.contains(bit)
+ }
+
+ fn set(&mut self, bit: usize) {
+ self.insert(bit);
+ }
+
+ fn clear(&mut self, bit: usize) {
+ self.remove(bit);
+ }
+
+ fn count(&self) -> usize {
+ self.len()
+ }
+}
+
+impl BitSetLike for Vec<bool> {
+ fn new_bitset(max: usize) -> Self {
+ vec![false; max]
+ }
+
+ fn len(&self) -> usize {
+ self.len()
+ }
+
+ fn test(&self, bit: usize) -> bool {
+ if bit >= self.len() {
+ false
+ } else {
+ self[bit]
+ }
+ }
+
+ fn set(&mut self, bit: usize) {
+ if bit >= self.len() {
+ self.resize(bit + 1, false);
+ }
+
+ self[bit] = true;
+ }
+
+ fn clear(&mut self, bit: usize) {
+ if bit < self.len() {
+ self[bit] = false;
+ }
+ }
+
+ fn count(&self) -> usize {
+ self.iter().filter(|&&b| b).count()
+ }
+}
+
+/// Generates values as a set of bits between the two bounds.
+///
+/// Values are generated by uniformly setting individual bits to 0
+/// or 1 between the bounds. Shrinking iteratively clears bits.
+#[must_use = "strategies do nothing unless used"]
+#[derive(Clone, Copy, Debug)]
+pub struct BitSetStrategy<T: BitSetLike> {
+ min: usize,
+ max: usize,
+ mask: Option<T>,
+}
+
+impl<T: BitSetLike> BitSetStrategy<T> {
+ /// Create a strategy which generates values where bits between `min`
+ /// (inclusive) and `max` (exclusive) may be set.
+ ///
+ /// Due to the generics, the functions in the typed submodules are usually
+ /// preferable to calling this directly.
+ pub fn new(min: usize, max: usize) -> Self {
+ BitSetStrategy {
+ min,
+ max,
+ mask: None,
+ }
+ }
+
+ /// Create a strategy which generates values where any bits set (and only
+ /// those bits) in `mask` may be set.
+ pub fn masked(mask: T) -> Self {
+ BitSetStrategy {
+ min: 0,
+ max: mask.len(),
+ mask: Some(mask),
+ }
+ }
+}
+
+impl<T: BitSetLike> Strategy for BitSetStrategy<T> {
+ type Tree = BitSetValueTree<T>;
+ type Value = T;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let mut inner = T::new_bitset(self.max);
+ for bit in self.min..self.max {
+ if self.mask.as_ref().map_or(true, |mask| mask.test(bit))
+ && runner.rng().gen()
+ {
+ inner.set(bit);
+ }
+ }
+
+ Ok(BitSetValueTree {
+ inner,
+ shrink: self.min,
+ prev_shrink: None,
+ min_count: 0,
+ })
+ }
+}
+
+/// Generates bit sets with a particular number of bits set.
+///
+/// Specifically, this strategy is given both a size range and a bit range. To
+/// produce a new value, it selects a size, then uniformly selects that many
+/// bits from within the bit range.
+///
+/// Shrinking happens as with [`BitSetStrategy`](struct.BitSetStrategy.html).
+#[derive(Clone, Debug)]
+#[must_use = "strategies do nothing unless used"]
+pub struct SampledBitSetStrategy<T: BitSetLike> {
+ size: SizeRange,
+ bits: SizeRange,
+ _marker: PhantomData<T>,
+}
+
+impl<T: BitSetLike> SampledBitSetStrategy<T> {
+ /// Create a strategy which generates values where bits within the bounds
+ /// given by `bits` may be set. The number of bits that are set is chosen
+ /// to be in the range given by `size`.
+ ///
+ /// Due to the generics, the functions in the typed submodules are usually
+ /// preferable to calling this directly.
+ ///
+ /// ## Panics
+ ///
+ /// Panics if `size` includes a value that is greater than the number of
+ /// bits in `bits`.
+ pub fn new(size: impl Into<SizeRange>, bits: impl Into<SizeRange>) -> Self {
+ let size = size.into();
+ let bits = bits.into();
+ size.assert_nonempty();
+
+ let available_bits = bits.end_excl() - bits.start();
+ assert!(
+ size.end_excl() <= available_bits + 1,
+ "Illegal SampledBitSetStrategy: have {} bits available, \
+ but requested size is {}..{}",
+ available_bits,
+ size.start(),
+ size.end_excl()
+ );
+ SampledBitSetStrategy {
+ size,
+ bits,
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl<T: BitSetLike> Strategy for SampledBitSetStrategy<T> {
+ type Tree = BitSetValueTree<T>;
+ type Value = T;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let mut bits = T::new_bitset(self.bits.end_excl());
+ let count = sample_uniform_incl(
+ runner,
+ self.size.start(),
+ self.size.end_incl(),
+ );
+ if bits.len() < count {
+ panic!("not enough bits to sample");
+ }
+
+ for bit in self.bits.iter().choose_multiple(runner.rng(), count) {
+ bits.set(bit);
+ }
+
+ Ok(BitSetValueTree {
+ inner: bits,
+ shrink: self.bits.start(),
+ prev_shrink: None,
+ min_count: self.size.start(),
+ })
+ }
+}
+
+/// Value tree produced by `BitSetStrategy` and `SampledBitSetStrategy`.
+#[derive(Clone, Copy, Debug)]
+pub struct BitSetValueTree<T: BitSetLike> {
+ inner: T,
+ shrink: usize,
+ prev_shrink: Option<usize>,
+ min_count: usize,
+}
+
+impl<T: BitSetLike> ValueTree for BitSetValueTree<T> {
+ type Value = T;
+
+ fn current(&self) -> T {
+ self.inner.clone()
+ }
+
+ fn simplify(&mut self) -> bool {
+ if self.inner.count() <= self.min_count {
+ return false;
+ }
+
+ while self.shrink < self.inner.len() && !self.inner.test(self.shrink) {
+ self.shrink += 1;
+ }
+
+ if self.shrink >= self.inner.len() {
+ self.prev_shrink = None;
+ false
+ } else {
+ self.prev_shrink = Some(self.shrink);
+ self.inner.clear(self.shrink);
+ self.shrink += 1;
+ true
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ if let Some(bit) = self.prev_shrink.take() {
+ self.inner.set(bit);
+ true
+ } else {
+ false
+ }
+ }
+}
+
+macro_rules! int_api {
+ ($typ:ident, $max:expr) => {
+ #[allow(missing_docs)]
+ pub mod $typ {
+ use super::*;
+
+ /// Generates integers where all bits may be set.
+ pub const ANY: BitSetStrategy<$typ> = BitSetStrategy {
+ min: 0,
+ max: $max,
+ mask: None,
+ };
+
+ /// Generates values where bits between the given bounds may be
+ /// set.
+ pub fn between(min: usize, max: usize) -> BitSetStrategy<$typ> {
+ BitSetStrategy::new(min, max)
+ }
+
+ /// Generates values where any bits set in `mask` (and no others)
+ /// may be set.
+ pub fn masked(mask: $typ) -> BitSetStrategy<$typ> {
+ BitSetStrategy::masked(mask)
+ }
+
+ /// Create a strategy which generates values where bits within the
+ /// bounds given by `bits` may be set. The number of bits that are
+ /// set is chosen to be in the range given by `size`.
+ ///
+ /// ## Panics
+ ///
+ /// Panics if `size` includes a value that is greater than the
+ /// number of bits in `bits`.
+ pub fn sampled(
+ size: impl Into<SizeRange>,
+ bits: impl Into<SizeRange>,
+ ) -> SampledBitSetStrategy<$typ> {
+ SampledBitSetStrategy::new(size, bits)
+ }
+ }
+ };
+}
+
+int_api!(u8, 8);
+int_api!(u16, 16);
+int_api!(u32, 32);
+int_api!(u64, 64);
+int_api!(i8, 8);
+int_api!(i16, 16);
+int_api!(i32, 32);
+int_api!(i64, 64);
+
+macro_rules! minimal_api {
+ ($md:ident, $typ:ty) => {
+ #[allow(missing_docs)]
+ pub mod $md {
+ use super::*;
+
+ /// Generates values where bits between the given bounds may be
+ /// set.
+ pub fn between(min: usize, max: usize) -> BitSetStrategy<$typ> {
+ BitSetStrategy::new(min, max)
+ }
+
+ /// Generates values where any bits set in `mask` (and no others)
+ /// may be set.
+ pub fn masked(mask: $typ) -> BitSetStrategy<$typ> {
+ BitSetStrategy::masked(mask)
+ }
+
+ /// Create a strategy which generates values where bits within the
+ /// bounds given by `bits` may be set. The number of bits that are
+ /// set is chosen to be in the range given by `size`.
+ ///
+ /// ## Panics
+ ///
+ /// Panics if `size` includes a value that is greater than the
+ /// number of bits in `bits`.
+ pub fn sampled(
+ size: impl Into<SizeRange>,
+ bits: impl Into<SizeRange>,
+ ) -> SampledBitSetStrategy<$typ> {
+ SampledBitSetStrategy::new(size, bits)
+ }
+ }
+ };
+}
+minimal_api!(usize, usize);
+minimal_api!(isize, isize);
+#[cfg(feature = "bit-set")]
+minimal_api!(bitset, BitSet);
+minimal_api!(bool_vec, Vec<bool>);
+
+pub(crate) mod varsize {
+ use super::*;
+ use core::iter::FromIterator;
+
+ #[cfg(feature = "bit-set")]
+ type Inner = BitSet;
+ #[cfg(not(feature = "bit-set"))]
+ type Inner = Vec<bool>;
+
+ #[derive(Debug, Clone)]
+ pub(crate) struct VarBitSet(Inner);
+
+ impl VarBitSet {
+ pub(crate) fn saturated(len: usize) -> Self {
+ (0..len).collect::<VarBitSet>()
+ }
+
+ #[cfg(not(feature = "bit-set"))]
+ pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
+ (0..self.len()).into_iter().filter(move |&ix| self.test(ix))
+ }
+
+ #[cfg(feature = "bit-set")]
+ pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
+ self.0.iter()
+ }
+ }
+
+ impl BitSetLike for VarBitSet {
+ fn new_bitset(max: usize) -> Self {
+ VarBitSet(Inner::new_bitset(max))
+ }
+
+ fn len(&self) -> usize {
+ BitSetLike::len(&self.0)
+ }
+
+ fn test(&self, bit: usize) -> bool {
+ BitSetLike::test(&self.0, bit)
+ }
+
+ fn set(&mut self, bit: usize) {
+ BitSetLike::set(&mut self.0, bit);
+ }
+
+ fn clear(&mut self, bit: usize) {
+ BitSetLike::clear(&mut self.0, bit);
+ }
+
+ fn count(&self) -> usize {
+ BitSetLike::count(&self.0)
+ }
+ }
+
+ impl FromIterator<usize> for VarBitSet {
+ fn from_iter<T: IntoIterator<Item = usize>>(iter: T) -> Self {
+ let mut bits = VarBitSet::new_bitset(0);
+ for bit in iter {
+ bits.set(bit);
+ }
+ bits
+ }
+ }
+
+ /*
+ pub(crate) fn between(min: usize, max: usize) -> BitSetStrategy<VarBitSet> {
+ BitSetStrategy::new(min, max)
+ }
+
+ pub(crate) fn masked(mask: VarBitSet) -> BitSetStrategy<VarBitSet> {
+ BitSetStrategy::masked(mask)
+ }
+ */
+
+ pub(crate) fn sampled(
+ size: impl Into<SizeRange>,
+ bits: impl Into<SizeRange>,
+ ) -> SampledBitSetStrategy<VarBitSet> {
+ SampledBitSetStrategy::new(size, bits)
+ }
+}
+
+pub(crate) use self::varsize::VarBitSet;
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn generates_values_in_range() {
+ let input = u32::between(4, 8);
+
+ let mut runner = TestRunner::default();
+ for _ in 0..256 {
+ let value = input.new_tree(&mut runner).unwrap().current();
+ assert!(0 == value & !0xF0u32, "Generate value {}", value);
+ }
+ }
+
+ #[test]
+ fn generates_values_in_mask() {
+ let mut accum = 0;
+
+ let mut runner = TestRunner::deterministic();
+ let input = u32::masked(0xdeadbeef);
+ for _ in 0..1024 {
+ accum |= input.new_tree(&mut runner).unwrap().current();
+ }
+
+ assert_eq!(0xdeadbeef, accum);
+ }
+
+ #[cfg(feature = "bit-set")]
+ #[test]
+ fn mask_bounds_for_bitset_correct() {
+ let mut seen_0 = false;
+ let mut seen_2 = false;
+
+ let mut mask = BitSet::new();
+ mask.insert(0);
+ mask.insert(2);
+
+ let mut runner = TestRunner::deterministic();
+ let input = bitset::masked(mask);
+ for _ in 0..32 {
+ let v = input.new_tree(&mut runner).unwrap().current();
+ seen_0 |= v.contains(0);
+ seen_2 |= v.contains(2);
+ }
+
+ assert!(seen_0);
+ assert!(seen_2);
+ }
+
+ #[test]
+ fn mask_bounds_for_vecbool_correct() {
+ let mut seen_0 = false;
+ let mut seen_2 = false;
+
+ let mask = vec![true, false, true, false];
+
+ let mut runner = TestRunner::deterministic();
+ let input = bool_vec::masked(mask);
+ for _ in 0..32 {
+ let v = input.new_tree(&mut runner).unwrap().current();
+ assert_eq!(4, v.len());
+ seen_0 |= v[0];
+ seen_2 |= v[2];
+ }
+
+ assert!(seen_0);
+ assert!(seen_2);
+ }
+
+ #[test]
+ fn shrinks_to_zero() {
+ let input = u32::between(4, 24);
+
+ let mut runner = TestRunner::default();
+ for _ in 0..256 {
+ let mut value = input.new_tree(&mut runner).unwrap();
+ let mut prev = value.current();
+ while value.simplify() {
+ let v = value.current();
+ assert!(
+ 1 == (prev & !v).count_ones(),
+ "Shrank from {} to {}",
+ prev,
+ v
+ );
+ prev = v;
+ }
+
+ assert_eq!(0, value.current());
+ }
+ }
+
+ #[test]
+ fn complicates_to_previous() {
+ let input = u32::between(4, 24);
+
+ let mut runner = TestRunner::default();
+ for _ in 0..256 {
+ let mut value = input.new_tree(&mut runner).unwrap();
+ let orig = value.current();
+ if value.simplify() {
+ assert!(value.complicate());
+ assert_eq!(orig, value.current());
+ }
+ }
+ }
+
+ #[test]
+ fn sampled_selects_correct_sizes_and_bits() {
+ let input = u32::sampled(4..8, 10..20);
+ let mut seen_counts = [0; 32];
+ let mut seen_bits = [0; 32];
+
+ let mut runner = TestRunner::deterministic();
+ for _ in 0..2048 {
+ let value = input.new_tree(&mut runner).unwrap().current();
+ let count = value.count_ones() as usize;
+ assert!(count >= 4 && count < 8);
+ seen_counts[count] += 1;
+
+ for bit in 0..32 {
+ if 0 != value & (1 << bit) {
+ assert!(bit >= 10 && bit < 20);
+ seen_bits[bit] += value;
+ }
+ }
+ }
+
+ for i in 4..8 {
+ assert!(seen_counts[i] >= 256 && seen_counts[i] < 1024);
+ }
+
+ let least_seen_bit_count =
+ seen_bits[10..20].iter().cloned().min().unwrap();
+ let most_seen_bit_count =
+ seen_bits[10..20].iter().cloned().max().unwrap();
+ assert_eq!(1, most_seen_bit_count / least_seen_bit_count);
+ }
+
+ #[test]
+ fn sampled_doesnt_shrink_below_min_size() {
+ let input = u32::sampled(4..8, 10..20);
+
+ let mut runner = TestRunner::default();
+ for _ in 0..256 {
+ let mut value = input.new_tree(&mut runner).unwrap();
+ while value.simplify() {}
+
+ assert_eq!(4, value.current().count_ones());
+ }
+ }
+
+ #[test]
+ fn test_sanity() {
+ check_strategy_sanity(u32::masked(0xdeadbeef), None);
+ }
+}
diff --git a/vendor/proptest/src/bool.rs b/vendor/proptest/src/bool.rs
new file mode 100644
index 000000000..e64e78467
--- /dev/null
+++ b/vendor/proptest/src/bool.rs
@@ -0,0 +1,144 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+//! Strategies for generating `bool` values.
+
+use crate::strategy::*;
+use crate::test_runner::*;
+
+use rand::Rng;
+
+/// The type of the `ANY` constant.
+#[derive(Clone, Copy, Debug)]
+pub struct Any(());
+
+/// Generates boolean values by picking `true` or `false` uniformly.
+///
+/// Shrinks `true` to `false`.
+pub const ANY: Any = Any(());
+
+impl Strategy for Any {
+ type Tree = BoolValueTree;
+ type Value = bool;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(BoolValueTree::new(runner.rng().gen()))
+ }
+}
+
+/// Generates boolean values by picking `true` with the given `probability`
+/// (1.0 = always true, 0.0 = always false).
+///
+/// Shrinks `true` to `false`.
+pub fn weighted(probability: f64) -> Weighted {
+ Weighted(probability)
+}
+
+/// The return type from `weighted()`.
+#[must_use = "strategies do nothing unless used"]
+#[derive(Clone, Copy, Debug)]
+pub struct Weighted(f64);
+
+impl Strategy for Weighted {
+ type Tree = BoolValueTree;
+ type Value = bool;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(BoolValueTree::new(runner.rng().gen_bool(self.0)))
+ }
+}
+
+/// The `ValueTree` to shrink booleans to false.
+#[derive(Clone, Copy, Debug)]
+pub struct BoolValueTree {
+ current: bool,
+ state: ShrinkState,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum ShrinkState {
+ Untouched,
+ Simplified,
+ Final,
+}
+
+impl BoolValueTree {
+ fn new(current: bool) -> Self {
+ BoolValueTree {
+ current,
+ state: ShrinkState::Untouched,
+ }
+ }
+}
+
+impl ValueTree for BoolValueTree {
+ type Value = bool;
+
+ fn current(&self) -> bool {
+ self.current
+ }
+ fn simplify(&mut self) -> bool {
+ match self.state {
+ ShrinkState::Untouched if self.current => {
+ self.current = false;
+ self.state = ShrinkState::Simplified;
+ true
+ }
+
+ ShrinkState::Untouched
+ | ShrinkState::Simplified
+ | ShrinkState::Final => {
+ self.state = ShrinkState::Final;
+ false
+ }
+ }
+ }
+ fn complicate(&mut self) -> bool {
+ match self.state {
+ ShrinkState::Untouched | ShrinkState::Final => {
+ self.state = ShrinkState::Final;
+ false
+ }
+
+ ShrinkState::Simplified => {
+ self.current = true;
+ self.state = ShrinkState::Final;
+ true
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_sanity() {
+ check_strategy_sanity(ANY, None);
+ }
+
+ #[test]
+ fn shrinks_properly() {
+ let mut tree = BoolValueTree::new(true);
+ assert!(tree.simplify());
+ assert!(!tree.current());
+ assert!(!tree.clone().simplify());
+ assert!(tree.complicate());
+ assert!(!tree.clone().complicate());
+ assert!(tree.current());
+ assert!(!tree.simplify());
+ assert!(tree.current());
+
+ tree = BoolValueTree::new(false);
+ assert!(!tree.clone().simplify());
+ assert!(!tree.clone().complicate());
+ assert!(!tree.current());
+ }
+}
diff --git a/vendor/proptest/src/char.rs b/vendor/proptest/src/char.rs
new file mode 100644
index 000000000..7f0e92d7a
--- /dev/null
+++ b/vendor/proptest/src/char.rs
@@ -0,0 +1,409 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+//! Strategies for generating `char` values.
+//!
+//! Unlike most strategies in Proptest, character generation is by default
+//! biased to particular values known to be difficult to handle in various
+//! circumstances.
+//!
+//! The main things of interest are `any()` to generate truly arbitrary
+//! characters, and `range()` and `ranges()` to select characters from
+//! inclusive ranges.
+
+use crate::std_facade::Cow;
+use core::ops::RangeInclusive;
+
+use rand::Rng;
+
+use crate::num;
+use crate::strategy::*;
+use crate::test_runner::*;
+
+/// An inclusive char range from fst to snd.
+type CharRange = RangeInclusive<char>;
+
+/// A default set of characters to consider as "special" during character
+/// generation.
+///
+/// Most of the characters here were chosen specifically because they are
+/// difficult to handle in particular contexts.
+pub const DEFAULT_SPECIAL_CHARS: &[char] = &[
+ // Things to give shell scripts and filesystem logic difficulties
+ '/', '\\', '$', '.', '*', '{', '\'', '"', '`', ':',
+ // Characters with special significance in URLs and elsewhere
+ '?', '%', '=', '&', '<',
+ // Interesting ASCII control characters
+ // NUL, HT, CR, LF, VT ESC DEL
+ '\x00', '\t', '\r', '\n', '\x0B', '\x1B', '\x7F',
+ // ¥ both to test simple Unicode handling and because it has interesting
+ // properties on MS Shift-JIS systems.
+ '¥', // No non-Unicode encoding has both ¥ and Ѩ
+ 'Ѩ',
+ // In UTF-8, Ⱥ increases in length from 2 to 3 bytes when lowercased
+ 'Ⱥ',
+ // More Unicode edge-cases: BOM, replacement character, RTL override, and non-BMP
+ '\u{FEFF}', '\u{FFFD}', '\u{202E}', '🕴',
+];
+
+/// A default sequence of ranges used preferentially when generating random
+/// characters.
+pub const DEFAULT_PREFERRED_RANGES: &[CharRange] = &[
+ // ASCII printable
+ ' '..='~',
+ ' '..='~',
+ ' '..='~',
+ ' '..='~',
+ ' '..='~',
+ // Latin-1
+ '\u{0040}'..='\u{00ff}',
+];
+
+/// Selects a random character the way `CharStrategy` does.
+///
+/// If `special` is non-empty, there is a 50% chance that a character from this
+/// array is chosen randomly, and will be returned if that character falls
+/// within `ranges`.
+///
+/// If `preferred` is non-empty, there is a 50% chance that any generation
+/// which gets past the `special` step picks a random element from this list,
+/// then a random character from within that range (both endpoints inclusive).
+/// That character will be returned if it falls within `ranges`.
+///
+/// In all other cases, an element is picked randomly from `ranges` and a
+/// random character within the range (both endpoints inclusive) is chosen and
+/// returned.
+///
+/// Notice that in all cases, `ranges` completely defines the set of characters
+/// that can possibly be defined.
+///
+/// It is legal for ranges in all cases to contain non-characters.
+///
+/// Both `preferred` and `ranges` bias selection towards characters in smaller
+/// ranges. This is deliberate. `preferred` is usually tuned to select
+/// particular characters anyway. `ranges` is usually derived from some
+/// external property, and the fact that a range is small often means it is
+/// more interesting.
+pub fn select_char(
+ rnd: &mut impl Rng,
+ special: &[char],
+ preferred: &[CharRange],
+ ranges: &[CharRange],
+) -> char {
+ let (base, offset) = select_range_index(rnd, special, preferred, ranges);
+ ::core::char::from_u32(base + offset).expect("bad character selected")
+}
+
+fn select_range_index(
+ rnd: &mut impl Rng,
+ special: &[char],
+ preferred: &[CharRange],
+ ranges: &[CharRange],
+) -> (u32, u32) {
+ fn in_range(ranges: &[CharRange], ch: char) -> Option<(u32, u32)> {
+ ranges
+ .iter()
+ .find(|r| ch >= *r.start() && ch <= *r.end())
+ .map(|r| (*r.start() as u32, ch as u32 - *r.start() as u32))
+ }
+
+ if !special.is_empty() && rnd.gen() {
+ let s = special[rnd.gen_range(0..special.len())];
+ if let Some(ret) = in_range(ranges, s) {
+ return ret;
+ }
+ }
+
+ if !preferred.is_empty() && rnd.gen() {
+ let range = preferred[rnd.gen_range(0..preferred.len())].clone();
+ if let Some(ch) = ::core::char::from_u32(
+ rnd.gen_range(*range.start() as u32..*range.end() as u32 + 1),
+ ) {
+ if let Some(ret) = in_range(ranges, ch) {
+ return ret;
+ }
+ }
+ }
+
+ for _ in 0..65_536 {
+ let range = ranges[rnd.gen_range(0..ranges.len())].clone();
+ if let Some(ch) = ::core::char::from_u32(
+ rnd.gen_range(*range.start() as u32..*range.end() as u32 + 1),
+ ) {
+ return (*range.start() as u32, ch as u32 - *range.start() as u32);
+ }
+ }
+
+ // Give up and return a character we at least know is valid.
+ (*ranges[0].start() as u32, 0)
+}
+
+/// Strategy for generating `char`s.
+///
+/// Character selection is more sophisticated than integer selection. Naïve
+/// selection (particularly in the larger context of generating strings) would
+/// result in starting inputs like `ꂡ螧轎ቶᢹ糦狥芹ᘆ㶏曊ᒀ踔虙ჲ` and "simplified"
+/// inputs consisting mostly of control characters. It also has difficulty
+/// locating edge cases, since the vast majority of code points (such as the
+/// enormous CJK regions) don't cause problems for anything with even basic
+/// Unicode support.
+///
+/// Instead, character selection is always based on explicit ranges, and is
+/// designed to bias to specifically chosen characters and character ranges to
+/// produce inputs that are both more useful and easier for humans to
+/// understand. There are also hard-wired simplification targets based on ASCII
+/// instead of simply simplifying towards NUL to avoid problematic inputs being
+/// reduced to a bunch of NUL characters.
+///
+/// Shrinking never crosses ranges. If you have a complex range like `[A-Za-z]`
+/// and the starting point `x` is chosen, it will not shrink to the first `A-Z`
+/// group, but rather simply to `a`.
+///
+/// The usual way to get instances of this class is with the module-level `ANY`
+/// constant or `range` function. Directly constructing a `CharStrategy` is
+/// only necessary for complex ranges or to override the default biases.
+#[derive(Debug, Clone)]
+#[must_use = "strategies do nothing unless used"]
+pub struct CharStrategy<'a> {
+ special: Cow<'a, [char]>,
+ preferred: Cow<'a, [CharRange]>,
+ ranges: Cow<'a, [CharRange]>,
+}
+
+impl<'a> CharStrategy<'a> {
+ /// Construct a new `CharStrategy` with the parameters it will pass to the
+ /// function underlying `select_char()`.
+ ///
+ /// All arguments as per `select_char()`.
+ pub fn new(
+ special: Cow<'a, [char]>,
+ preferred: Cow<'a, [CharRange]>,
+ ranges: Cow<'a, [CharRange]>,
+ ) -> Self {
+ CharStrategy {
+ special,
+ preferred,
+ ranges,
+ }
+ }
+
+ /// Same as `CharStrategy::new()` but using `Cow::Borrowed` for all parts.
+ pub fn new_borrowed(
+ special: &'a [char],
+ preferred: &'a [CharRange],
+ ranges: &'a [CharRange],
+ ) -> Self {
+ CharStrategy::new(
+ Cow::Borrowed(special),
+ Cow::Borrowed(preferred),
+ Cow::Borrowed(ranges),
+ )
+ }
+}
+
+const WHOLE_RANGE: &[CharRange] = &['\x00'..=::core::char::MAX];
+
+/// Creates a `CharStrategy` which picks from literally any character, with the
+/// default biases.
+pub fn any() -> CharStrategy<'static> {
+ CharStrategy {
+ special: Cow::Borrowed(DEFAULT_SPECIAL_CHARS),
+ preferred: Cow::Borrowed(DEFAULT_PREFERRED_RANGES),
+ ranges: Cow::Borrowed(WHOLE_RANGE),
+ }
+}
+
+/// Creates a `CharStrategy` which selects characters within the given
+/// endpoints, inclusive, using the default biases.
+pub fn range(start: char, end: char) -> CharStrategy<'static> {
+ CharStrategy {
+ special: Cow::Borrowed(DEFAULT_SPECIAL_CHARS),
+ preferred: Cow::Borrowed(DEFAULT_PREFERRED_RANGES),
+ ranges: Cow::Owned(vec![start..=end]),
+ }
+}
+
+/// Creates a `CharStrategy` which selects characters within the given ranges,
+/// all inclusive, using the default biases.
+pub fn ranges(ranges: Cow<[CharRange]>) -> CharStrategy {
+ CharStrategy {
+ special: Cow::Borrowed(DEFAULT_SPECIAL_CHARS),
+ preferred: Cow::Borrowed(DEFAULT_PREFERRED_RANGES),
+ ranges,
+ }
+}
+
+/// The `ValueTree` corresponding to `CharStrategy`.
+#[derive(Debug, Clone, Copy)]
+pub struct CharValueTree {
+ value: num::u32::BinarySearch,
+}
+
+impl<'a> Strategy for CharStrategy<'a> {
+ type Tree = CharValueTree;
+ type Value = char;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let (base, offset) = select_range_index(
+ runner.rng(),
+ &self.special,
+ &self.preferred,
+ &self.ranges,
+ );
+
+ // Select a minimum point more convenient than 0
+ let start = base + offset;
+ let bottom = if start >= '¡' as u32 && base < '¡' as u32 {
+ '¡' as u32
+ } else if start >= 'a' as u32 && base < 'a' as u32 {
+ 'a' as u32
+ } else if start >= 'A' as u32 && base < 'A' as u32 {
+ 'A' as u32
+ } else if start >= '0' as u32 && base < '0' as u32 {
+ '0' as u32
+ } else if start >= ' ' as u32 && base < ' ' as u32 {
+ ' ' as u32
+ } else {
+ base
+ };
+
+ Ok(CharValueTree {
+ value: num::u32::BinarySearch::new_above(bottom, start),
+ })
+ }
+}
+
+impl CharValueTree {
+ fn reposition(&mut self) {
+ while ::core::char::from_u32(self.value.current()).is_none() {
+ if !self.value.complicate() {
+ panic!("Converged to non-char value");
+ }
+ }
+ }
+}
+
+impl ValueTree for CharValueTree {
+ type Value = char;
+
+ fn current(&self) -> char {
+ ::core::char::from_u32(self.value.current())
+ .expect("Generated non-char value")
+ }
+
+ fn simplify(&mut self) -> bool {
+ if self.value.simplify() {
+ self.reposition();
+ true
+ } else {
+ false
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ if self.value.complicate() {
+ self.reposition();
+ true
+ } else {
+ false
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use std::cmp::{max, min};
+ use std::vec::Vec;
+
+ use super::*;
+ use crate::collection;
+
+ proptest! {
+ #[test]
+ fn stays_in_range(input_ranges in collection::vec(
+ (0..::std::char::MAX as u32,
+ 0..::std::char::MAX as u32),
+ 1..5))
+ {
+ let input = ranges(Cow::Owned(input_ranges.iter().map(
+ |&(lo, hi)| ::std::char::from_u32(lo).and_then(
+ |lo| ::std::char::from_u32(hi).map(
+ |hi| min(lo, hi) ..= max(lo, hi)))
+ .ok_or_else(|| TestCaseError::reject("non-char")))
+ .collect::<Result<Vec<CharRange>,_>>()?));
+
+ let mut runner = TestRunner::default();
+ for _ in 0..256 {
+ let mut value = input.new_tree(&mut runner).unwrap();
+ loop {
+ let ch = value.current() as u32;
+ assert!(input_ranges.iter().any(
+ |&(lo, hi)| ch >= min(lo, hi) &&
+ ch <= max(lo, hi)));
+
+ if !value.simplify() { break; }
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn applies_desired_bias() {
+ let mut men_in_business_suits_levitating = 0;
+ let mut ascii_printable = 0;
+ let mut runner = TestRunner::deterministic();
+
+ for _ in 0..1024 {
+ let ch = any().new_tree(&mut runner).unwrap().current();
+ if '🕴' == ch {
+ men_in_business_suits_levitating += 1;
+ } else if ch >= ' ' && ch <= '~' {
+ ascii_printable += 1;
+ }
+ }
+
+ assert!(ascii_printable >= 256);
+ assert!(men_in_business_suits_levitating >= 1);
+ }
+
+ #[test]
+ fn doesnt_shrink_to_ascii_control() {
+ let mut accepted = 0;
+ let mut runner = TestRunner::deterministic();
+
+ for _ in 0..256 {
+ let mut value = any().new_tree(&mut runner).unwrap();
+
+ if value.current() <= ' ' {
+ continue;
+ }
+
+ while value.simplify() {}
+
+ assert!(value.current() >= ' ');
+ accepted += 1;
+ }
+
+ assert!(accepted >= 200);
+ }
+
+ #[test]
+ fn test_sanity() {
+ check_strategy_sanity(
+ any(),
+ Some(CheckStrategySanityOptions {
+ // `simplify()` can itself `complicate()` back to the starting
+ // position, so the overly strict complicate-after-simplify check
+ // must be disabled.
+ strict_complicate_after_simplify: false,
+ ..CheckStrategySanityOptions::default()
+ }),
+ );
+ }
+}
diff --git a/vendor/proptest/src/collection.rs b/vendor/proptest/src/collection.rs
new file mode 100644
index 000000000..90d04977e
--- /dev/null
+++ b/vendor/proptest/src/collection.rs
@@ -0,0 +1,779 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Strategies for generating `std::collections` of values.
+
+use core::cmp::Ord;
+use core::hash::Hash;
+use core::ops::{Add, Range, RangeInclusive, RangeTo, RangeToInclusive};
+use core::usize;
+
+use crate::std_facade::{
+ fmt, BTreeMap, BTreeSet, BinaryHeap, LinkedList, Vec, VecDeque,
+};
+
+#[cfg(feature = "std")]
+use crate::std_facade::{HashMap, HashSet};
+
+use crate::bits::{BitSetLike, VarBitSet};
+use crate::num::sample_uniform_incl;
+use crate::strategy::*;
+use crate::test_runner::*;
+use crate::tuple::TupleValueTree;
+
+//==============================================================================
+// SizeRange
+//==============================================================================
+
+/// The minimum and maximum range/bounds on the size of a collection.
+/// The interval must form a subset of `[0, std::usize::MAX)`.
+///
+/// A value like `0..=std::usize::MAX` will still be accepted but will silently
+/// truncate the maximum to `std::usize::MAX - 1`.
+///
+/// The `Default` is `0..100`.
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct SizeRange(Range<usize>);
+
+/// Creates a `SizeRange` from some value that is convertible into it.
+pub fn size_range(from: impl Into<SizeRange>) -> SizeRange {
+ from.into()
+}
+
+impl Default for SizeRange {
+ /// Constructs a `SizeRange` equivalent to `size_range(0..100)`.
+ fn default() -> Self {
+ size_range(0..100)
+ }
+}
+
+impl SizeRange {
+ /// Creates a `SizeBounds` from a `RangeInclusive<usize>`.
+ pub fn new(range: RangeInclusive<usize>) -> Self {
+ range.into()
+ }
+
+ // Don't rely on these existing internally:
+
+ /// Merges self together with some other argument producing a product
+ /// type expected by some implementations of `A: Arbitrary` in
+ /// `A::Parameters`. This can be more ergonomic to work with and may
+ /// help type inference.
+ pub fn with<X>(self, and: X) -> product_type![Self, X] {
+ product_pack![self, and]
+ }
+
+ /// Merges self together with some other argument generated with a
+ /// default value producing a product type expected by some
+ /// implementations of `A: Arbitrary` in `A::Parameters`.
+ /// This can be more ergonomic to work with and may help type inference.
+ pub fn lift<X: Default>(self) -> product_type![Self, X] {
+ self.with(Default::default())
+ }
+
+ pub(crate) fn start(&self) -> usize {
+ self.0.start
+ }
+
+ /// Extract the ends `[low, high]` of a `SizeRange`.
+ pub(crate) fn start_end_incl(&self) -> (usize, usize) {
+ (self.start(), self.end_incl())
+ }
+
+ pub(crate) fn end_incl(&self) -> usize {
+ self.0.end - 1
+ }
+
+ pub(crate) fn end_excl(&self) -> usize {
+ self.0.end
+ }
+
+ pub(crate) fn iter(&self) -> impl Iterator<Item = usize> {
+ self.0.clone().into_iter()
+ }
+
+ pub(crate) fn is_empty(&self) -> bool {
+ self.start() == self.end_excl()
+ }
+
+ pub(crate) fn assert_nonempty(&self) {
+ if self.is_empty() {
+ panic!(
+ "Invalid use of empty size range. (hint: did you \
+ accidentally write {}..{} where you meant {}..={} \
+ somewhere?)",
+ self.start(),
+ self.end_excl(),
+ self.start(),
+ self.end_excl()
+ );
+ }
+ }
+}
+
+/// Given `(low: usize, high: usize)`,
+/// then a size range of `[low..high)` is the result.
+impl From<(usize, usize)> for SizeRange {
+ fn from((low, high): (usize, usize)) -> Self {
+ size_range(low..high)
+ }
+}
+
+/// Given `exact`, then a size range of `[exact, exact]` is the result.
+impl From<usize> for SizeRange {
+ fn from(exact: usize) -> Self {
+ size_range(exact..=exact)
+ }
+}
+
+/// Given `..high`, then a size range `[0, high)` is the result.
+impl From<RangeTo<usize>> for SizeRange {
+ fn from(high: RangeTo<usize>) -> Self {
+ size_range(0..high.end)
+ }
+}
+
+/// Given `low .. high`, then a size range `[low, high)` is the result.
+impl From<Range<usize>> for SizeRange {
+ fn from(r: Range<usize>) -> Self {
+ SizeRange(r)
+ }
+}
+
+/// Given `low ..= high`, then a size range `[low, high]` is the result.
+impl From<RangeInclusive<usize>> for SizeRange {
+ fn from(r: RangeInclusive<usize>) -> Self {
+ size_range(*r.start()..r.end().saturating_add(1))
+ }
+}
+
+/// Given `..=high`, then a size range `[0, high]` is the result.
+impl From<RangeToInclusive<usize>> for SizeRange {
+ fn from(high: RangeToInclusive<usize>) -> Self {
+ size_range(0..=high.end)
+ }
+}
+
+#[cfg(feature = "frunk")]
+impl Generic for SizeRange {
+ type Repr = RangeInclusive<usize>;
+
+ /// Converts the `SizeRange` into `Range<usize>`.
+ fn into(self) -> Self::Repr {
+ self.0
+ }
+
+ /// Converts `RangeInclusive<usize>` into `SizeRange`.
+ fn from(r: Self::Repr) -> Self {
+ r.into()
+ }
+}
+
+/// Adds `usize` to both start and end of the bounds.
+///
+/// Panics if adding to either end overflows `usize`.
+impl Add<usize> for SizeRange {
+ type Output = SizeRange;
+
+ fn add(self, rhs: usize) -> Self::Output {
+ let (start, end) = self.start_end_incl();
+ size_range((start + rhs)..=(end + rhs))
+ }
+}
+
+//==============================================================================
+// Strategies
+//==============================================================================
+
+/// Strategy to create `Vec`s with a length in a certain range.
+///
+/// Created by the `vec()` function in the same module.
+#[must_use = "strategies do nothing unless used"]
+#[derive(Clone, Debug)]
+pub struct VecStrategy<T: Strategy> {
+ element: T,
+ size: SizeRange,
+}
+
+/// Create a strategy to generate `Vec`s containing elements drawn from
+/// `element` and with a size range given by `size`.
+///
+/// To make a `Vec` with a fixed number of elements, each with its own
+/// strategy, you can instead make a `Vec` of strategies (boxed if necessary).
+pub fn vec<T: Strategy>(
+ element: T,
+ size: impl Into<SizeRange>,
+) -> VecStrategy<T> {
+ let size = size.into();
+ size.assert_nonempty();
+ VecStrategy { element, size }
+}
+
+mapfn! {
+ [] fn VecToDeque[<T : fmt::Debug>](vec: Vec<T>) -> VecDeque<T> {
+ vec.into()
+ }
+}
+
+opaque_strategy_wrapper! {
+ /// Strategy to create `VecDeque`s with a length in a certain range.
+ ///
+ /// Created by the `vec_deque()` function in the same module.
+ #[derive(Clone, Debug)]
+ pub struct VecDequeStrategy[<T>][where T : Strategy](
+ statics::Map<VecStrategy<T>, VecToDeque>)
+ -> VecDequeValueTree<T::Tree>;
+ /// `ValueTree` corresponding to `VecDequeStrategy`.
+ #[derive(Clone, Debug)]
+ pub struct VecDequeValueTree[<T>][where T : ValueTree](
+ statics::Map<VecValueTree<T>, VecToDeque>)
+ -> VecDeque<T::Value>;
+}
+
+/// Create a strategy to generate `VecDeque`s containing elements drawn from
+/// `element` and with a size range given by `size`.
+pub fn vec_deque<T: Strategy>(
+ element: T,
+ size: impl Into<SizeRange>,
+) -> VecDequeStrategy<T> {
+ VecDequeStrategy(statics::Map::new(vec(element, size), VecToDeque))
+}
+
+mapfn! {
+ [] fn VecToLl[<T : fmt::Debug>](vec: Vec<T>) -> LinkedList<T> {
+ vec.into_iter().collect()
+ }
+}
+
+opaque_strategy_wrapper! {
+ /// Strategy to create `LinkedList`s with a length in a certain range.
+ ///
+ /// Created by the `linkedlist()` function in the same module.
+ #[derive(Clone, Debug)]
+ pub struct LinkedListStrategy[<T>][where T : Strategy](
+ statics::Map<VecStrategy<T>, VecToLl>)
+ -> LinkedListValueTree<T::Tree>;
+ /// `ValueTree` corresponding to `LinkedListStrategy`.
+ #[derive(Clone, Debug)]
+ pub struct LinkedListValueTree[<T>][where T : ValueTree](
+ statics::Map<VecValueTree<T>, VecToLl>)
+ -> LinkedList<T::Value>;
+}
+
+/// Create a strategy to generate `LinkedList`s containing elements drawn from
+/// `element` and with a size range given by `size`.
+pub fn linked_list<T: Strategy>(
+ element: T,
+ size: impl Into<SizeRange>,
+) -> LinkedListStrategy<T> {
+ LinkedListStrategy(statics::Map::new(vec(element, size), VecToLl))
+}
+
+mapfn! {
+ [] fn VecToBinHeap[<T : fmt::Debug + Ord>](vec: Vec<T>) -> BinaryHeap<T> {
+ vec.into()
+ }
+}
+
+opaque_strategy_wrapper! {
+ /// Strategy to create `BinaryHeap`s with a length in a certain range.
+ ///
+ /// Created by the `binary_heap()` function in the same module.
+ #[derive(Clone, Debug)]
+ pub struct BinaryHeapStrategy[<T>][where T : Strategy, T::Value : Ord](
+ statics::Map<VecStrategy<T>, VecToBinHeap>)
+ -> BinaryHeapValueTree<T::Tree>;
+ /// `ValueTree` corresponding to `BinaryHeapStrategy`.
+ #[derive(Clone, Debug)]
+ pub struct BinaryHeapValueTree[<T>][where T : ValueTree, T::Value : Ord](
+ statics::Map<VecValueTree<T>, VecToBinHeap>)
+ -> BinaryHeap<T::Value>;
+}
+
+/// Create a strategy to generate `BinaryHeap`s containing elements drawn from
+/// `element` and with a size range given by `size`.
+pub fn binary_heap<T: Strategy>(
+ element: T,
+ size: impl Into<SizeRange>,
+) -> BinaryHeapStrategy<T>
+where
+ T::Value: Ord,
+{
+ BinaryHeapStrategy(statics::Map::new(vec(element, size), VecToBinHeap))
+}
+
+mapfn! {
+ {#[cfg(feature = "std")]}
+ [] fn VecToHashSet[<T : fmt::Debug + Hash + Eq>](vec: Vec<T>)
+ -> HashSet<T> {
+ vec.into_iter().collect()
+ }
+}
+
+#[derive(Debug, Clone, Copy)]
+struct MinSize(usize);
+
+#[cfg(feature = "std")]
+impl<T: Eq + Hash> statics::FilterFn<HashSet<T>> for MinSize {
+ fn apply(&self, set: &HashSet<T>) -> bool {
+ set.len() >= self.0
+ }
+}
+
+opaque_strategy_wrapper! {
+ {#[cfg(feature = "std")]}
+ /// Strategy to create `HashSet`s with a length in a certain range.
+ ///
+ /// Created by the `hash_set()` function in the same module.
+ #[derive(Clone, Debug)]
+ pub struct HashSetStrategy[<T>][where T : Strategy, T::Value : Hash + Eq](
+ statics::Filter<statics::Map<VecStrategy<T>, VecToHashSet>, MinSize>)
+ -> HashSetValueTree<T::Tree>;
+ /// `ValueTree` corresponding to `HashSetStrategy`.
+ #[derive(Clone, Debug)]
+ pub struct HashSetValueTree[<T>][where T : ValueTree, T::Value : Hash + Eq](
+ statics::Filter<statics::Map<VecValueTree<T>, VecToHashSet>, MinSize>)
+ -> HashSet<T::Value>;
+}
+
+/// Create a strategy to generate `HashSet`s containing elements drawn from
+/// `element` and with a size range given by `size`.
+///
+/// This strategy will implicitly do local rejects to ensure that the `HashSet`
+/// has at least the minimum number of elements, in case `element` should
+/// produce duplicate values.
+#[cfg(feature = "std")]
+pub fn hash_set<T: Strategy>(
+ element: T,
+ size: impl Into<SizeRange>,
+) -> HashSetStrategy<T>
+where
+ T::Value: Hash + Eq,
+{
+ let size = size.into();
+ HashSetStrategy(statics::Filter::new(
+ statics::Map::new(vec(element, size.clone()), VecToHashSet),
+ "HashSet minimum size".into(),
+ MinSize(size.start()),
+ ))
+}
+
+mapfn! {
+ [] fn VecToBTreeSet[<T : fmt::Debug + Ord>](vec: Vec<T>)
+ -> BTreeSet<T> {
+ vec.into_iter().collect()
+ }
+}
+
+impl<T: Ord> statics::FilterFn<BTreeSet<T>> for MinSize {
+ fn apply(&self, set: &BTreeSet<T>) -> bool {
+ set.len() >= self.0
+ }
+}
+
+opaque_strategy_wrapper! {
+ /// Strategy to create `BTreeSet`s with a length in a certain range.
+ ///
+ /// Created by the `btree_set()` function in the same module.
+ #[derive(Clone, Debug)]
+ pub struct BTreeSetStrategy[<T>][where T : Strategy, T::Value : Ord](
+ statics::Filter<statics::Map<VecStrategy<T>, VecToBTreeSet>, MinSize>)
+ -> BTreeSetValueTree<T::Tree>;
+ /// `ValueTree` corresponding to `BTreeSetStrategy`.
+ #[derive(Clone, Debug)]
+ pub struct BTreeSetValueTree[<T>][where T : ValueTree, T::Value : Ord](
+ statics::Filter<statics::Map<VecValueTree<T>, VecToBTreeSet>, MinSize>)
+ -> BTreeSet<T::Value>;
+}
+
+/// Create a strategy to generate `BTreeSet`s containing elements drawn from
+/// `element` and with a size range given by `size`.
+///
+/// This strategy will implicitly do local rejects to ensure that the
+/// `BTreeSet` has at least the minimum number of elements, in case `element`
+/// should produce duplicate values.
+pub fn btree_set<T: Strategy>(
+ element: T,
+ size: impl Into<SizeRange>,
+) -> BTreeSetStrategy<T>
+where
+ T::Value: Ord,
+{
+ let size = size.into();
+ BTreeSetStrategy(statics::Filter::new(
+ statics::Map::new(vec(element, size.clone()), VecToBTreeSet),
+ "BTreeSet minimum size".into(),
+ MinSize(size.start()),
+ ))
+}
+
+mapfn! {
+ {#[cfg(feature = "std")]}
+ [] fn VecToHashMap[<K : fmt::Debug + Hash + Eq, V : fmt::Debug>]
+ (vec: Vec<(K, V)>) -> HashMap<K, V>
+ {
+ vec.into_iter().collect()
+ }
+}
+
+#[cfg(feature = "std")]
+impl<K: Hash + Eq, V> statics::FilterFn<HashMap<K, V>> for MinSize {
+ fn apply(&self, map: &HashMap<K, V>) -> bool {
+ map.len() >= self.0
+ }
+}
+
+opaque_strategy_wrapper! {
+ {#[cfg(feature = "std")]}
+ /// Strategy to create `HashMap`s with a length in a certain range.
+ ///
+ /// Created by the `hash_map()` function in the same module.
+ #[derive(Clone, Debug)]
+ pub struct HashMapStrategy[<K, V>]
+ [where K : Strategy, V : Strategy, K::Value : Hash + Eq](
+ statics::Filter<statics::Map<VecStrategy<(K,V)>,
+ VecToHashMap>, MinSize>)
+ -> HashMapValueTree<K::Tree, V::Tree>;
+ /// `ValueTree` corresponding to `HashMapStrategy`.
+ #[derive(Clone, Debug)]
+ pub struct HashMapValueTree[<K, V>]
+ [where K : ValueTree, V : ValueTree, K::Value : Hash + Eq](
+ statics::Filter<statics::Map<VecValueTree<TupleValueTree<(K, V)>>,
+ VecToHashMap>, MinSize>)
+ -> HashMap<K::Value, V::Value>;
+}
+
+/// Create a strategy to generate `HashMap`s containing keys and values drawn
+/// from `key` and `value` respectively, and with a size within the given
+/// range.
+///
+/// This strategy will implicitly do local rejects to ensure that the `HashMap`
+/// has at least the minimum number of elements, in case `key` should produce
+/// duplicate values.
+#[cfg(feature = "std")]
+pub fn hash_map<K: Strategy, V: Strategy>(
+ key: K,
+ value: V,
+ size: impl Into<SizeRange>,
+) -> HashMapStrategy<K, V>
+where
+ K::Value: Hash + Eq,
+{
+ let size = size.into();
+ HashMapStrategy(statics::Filter::new(
+ statics::Map::new(vec((key, value), size.clone()), VecToHashMap),
+ "HashMap minimum size".into(),
+ MinSize(size.start()),
+ ))
+}
+
+mapfn! {
+ [] fn VecToBTreeMap[<K : fmt::Debug + Ord, V : fmt::Debug>]
+ (vec: Vec<(K, V)>) -> BTreeMap<K, V>
+ {
+ vec.into_iter().collect()
+ }
+}
+
+impl<K: Ord, V> statics::FilterFn<BTreeMap<K, V>> for MinSize {
+ fn apply(&self, map: &BTreeMap<K, V>) -> bool {
+ map.len() >= self.0
+ }
+}
+
+opaque_strategy_wrapper! {
+ /// Strategy to create `BTreeMap`s with a length in a certain range.
+ ///
+ /// Created by the `btree_map()` function in the same module.
+ #[derive(Clone, Debug)]
+ pub struct BTreeMapStrategy[<K, V>]
+ [where K : Strategy, V : Strategy, K::Value : Ord](
+ statics::Filter<statics::Map<VecStrategy<(K,V)>,
+ VecToBTreeMap>, MinSize>)
+ -> BTreeMapValueTree<K::Tree, V::Tree>;
+ /// `ValueTree` corresponding to `BTreeMapStrategy`.
+ #[derive(Clone, Debug)]
+ pub struct BTreeMapValueTree[<K, V>]
+ [where K : ValueTree, V : ValueTree, K::Value : Ord](
+ statics::Filter<statics::Map<VecValueTree<TupleValueTree<(K, V)>>,
+ VecToBTreeMap>, MinSize>)
+ -> BTreeMap<K::Value, V::Value>;
+}
+
+/// Create a strategy to generate `BTreeMap`s containing keys and values drawn
+/// from `key` and `value` respectively, and with a size within the given
+/// range.
+///
+/// This strategy will implicitly do local rejects to ensure that the
+/// `BTreeMap` has at least the minimum number of elements, in case `key`
+/// should produce duplicate values.
+pub fn btree_map<K: Strategy, V: Strategy>(
+ key: K,
+ value: V,
+ size: impl Into<SizeRange>,
+) -> BTreeMapStrategy<K, V>
+where
+ K::Value: Ord,
+{
+ let size = size.into();
+ BTreeMapStrategy(statics::Filter::new(
+ statics::Map::new(vec((key, value), size.clone()), VecToBTreeMap),
+ "BTreeMap minimum size".into(),
+ MinSize(size.start()),
+ ))
+}
+
+#[derive(Clone, Copy, Debug)]
+enum Shrink {
+ DeleteElement(usize),
+ ShrinkElement(usize),
+}
+
+/// `ValueTree` corresponding to `VecStrategy`.
+#[derive(Clone, Debug)]
+pub struct VecValueTree<T: ValueTree> {
+ elements: Vec<T>,
+ included_elements: VarBitSet,
+ min_size: usize,
+ shrink: Shrink,
+ prev_shrink: Option<Shrink>,
+}
+
+impl<T: Strategy> Strategy for VecStrategy<T> {
+ type Tree = VecValueTree<T::Tree>;
+ type Value = Vec<T::Value>;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let (start, end) = self.size.start_end_incl();
+ let max_size = sample_uniform_incl(runner, start, end);
+ let mut elements = Vec::with_capacity(max_size);
+ while elements.len() < max_size {
+ elements.push(self.element.new_tree(runner)?);
+ }
+
+ Ok(VecValueTree {
+ elements,
+ included_elements: VarBitSet::saturated(max_size),
+ min_size: start,
+ shrink: Shrink::DeleteElement(0),
+ prev_shrink: None,
+ })
+ }
+}
+
+impl<T: Strategy> Strategy for Vec<T> {
+ type Tree = VecValueTree<T::Tree>;
+ type Value = Vec<T::Value>;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let len = self.len();
+ let elements = self
+ .iter()
+ .map(|t| t.new_tree(runner))
+ .collect::<Result<Vec<_>, Reason>>()?;
+
+ Ok(VecValueTree {
+ elements,
+ included_elements: VarBitSet::saturated(len),
+ min_size: len,
+ shrink: Shrink::ShrinkElement(0),
+ prev_shrink: None,
+ })
+ }
+}
+
+impl<T: ValueTree> ValueTree for VecValueTree<T> {
+ type Value = Vec<T::Value>;
+
+ fn current(&self) -> Vec<T::Value> {
+ self.elements
+ .iter()
+ .enumerate()
+ .filter(|&(ix, _)| self.included_elements.test(ix))
+ .map(|(_, element)| element.current())
+ .collect()
+ }
+
+ fn simplify(&mut self) -> bool {
+ // The overall strategy here is to iteratively delete elements from the
+ // list until we can do so no further, then to shrink each remaining
+ // element in sequence.
+ //
+ // For `complicate()`, we simply undo the last shrink operation, if
+ // there was any.
+ if let Shrink::DeleteElement(ix) = self.shrink {
+ // Can't delete an element if beyond the end of the vec or if it
+ // would put us under the minimum length.
+ if ix >= self.elements.len()
+ || self.included_elements.count() == self.min_size
+ {
+ self.shrink = Shrink::ShrinkElement(0);
+ } else {
+ self.included_elements.clear(ix);
+ self.prev_shrink = Some(self.shrink);
+ self.shrink = Shrink::DeleteElement(ix + 1);
+ return true;
+ }
+ }
+
+ while let Shrink::ShrinkElement(ix) = self.shrink {
+ if ix >= self.elements.len() {
+ // Nothing more we can do
+ return false;
+ }
+
+ if !self.included_elements.test(ix) {
+ // No use shrinking something we're not including.
+ self.shrink = Shrink::ShrinkElement(ix + 1);
+ continue;
+ }
+
+ if !self.elements[ix].simplify() {
+ // Move on to the next element
+ self.shrink = Shrink::ShrinkElement(ix + 1);
+ } else {
+ self.prev_shrink = Some(self.shrink);
+ return true;
+ }
+ }
+
+ panic!("Unexpected shrink state");
+ }
+
+ fn complicate(&mut self) -> bool {
+ match self.prev_shrink {
+ None => false,
+ Some(Shrink::DeleteElement(ix)) => {
+ // Undo the last item we deleted. Can't complicate any further,
+ // so unset prev_shrink.
+ self.included_elements.set(ix);
+ self.prev_shrink = None;
+ true
+ }
+ Some(Shrink::ShrinkElement(ix)) => {
+ if self.elements[ix].complicate() {
+ // Don't unset prev_shrink; we may be able to complicate
+ // again.
+ true
+ } else {
+ // Can't complicate the last element any further.
+ self.prev_shrink = None;
+ false
+ }
+ }
+ }
+ }
+}
+
+//==============================================================================
+// Tests
+//==============================================================================
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ use crate::bits;
+
+ #[test]
+ fn test_vec() {
+ let input = vec(1usize..20usize, 5..20);
+ let mut num_successes = 0;
+
+ let mut runner = TestRunner::deterministic();
+ for _ in 0..256 {
+ let case = input.new_tree(&mut runner).unwrap();
+ let start = case.current();
+ // Has correct length
+ assert!(start.len() >= 5 && start.len() < 20);
+ // Has at least 2 distinct values
+ assert!(start.iter().map(|&v| v).collect::<VarBitSet>().len() >= 2);
+
+ let result = runner.run_one(case, |v| {
+ prop_assert!(
+ v.iter().map(|&v| v).sum::<usize>() < 9,
+ "greater than 8"
+ );
+ Ok(())
+ });
+
+ match result {
+ Ok(true) => num_successes += 1,
+ Err(TestError::Fail(_, value)) => {
+ // The minimal case always has between 5 (due to min
+ // length) and 9 (min element value = 1) elements, and
+ // always sums to exactly 9.
+ assert!(
+ value.len() >= 5
+ && value.len() <= 9
+ && value.iter().map(|&v| v).sum::<usize>() == 9,
+ "Unexpected minimal value: {:?}",
+ value
+ );
+ }
+ e => panic!("Unexpected result: {:?}", e),
+ }
+ }
+
+ assert!(num_successes < 256);
+ }
+
+ #[test]
+ fn test_vec_sanity() {
+ check_strategy_sanity(vec(0i32..1000, 5..10), None);
+ }
+
+ #[test]
+ fn test_parallel_vec() {
+ let input =
+ vec![(1u32..10).boxed(), bits::u32::masked(0xF0u32).boxed()];
+
+ for _ in 0..256 {
+ let mut runner = TestRunner::default();
+ let mut case = input.new_tree(&mut runner).unwrap();
+
+ loop {
+ let current = case.current();
+ assert_eq!(2, current.len());
+ assert!(current[0] >= 1 && current[0] <= 10);
+ assert_eq!(0, (current[1] & !0xF0));
+
+ if !case.simplify() {
+ break;
+ }
+ }
+ }
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn test_map() {
+ // Only 8 possible keys
+ let input = hash_map("[ab]{3}", "a", 2..3);
+ let mut runner = TestRunner::deterministic();
+
+ for _ in 0..256 {
+ let v = input.new_tree(&mut runner).unwrap().current();
+ assert_eq!(2, v.len());
+ }
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn test_set() {
+ // Only 8 possible values
+ let input = hash_set("[ab]{3}", 2..3);
+ let mut runner = TestRunner::deterministic();
+
+ for _ in 0..256 {
+ let v = input.new_tree(&mut runner).unwrap().current();
+ assert_eq!(2, v.len());
+ }
+ }
+}
diff --git a/vendor/proptest/src/file-preamble b/vendor/proptest/src/file-preamble
new file mode 100644
index 000000000..13abfcdc0
--- /dev/null
+++ b/vendor/proptest/src/file-preamble
@@ -0,0 +1,8 @@
+//-
+// Copyright 2017
+//
+// 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.
diff --git a/vendor/proptest/src/lib.rs b/vendor/proptest/src/lib.rs
new file mode 100644
index 000000000..1cba5f900
--- /dev/null
+++ b/vendor/proptest/src/lib.rs
@@ -0,0 +1,102 @@
+//-
+// Copyright 2017, 2018 Jason Lingle
+//
+// 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.
+
+//! # Proptest Reference Documentation
+//!
+//! This is the reference documentation for the proptest API.
+//!
+//! For documentation on how to get started with proptest and general usage
+//! advice, please refer to the [Proptest Book](https://altsysrq.github.io/proptest-book/intro.html).
+
+#![forbid(future_incompatible)]
+#![deny(missing_docs, bare_trait_objects)]
+#![no_std]
+#![cfg_attr(feature = "cargo-clippy", allow(
+ doc_markdown,
+ // We have a lot of these lints for associated types... And we don't care.
+ type_complexity
+))]
+#![cfg_attr(
+ feature = "unstable",
+ feature(allocator_api, try_trait_v2, generator_trait, never_type)
+)]
+#![cfg_attr(all(feature = "std", feature = "unstable"), feature(ip))]
+#![cfg_attr(
+ all(feature = "alloc", not(feature = "std")),
+ feature(core_intrinsics)
+)]
+
+// std_facade is used in a few macros, so it needs to be public.
+#[macro_use]
+#[doc(hidden)]
+pub mod std_facade;
+
+#[cfg(any(feature = "std", test))]
+#[macro_use]
+extern crate std;
+
+#[cfg(all(feature = "alloc", not(feature = "std")))]
+#[macro_use]
+extern crate alloc;
+
+#[cfg(feature = "frunk")]
+#[macro_use]
+extern crate frunk_core;
+
+#[cfg(feature = "frunk")]
+#[macro_use]
+mod product_frunk;
+
+#[cfg(not(feature = "frunk"))]
+#[macro_use]
+mod product_tuple;
+
+#[macro_use]
+extern crate bitflags;
+#[cfg(feature = "bit-set")]
+extern crate bit_set;
+
+#[cfg(feature = "std")]
+#[macro_use]
+extern crate lazy_static;
+
+// Only required for the string module.
+#[cfg(feature = "std")]
+#[macro_use]
+extern crate quick_error;
+
+#[cfg(feature = "fork")]
+#[macro_use]
+extern crate rusty_fork;
+
+#[macro_use]
+mod macros;
+
+#[doc(hidden)]
+#[macro_use]
+pub mod sugar;
+
+pub mod arbitrary;
+pub mod array;
+pub mod bits;
+pub mod bool;
+pub mod char;
+pub mod collection;
+pub mod num;
+pub mod strategy;
+pub mod test_runner;
+pub mod tuple;
+
+pub mod option;
+pub mod result;
+pub mod sample;
+#[cfg(feature = "std")]
+pub mod string;
+
+pub mod prelude;
diff --git a/vendor/proptest/src/macros.rs b/vendor/proptest/src/macros.rs
new file mode 100644
index 000000000..c76989eb6
--- /dev/null
+++ b/vendor/proptest/src/macros.rs
@@ -0,0 +1,93 @@
+//-
+// Copyright 2017, 2018 Jason Lingle
+//
+// 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.
+
+//! Macros for internal use to reduce boilerplate.
+
+// Pervasive internal sugar
+macro_rules! mapfn {
+ ($({#[$allmeta:meta]})* $(#[$meta:meta])* [$($vis:tt)*]
+ fn $name:ident[$($gen:tt)*]($parm:ident: $input:ty) -> $output:ty {
+ $($body:tt)*
+ }) => {
+ $(#[$allmeta])* $(#[$meta])*
+ #[derive(Clone, Copy, Debug)]
+ $($vis)* struct $name;
+ $(#[$allmeta])*
+ impl $($gen)* $crate::strategy::statics::MapFn<$input> for $name {
+ type Output = $output;
+ fn apply(&self, $parm: $input) -> $output {
+ $($body)*
+ }
+ }
+ }
+}
+
+macro_rules! delegate_vt_0 {
+ () => {
+ fn current(&self) -> Self::Value {
+ self.0.current()
+ }
+
+ fn simplify(&mut self) -> bool {
+ self.0.simplify()
+ }
+
+ fn complicate(&mut self) -> bool {
+ self.0.complicate()
+ }
+ };
+}
+
+macro_rules! opaque_strategy_wrapper {
+ ($({#[$allmeta:meta]})*
+ $(#[$smeta:meta])*
+ pub struct $stratname:ident
+ [$($sgen:tt)*][$($swhere:tt)*]
+ ($innerstrat:ty) -> $stratvtty:ty;
+
+ $(#[$vmeta:meta])* pub struct $vtname:ident
+ [$($vgen:tt)*][$($vwhere:tt)*]
+ ($innervt:ty) -> $actualty:ty;
+ ) => {
+ $(#[$allmeta])*
+ $(#[$smeta])*
+ #[must_use = "strategies do nothing unless used"]
+ pub struct $stratname $($sgen)* ($innerstrat)
+ $($swhere)*;
+
+ $(#[$allmeta])*
+ $(#[$vmeta])* pub struct $vtname $($vgen)* ($innervt) $($vwhere)*;
+
+ $(#[$allmeta])*
+ impl $($sgen)* Strategy for $stratname $($sgen)* $($swhere)* {
+ type Tree = $stratvtty;
+ type Value = $actualty;
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ self.0.new_tree(runner).map($vtname)
+ }
+ }
+
+ $(#[$allmeta])*
+ impl $($vgen)* ValueTree for $vtname $($vgen)* $($vwhere)* {
+ type Value = $actualty;
+
+ delegate_vt_0!();
+ }
+ }
+}
+
+// Example: unwrap_or!(result, err => handle_err(err));
+macro_rules! unwrap_or {
+ ($unwrap: expr, $err: ident => $on_err: expr) => {
+ match $unwrap {
+ Ok(ok) => ok,
+ Err($err) => $on_err,
+ }
+ };
+}
diff --git a/vendor/proptest/src/num.rs b/vendor/proptest/src/num.rs
new file mode 100644
index 000000000..75431c7b6
--- /dev/null
+++ b/vendor/proptest/src/num.rs
@@ -0,0 +1,1388 @@
+//-
+// Copyright 2017, 2018 Jason Lingle
+//
+// 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.
+
+//! Strategies to generate numeric values (as opposed to integers used as bit
+//! fields).
+//!
+//! All strategies in this module shrink by binary searching towards 0.
+
+mod float_samplers;
+
+use crate::test_runner::TestRunner;
+use rand::distributions::uniform::{SampleUniform, Uniform};
+use rand::distributions::{Distribution, Standard};
+
+pub(crate) fn sample_uniform<X: SampleUniform>(
+ run: &mut TestRunner,
+ start: X,
+ end: X,
+) -> X {
+ Uniform::new(start, end).sample(run.rng())
+}
+
+pub(crate) fn sample_uniform_incl<X: SampleUniform>(
+ run: &mut TestRunner,
+ start: X,
+ end: X,
+) -> X {
+ Uniform::new_inclusive(start, end).sample(run.rng())
+}
+
+macro_rules! int_any {
+ ($typ: ident) => {
+ /// Type of the `ANY` constant.
+ #[derive(Clone, Copy, Debug)]
+ #[must_use = "strategies do nothing unless used"]
+ pub struct Any(());
+ /// Generates integers with completely arbitrary values, uniformly
+ /// distributed over the whole range.
+ pub const ANY: Any = Any(());
+
+ impl Strategy for Any {
+ type Tree = BinarySearch;
+ type Value = $typ;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(BinarySearch::new(runner.rng().gen()))
+ }
+ }
+ };
+}
+
+macro_rules! numeric_api {
+ ($typ:ident, $epsilon:expr) => {
+ numeric_api!($typ, $typ, $epsilon);
+ };
+ ($typ:ident, $sample_typ:ty, $epsilon:expr) => {
+ impl Strategy for ::core::ops::Range<$typ> {
+ type Tree = BinarySearch;
+ type Value = $typ;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(BinarySearch::new_clamped(
+ self.start,
+ $crate::num::sample_uniform::<$sample_typ>(
+ runner,
+ self.start.into(),
+ self.end.into(),
+ )
+ .into(),
+ self.end - $epsilon,
+ ))
+ }
+ }
+
+ impl Strategy for ::core::ops::RangeInclusive<$typ> {
+ type Tree = BinarySearch;
+ type Value = $typ;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(BinarySearch::new_clamped(
+ *self.start(),
+ $crate::num::sample_uniform_incl::<$sample_typ>(
+ runner,
+ (*self.start()).into(),
+ (*self.end()).into(),
+ )
+ .into(),
+ *self.end(),
+ ))
+ }
+ }
+
+ impl Strategy for ::core::ops::RangeFrom<$typ> {
+ type Tree = BinarySearch;
+ type Value = $typ;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(BinarySearch::new_clamped(
+ self.start,
+ $crate::num::sample_uniform_incl::<$sample_typ>(
+ runner,
+ self.start.into(),
+ ::core::$typ::MAX.into(),
+ )
+ .into(),
+ ::core::$typ::MAX,
+ ))
+ }
+ }
+
+ impl Strategy for ::core::ops::RangeTo<$typ> {
+ type Tree = BinarySearch;
+ type Value = $typ;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(BinarySearch::new_clamped(
+ ::core::$typ::MIN,
+ $crate::num::sample_uniform::<$sample_typ>(
+ runner,
+ ::core::$typ::MIN.into(),
+ self.end.into(),
+ )
+ .into(),
+ self.end,
+ ))
+ }
+ }
+
+ impl Strategy for ::core::ops::RangeToInclusive<$typ> {
+ type Tree = BinarySearch;
+ type Value = $typ;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(BinarySearch::new_clamped(
+ ::core::$typ::MIN,
+ $crate::num::sample_uniform_incl::<$sample_typ>(
+ runner,
+ ::core::$typ::MIN.into(),
+ self.end.into(),
+ )
+ .into(),
+ self.end,
+ ))
+ }
+ }
+ };
+}
+
+macro_rules! signed_integer_bin_search {
+ ($typ:ident) => {
+ #[allow(missing_docs)]
+ pub mod $typ {
+ use rand::Rng;
+
+ use crate::strategy::*;
+ use crate::test_runner::TestRunner;
+
+ int_any!($typ);
+
+ /// Shrinks an integer towards 0, using binary search to find
+ /// boundary points.
+ #[derive(Clone, Copy, Debug)]
+ pub struct BinarySearch {
+ lo: $typ,
+ curr: $typ,
+ hi: $typ,
+ }
+ impl BinarySearch {
+ /// Creates a new binary searcher starting at the given value.
+ pub fn new(start: $typ) -> Self {
+ BinarySearch {
+ lo: 0,
+ curr: start,
+ hi: start,
+ }
+ }
+
+ /// Creates a new binary searcher which will not produce values
+ /// on the other side of `lo` or `hi` from `start`. `lo` is
+ /// inclusive, `hi` is exclusive.
+ fn new_clamped(lo: $typ, start: $typ, hi: $typ) -> Self {
+ use core::cmp::{max, min};
+
+ BinarySearch {
+ lo: if start < 0 {
+ min(0, hi - 1)
+ } else {
+ max(0, lo)
+ },
+ hi: start,
+ curr: start,
+ }
+ }
+
+ fn reposition(&mut self) -> bool {
+ // Won't ever overflow since lo starts at 0 and advances
+ // towards hi.
+ let interval = self.hi - self.lo;
+ let new_mid = self.lo + interval / 2;
+
+ if new_mid == self.curr {
+ false
+ } else {
+ self.curr = new_mid;
+ true
+ }
+ }
+
+ fn magnitude_greater(lhs: $typ, rhs: $typ) -> bool {
+ if 0 == lhs {
+ false
+ } else if lhs < 0 {
+ lhs < rhs
+ } else {
+ lhs > rhs
+ }
+ }
+ }
+ impl ValueTree for BinarySearch {
+ type Value = $typ;
+
+ fn current(&self) -> $typ {
+ self.curr
+ }
+
+ fn simplify(&mut self) -> bool {
+ if !BinarySearch::magnitude_greater(self.hi, self.lo) {
+ return false;
+ }
+
+ self.hi = self.curr;
+ self.reposition()
+ }
+
+ fn complicate(&mut self) -> bool {
+ if !BinarySearch::magnitude_greater(self.hi, self.lo) {
+ return false;
+ }
+
+ self.lo = self.curr + if self.hi < 0 { -1 } else { 1 };
+
+ self.reposition()
+ }
+ }
+
+ numeric_api!($typ, 1);
+ }
+ };
+}
+
+macro_rules! unsigned_integer_bin_search {
+ ($typ:ident) => {
+ #[allow(missing_docs)]
+ pub mod $typ {
+ use rand::Rng;
+
+ use crate::strategy::*;
+ use crate::test_runner::TestRunner;
+
+ int_any!($typ);
+
+ /// Shrinks an integer towards 0, using binary search to find
+ /// boundary points.
+ #[derive(Clone, Copy, Debug)]
+ pub struct BinarySearch {
+ lo: $typ,
+ curr: $typ,
+ hi: $typ,
+ }
+ impl BinarySearch {
+ /// Creates a new binary searcher starting at the given value.
+ pub fn new(start: $typ) -> Self {
+ BinarySearch {
+ lo: 0,
+ curr: start,
+ hi: start,
+ }
+ }
+
+ /// Creates a new binary searcher which will not search below
+ /// the given `lo` value.
+ fn new_clamped(lo: $typ, start: $typ, _hi: $typ) -> Self {
+ BinarySearch {
+ lo: lo,
+ curr: start,
+ hi: start,
+ }
+ }
+
+ /// Creates a new binary searcher which will not search below
+ /// the given `lo` value.
+ pub fn new_above(lo: $typ, start: $typ) -> Self {
+ BinarySearch::new_clamped(lo, start, start)
+ }
+
+ fn reposition(&mut self) -> bool {
+ let interval = self.hi - self.lo;
+ let new_mid = self.lo + interval / 2;
+
+ if new_mid == self.curr {
+ false
+ } else {
+ self.curr = new_mid;
+ true
+ }
+ }
+ }
+ impl ValueTree for BinarySearch {
+ type Value = $typ;
+
+ fn current(&self) -> $typ {
+ self.curr
+ }
+
+ fn simplify(&mut self) -> bool {
+ if self.hi <= self.lo {
+ return false;
+ }
+
+ self.hi = self.curr;
+ self.reposition()
+ }
+
+ fn complicate(&mut self) -> bool {
+ if self.hi <= self.lo {
+ return false;
+ }
+
+ self.lo = self.curr + 1;
+ self.reposition()
+ }
+ }
+
+ numeric_api!($typ, 1);
+ }
+ };
+}
+
+signed_integer_bin_search!(i8);
+signed_integer_bin_search!(i16);
+signed_integer_bin_search!(i32);
+signed_integer_bin_search!(i64);
+#[cfg(not(target_arch = "wasm32"))]
+signed_integer_bin_search!(i128);
+signed_integer_bin_search!(isize);
+unsigned_integer_bin_search!(u8);
+unsigned_integer_bin_search!(u16);
+unsigned_integer_bin_search!(u32);
+unsigned_integer_bin_search!(u64);
+#[cfg(not(target_arch = "wasm32"))]
+unsigned_integer_bin_search!(u128);
+unsigned_integer_bin_search!(usize);
+
+bitflags! {
+ pub(crate) struct FloatTypes: u32 {
+ const POSITIVE = 0b0000_0001;
+ const NEGATIVE = 0b0000_0010;
+ const NORMAL = 0b0000_0100;
+ const SUBNORMAL = 0b0000_1000;
+ const ZERO = 0b0001_0000;
+ const INFINITE = 0b0010_0000;
+ const QUIET_NAN = 0b0100_0000;
+ const SIGNALING_NAN = 0b1000_0000;
+ const ANY =
+ Self::POSITIVE.bits |
+ Self::NEGATIVE.bits |
+ Self::NORMAL.bits |
+ Self::SUBNORMAL.bits |
+ Self::ZERO.bits |
+ Self::INFINITE.bits |
+ Self::QUIET_NAN.bits;
+ }
+}
+
+impl FloatTypes {
+ fn normalise(mut self) -> Self {
+ if !self.intersects(FloatTypes::POSITIVE | FloatTypes::NEGATIVE) {
+ self |= FloatTypes::POSITIVE;
+ }
+
+ if !self.intersects(
+ FloatTypes::NORMAL
+ | FloatTypes::SUBNORMAL
+ | FloatTypes::ZERO
+ | FloatTypes::INFINITE
+ | FloatTypes::QUIET_NAN
+ | FloatTypes::SIGNALING_NAN,
+ ) {
+ self |= FloatTypes::NORMAL;
+ }
+ self
+ }
+}
+
+trait FloatLayout
+where
+ Standard: Distribution<Self::Bits>,
+{
+ type Bits: Copy;
+
+ const SIGN_MASK: Self::Bits;
+ const EXP_MASK: Self::Bits;
+ const EXP_ZERO: Self::Bits;
+ const MANTISSA_MASK: Self::Bits;
+}
+
+impl FloatLayout for f32 {
+ type Bits = u32;
+
+ const SIGN_MASK: u32 = 0x8000_0000;
+ const EXP_MASK: u32 = 0x7F80_0000;
+ const EXP_ZERO: u32 = 0x3F80_0000;
+ const MANTISSA_MASK: u32 = 0x007F_FFFF;
+}
+
+impl FloatLayout for f64 {
+ type Bits = u64;
+
+ const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
+ const EXP_MASK: u64 = 0x7FF0_0000_0000_0000;
+ const EXP_ZERO: u64 = 0x3FF0_0000_0000_0000;
+ const MANTISSA_MASK: u64 = 0x000F_FFFF_FFFF_FFFF;
+}
+
+macro_rules! float_any {
+ ($typ:ident) => {
+ /// Strategies which produce floating-point values from particular
+ /// classes. See the various `Any`-typed constants in this module.
+ ///
+ /// Note that this usage is fairly advanced and primarily useful to
+ /// implementors of algorithms that need to handle wild values in a
+ /// particular way. For testing things like graphics processing or game
+ /// physics, simply using ranges (e.g., `-1.0..2.0`) will often be more
+ /// practical.
+ ///
+ /// `Any` can be OR'ed to combine multiple classes. For example,
+ /// `POSITIVE | INFINITE` will generate arbitrary positive, non-NaN
+ /// floats, including positive infinity (but not negative infinity, of
+ /// course).
+ ///
+ /// If neither `POSITIVE` nor `NEGATIVE` has been OR'ed into an `Any`
+ /// but a type to be generated requires a sign, `POSITIVE` is assumed.
+ /// If no classes are OR'ed into an `Any` (i.e., only `POSITIVE` and/or
+ /// `NEGATIVE` are given), `NORMAL` is assumed.
+ ///
+ /// The various float classes are assigned fixed weights for generation
+ /// which are believed to be reasonable for most applications. Roughly:
+ ///
+ /// - If `POSITIVE | NEGATIVE`, the sign is evenly distributed between
+ /// both options.
+ ///
+ /// - Classes are weighted as follows, in descending order:
+ /// `NORMAL` > `ZERO` > `SUBNORMAL` > `INFINITE` > `QUIET_NAN` =
+ /// `SIGNALING_NAN`.
+ #[derive(Clone, Copy, Debug)]
+ #[must_use = "strategies do nothing unless used"]
+ pub struct Any(FloatTypes);
+
+ #[cfg(test)]
+ impl Any {
+ pub(crate) fn from_bits(bits: u32) -> Self {
+ Any(FloatTypes::from_bits_truncate(bits))
+ }
+
+ pub(crate) fn normal_bits(&self) -> FloatTypes {
+ self.0.normalise()
+ }
+ }
+
+ impl ops::BitOr for Any {
+ type Output = Self;
+
+ fn bitor(self, rhs: Self) -> Self {
+ Any(self.0 | rhs.0)
+ }
+ }
+
+ impl ops::BitOrAssign for Any {
+ fn bitor_assign(&mut self, rhs: Self) {
+ self.0 |= rhs.0
+ }
+ }
+
+ /// Generates positive floats
+ ///
+ /// By itself, implies the `NORMAL` class, unless another class is
+ /// OR'ed in. That is, using `POSITIVE` as a strategy by itself will
+ /// generate arbitrary values between the type's `MIN_POSITIVE` and
+ /// `MAX`, while `POSITIVE | INFINITE` would only allow generating
+ /// positive infinity.
+ pub const POSITIVE: Any = Any(FloatTypes::POSITIVE);
+ /// Generates negative floats.
+ ///
+ /// By itself, implies the `NORMAL` class, unless another class is
+ /// OR'ed in. That is, using `POSITIVE` as a strategy by itself will
+ /// generate arbitrary values between the type's `MIN` and
+ /// `-MIN_POSITIVE`, while `NEGATIVE | INFINITE` would only allow
+ /// generating positive infinity.
+ pub const NEGATIVE: Any = Any(FloatTypes::NEGATIVE);
+ /// Generates "normal" floats.
+ ///
+ /// These are finite values where the first bit of the mantissa is an
+ /// implied `1`. When positive, this represents the range
+ /// `MIN_POSITIVE` through `MAX`, both inclusive.
+ ///
+ /// Generated values are uniform over the discrete floating-point
+ /// space, which means the numeric distribution is an inverse
+ /// exponential step function. For example, values between 1.0 and 2.0
+ /// are generated with the same frequency as values between 2.0 and
+ /// 4.0, even though the latter covers twice the numeric range.
+ ///
+ /// If neither `POSITIVE` nor `NEGATIVE` is OR'ed with this constant,
+ /// `POSITIVE` is implied.
+ pub const NORMAL: Any = Any(FloatTypes::NORMAL);
+ /// Generates subnormal floats.
+ ///
+ /// These are finite non-zero values where the first bit of the
+ /// mantissa is not an implied zero. When positive, this represents the
+ /// range `MIN`, inclusive, through `MIN_POSITIVE`, exclusive.
+ ///
+ /// Subnormals are generated with a uniform distribution both in terms
+ /// of discrete floating-point space and numerically.
+ ///
+ /// If neither `POSITIVE` nor `NEGATIVE` is OR'ed with this constant,
+ /// `POSITIVE` is implied.
+ pub const SUBNORMAL: Any = Any(FloatTypes::SUBNORMAL);
+ /// Generates zero-valued floats.
+ ///
+ /// Note that IEEE floats support both positive and negative zero, so
+ /// this class does interact with the sign flags.
+ ///
+ /// If neither `POSITIVE` nor `NEGATIVE` is OR'ed with this constant,
+ /// `POSITIVE` is implied.
+ pub const ZERO: Any = Any(FloatTypes::ZERO);
+ /// Generates infinity floats.
+ ///
+ /// If neither `POSITIVE` nor `NEGATIVE` is OR'ed with this constant,
+ /// `POSITIVE` is implied.
+ pub const INFINITE: Any = Any(FloatTypes::INFINITE);
+ /// Generates "Quiet NaN" floats.
+ ///
+ /// Operations on quiet NaNs generally simply propagate the NaN rather
+ /// than invoke any exception mechanism.
+ ///
+ /// The payload of the NaN is uniformly distributed over the possible
+ /// values which safe Rust allows, including the sign bit (as
+ /// controlled by `POSITIVE` and `NEGATIVE`).
+ ///
+ /// Note however that in Rust 1.23.0 and earlier, this constitutes only
+ /// one particular payload due to apparent issues with particular MIPS
+ /// and PA-RISC processors which fail to implement IEEE 754-2008
+ /// correctly.
+ ///
+ /// On Rust 1.24.0 and later, this does produce arbitrary payloads as
+ /// documented.
+ ///
+ /// On platforms where the CPU and the IEEE standard disagree on the
+ /// format of a quiet NaN, values generated conform to the hardware's
+ /// expectations.
+ pub const QUIET_NAN: Any = Any(FloatTypes::QUIET_NAN);
+ /// Generates "Signaling NaN" floats if allowed by the platform.
+ ///
+ /// On most platforms, signalling NaNs by default behave the same as
+ /// quiet NaNs, but it is possible to configure the OS or CPU to raise
+ /// an asynchronous exception if an operation is performed on a
+ /// signalling NaN.
+ ///
+ /// In Rust 1.23.0 and earlier, this silently behaves the same as
+ /// [`QUIET_NAN`](const.QUIET_NAN.html).
+ ///
+ /// On platforms where the CPU and the IEEE standard disagree on the
+ /// format of a quiet NaN, values generated conform to the hardware's
+ /// expectations.
+ ///
+ /// Note that certain platforms — most notably, x86/AMD64 — allow the
+ /// architecture to turn a signalling NaN into a quiet NaN with the
+ /// same payload. Whether this happens can depend on what registers the
+ /// compiler decides to use to pass the value around, what CPU flags
+ /// are set, and what compiler settings are in use.
+ pub const SIGNALING_NAN: Any = Any(FloatTypes::SIGNALING_NAN);
+
+ /// Generates literally arbitrary floating-point values, including
+ /// infinities and quiet NaNs (but not signaling NaNs).
+ ///
+ /// Equivalent to `POSITIVE | NEGATIVE | NORMAL | SUBNORMAL | ZERO |
+ /// INFINITE | QUIET_NAN`.
+ ///
+ /// See [`SIGNALING_NAN`](const.SIGNALING_NAN.html) if you also want to
+ /// generate signalling NaNs. This signalling NaNs are not included by
+ /// default since in most contexts they either make no difference, or
+ /// if the process enabled the relevant CPU mode, result in
+ /// hardware-triggered exceptions that usually just abort the process.
+ ///
+ /// Before proptest 0.4.1, this erroneously generated values in the
+ /// range 0.0..1.0.
+ pub const ANY: Any = Any(FloatTypes::ANY);
+
+ impl Strategy for Any {
+ type Tree = BinarySearch;
+ type Value = $typ;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let flags = self.0.normalise();
+ let sign_mask = if flags.contains(FloatTypes::NEGATIVE) {
+ $typ::SIGN_MASK
+ } else {
+ 0
+ };
+ let sign_or = if flags.contains(FloatTypes::POSITIVE) {
+ 0
+ } else {
+ $typ::SIGN_MASK
+ };
+
+ macro_rules! weight {
+ ($case:ident, $weight:expr) => {
+ if flags.contains(FloatTypes::$case) {
+ $weight
+ } else {
+ 0
+ }
+ }
+ }
+
+ // A few CPUs disagree with IEEE about the meaning of the
+ // signalling bit. Assume the `NAN` constant is a quiet NaN as
+ // interpreted by the hardware and generate values based on
+ // that.
+ let quiet_or = ::core::$typ::NAN.to_bits() &
+ ($typ::EXP_MASK | ($typ::EXP_MASK >> 1));
+ let signaling_or = (quiet_or ^ ($typ::EXP_MASK >> 1)) |
+ $typ::EXP_MASK;
+
+ let (class_mask, class_or, allow_edge_exp, allow_zero_mant) =
+ prop_oneof![
+ weight!(NORMAL, 20) => Just(
+ ($typ::EXP_MASK | $typ::MANTISSA_MASK, 0,
+ false, true)),
+ weight!(SUBNORMAL, 3) => Just(
+ ($typ::MANTISSA_MASK, 0, true, false)),
+ weight!(ZERO, 4) => Just(
+ (0, 0, true, true)),
+ weight!(INFINITE, 2) => Just(
+ (0, $typ::EXP_MASK, true, true)),
+ weight!(QUIET_NAN, 1) => Just(
+ ($typ::MANTISSA_MASK >> 1, quiet_or,
+ true, false)),
+ weight!(SIGNALING_NAN, 1) => Just(
+ ($typ::MANTISSA_MASK >> 1, signaling_or,
+ true, false)),
+ ].new_tree(runner)?.current();
+
+ let mut generated_value: <$typ as FloatLayout>::Bits =
+ runner.rng().gen();
+ generated_value &= sign_mask | class_mask;
+ generated_value |= sign_or | class_or;
+ let exp = generated_value & $typ::EXP_MASK;
+ if !allow_edge_exp && (0 == exp || $typ::EXP_MASK == exp) {
+ generated_value &= !$typ::EXP_MASK;
+ generated_value |= $typ::EXP_ZERO;
+ }
+ if !allow_zero_mant &&
+ 0 == generated_value & $typ::MANTISSA_MASK
+ {
+ generated_value |= 1;
+ }
+
+ Ok(BinarySearch::new_with_types(
+ $typ::from_bits(generated_value), flags))
+ }
+ }
+ }
+}
+
+macro_rules! float_bin_search {
+ ($typ:ident, $sample_typ:ident) => {
+ #[allow(missing_docs)]
+ pub mod $typ {
+ use super::float_samplers::$sample_typ;
+
+ use core::ops;
+ #[cfg(not(feature = "std"))]
+ use num_traits::float::FloatCore;
+
+ use rand::Rng;
+
+ use super::{FloatLayout, FloatTypes};
+ use crate::strategy::*;
+ use crate::test_runner::TestRunner;
+
+ float_any!($typ);
+
+ /// Shrinks a float towards 0, using binary search to find boundary
+ /// points.
+ ///
+ /// Non-finite values immediately shrink to 0.
+ #[derive(Clone, Copy, Debug)]
+ pub struct BinarySearch {
+ lo: $typ,
+ curr: $typ,
+ hi: $typ,
+ allowed: FloatTypes,
+ }
+
+ impl BinarySearch {
+ /// Creates a new binary searcher starting at the given value.
+ pub fn new(start: $typ) -> Self {
+ BinarySearch {
+ lo: 0.0,
+ curr: start,
+ hi: start,
+ allowed: FloatTypes::all(),
+ }
+ }
+
+ fn new_with_types(start: $typ, allowed: FloatTypes) -> Self {
+ BinarySearch {
+ lo: 0.0,
+ curr: start,
+ hi: start,
+ allowed,
+ }
+ }
+
+ /// Creates a new binary searcher which will not produce values
+ /// on the other side of `lo` or `hi` from `start`. `lo` is
+ /// inclusive, `hi` is exclusive.
+ fn new_clamped(lo: $typ, start: $typ, hi: $typ) -> Self {
+ BinarySearch {
+ lo: if start.is_sign_negative() {
+ hi.min(0.0)
+ } else {
+ lo.max(0.0)
+ },
+ hi: start,
+ curr: start,
+ allowed: FloatTypes::all(),
+ }
+ }
+
+ fn current_allowed(&self) -> bool {
+ use core::num::FpCategory::*;
+
+ // Don't reposition if the new value is not allowed
+ let class_allowed = match self.curr.classify() {
+ Nan =>
+ // We don't need to inspect whether the
+ // signallingness of the NaN matches the allowed
+ // set, as we never try to switch between them,
+ // instead shrinking to 0.
+ {
+ self.allowed.contains(FloatTypes::QUIET_NAN)
+ || self
+ .allowed
+ .contains(FloatTypes::SIGNALING_NAN)
+ }
+ Infinite => self.allowed.contains(FloatTypes::INFINITE),
+ Zero => self.allowed.contains(FloatTypes::ZERO),
+ Subnormal => {
+ self.allowed.contains(FloatTypes::SUBNORMAL)
+ }
+ Normal => self.allowed.contains(FloatTypes::NORMAL),
+ };
+ let signum = self.curr.signum();
+ let sign_allowed = if signum > 0.0 {
+ self.allowed.contains(FloatTypes::POSITIVE)
+ } else if signum < 0.0 {
+ self.allowed.contains(FloatTypes::NEGATIVE)
+ } else {
+ true
+ };
+
+ class_allowed && sign_allowed
+ }
+
+ fn ensure_acceptable(&mut self) {
+ while !self.current_allowed() {
+ if !self.complicate_once() {
+ panic!(
+ "Unable to complicate floating-point back \
+ to acceptable value"
+ );
+ }
+ }
+ }
+
+ fn reposition(&mut self) -> bool {
+ let interval = self.hi - self.lo;
+ let interval =
+ if interval.is_finite() { interval } else { 0.0 };
+ let new_mid = self.lo + interval / 2.0;
+
+ let new_mid = if new_mid == self.curr || 0.0 == interval {
+ new_mid
+ } else {
+ self.lo
+ };
+
+ if new_mid == self.curr {
+ false
+ } else {
+ self.curr = new_mid;
+ true
+ }
+ }
+
+ fn done(lo: $typ, hi: $typ) -> bool {
+ (lo.abs() > hi.abs() && !hi.is_nan()) || lo.is_nan()
+ }
+
+ fn complicate_once(&mut self) -> bool {
+ if BinarySearch::done(self.lo, self.hi) {
+ return false;
+ }
+
+ self.lo = if self.curr == self.lo {
+ self.hi
+ } else {
+ self.curr
+ };
+
+ self.reposition()
+ }
+ }
+ impl ValueTree for BinarySearch {
+ type Value = $typ;
+
+ fn current(&self) -> $typ {
+ self.curr
+ }
+
+ fn simplify(&mut self) -> bool {
+ if BinarySearch::done(self.lo, self.hi) {
+ return false;
+ }
+
+ self.hi = self.curr;
+ if self.reposition() {
+ self.ensure_acceptable();
+ true
+ } else {
+ false
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ if self.complicate_once() {
+ self.ensure_acceptable();
+ true
+ } else {
+ false
+ }
+ }
+ }
+
+ numeric_api!($typ, $sample_typ, 0.0);
+ }
+ };
+}
+
+float_bin_search!(f32, F32U);
+float_bin_search!(f64, F64U);
+
+#[cfg(test)]
+mod test {
+ use crate::strategy::*;
+ use crate::test_runner::*;
+
+ use super::*;
+
+ #[test]
+ fn u8_inclusive_end_included() {
+ let mut runner = TestRunner::deterministic();
+ let mut ok = 0;
+ for _ in 0..20 {
+ let tree = (0..=1).new_tree(&mut runner).unwrap();
+ let test = runner.run_one(tree, |v| {
+ prop_assert_eq!(v, 1);
+ Ok(())
+ });
+ if test.is_ok() {
+ ok += 1;
+ }
+ }
+ assert!(ok > 1, "inclusive end not included.");
+ }
+
+ #[test]
+ fn u8_inclusive_to_end_included() {
+ let mut runner = TestRunner::deterministic();
+ let mut ok = 0;
+ for _ in 0..20 {
+ let tree = (..=1u8).new_tree(&mut runner).unwrap();
+ let test = runner.run_one(tree, |v| {
+ prop_assert_eq!(v, 1);
+ Ok(())
+ });
+ if test.is_ok() {
+ ok += 1;
+ }
+ }
+ assert!(ok > 1, "inclusive end not included.");
+ }
+
+ #[test]
+ fn i8_binary_search_always_converges() {
+ fn assert_converges<P: Fn(i32) -> bool>(start: i8, pass: P) {
+ let mut state = i8::BinarySearch::new(start);
+ loop {
+ if !pass(state.current() as i32) {
+ if !state.simplify() {
+ break;
+ }
+ } else {
+ if !state.complicate() {
+ break;
+ }
+ }
+ }
+
+ assert!(!pass(state.current() as i32));
+ assert!(
+ pass(state.current() as i32 - 1)
+ || pass(state.current() as i32 + 1)
+ );
+ }
+
+ for start in -128..0 {
+ for target in start + 1..1 {
+ assert_converges(start as i8, |v| v > target);
+ }
+ }
+
+ for start in 0..128 {
+ for target in 0..start {
+ assert_converges(start as i8, |v| v < target);
+ }
+ }
+ }
+
+ #[test]
+ fn u8_binary_search_always_converges() {
+ fn assert_converges<P: Fn(u32) -> bool>(start: u8, pass: P) {
+ let mut state = u8::BinarySearch::new(start);
+ loop {
+ if !pass(state.current() as u32) {
+ if !state.simplify() {
+ break;
+ }
+ } else {
+ if !state.complicate() {
+ break;
+ }
+ }
+ }
+
+ assert!(!pass(state.current() as u32));
+ assert!(pass(state.current() as u32 - 1));
+ }
+
+ for start in 0..255 {
+ for target in 0..start {
+ assert_converges(start as u8, |v| v <= target);
+ }
+ }
+ }
+
+ #[test]
+ fn signed_integer_range_including_zero_converges_to_zero() {
+ let mut runner = TestRunner::default();
+ for _ in 0..100 {
+ let mut state = (-42i32..64i32).new_tree(&mut runner).unwrap();
+ let init_value = state.current();
+ assert!(init_value >= -42 && init_value < 64);
+
+ while state.simplify() {
+ let v = state.current();
+ assert!(v >= -42 && v < 64);
+ }
+
+ assert_eq!(0, state.current());
+ }
+ }
+
+ #[test]
+ fn negative_integer_range_stays_in_bounds() {
+ let mut runner = TestRunner::default();
+ for _ in 0..100 {
+ let mut state = (..-42i32).new_tree(&mut runner).unwrap();
+ let init_value = state.current();
+ assert!(init_value < -42);
+
+ while state.simplify() {
+ assert!(
+ state.current() < -42,
+ "Violated bounds: {}",
+ state.current()
+ );
+ }
+
+ assert_eq!(-43, state.current());
+ }
+ }
+
+ #[test]
+ fn positive_signed_integer_range_stays_in_bounds() {
+ let mut runner = TestRunner::default();
+ for _ in 0..100 {
+ let mut state = (42i32..).new_tree(&mut runner).unwrap();
+ let init_value = state.current();
+ assert!(init_value >= 42);
+
+ while state.simplify() {
+ assert!(
+ state.current() >= 42,
+ "Violated bounds: {}",
+ state.current()
+ );
+ }
+
+ assert_eq!(42, state.current());
+ }
+ }
+
+ #[test]
+ fn unsigned_integer_range_stays_in_bounds() {
+ let mut runner = TestRunner::default();
+ for _ in 0..100 {
+ let mut state = (42u32..56u32).new_tree(&mut runner).unwrap();
+ let init_value = state.current();
+ assert!(init_value >= 42 && init_value < 56);
+
+ while state.simplify() {
+ assert!(
+ state.current() >= 42,
+ "Violated bounds: {}",
+ state.current()
+ );
+ }
+
+ assert_eq!(42, state.current());
+ }
+ }
+
+ mod contract_sanity {
+ macro_rules! contract_sanity {
+ ($t:tt) => {
+ mod $t {
+ use crate::strategy::check_strategy_sanity;
+
+ const FOURTY_TWO: $t = 42 as $t;
+ const FIFTY_SIX: $t = 56 as $t;
+
+ #[test]
+ fn range() {
+ check_strategy_sanity(FOURTY_TWO..FIFTY_SIX, None);
+ }
+
+ #[test]
+ fn range_inclusive() {
+ check_strategy_sanity(FOURTY_TWO..=FIFTY_SIX, None);
+ }
+
+ #[test]
+ fn range_to() {
+ check_strategy_sanity(..FIFTY_SIX, None);
+ }
+
+ #[test]
+ fn range_to_inclusive() {
+ check_strategy_sanity(..=FIFTY_SIX, None);
+ }
+
+ #[test]
+ fn range_from() {
+ check_strategy_sanity(FOURTY_TWO.., None);
+ }
+ }
+ };
+ }
+ contract_sanity!(u8);
+ contract_sanity!(i8);
+ contract_sanity!(u16);
+ contract_sanity!(i16);
+ contract_sanity!(u32);
+ contract_sanity!(i32);
+ contract_sanity!(u64);
+ contract_sanity!(i64);
+ contract_sanity!(usize);
+ contract_sanity!(isize);
+ contract_sanity!(f32);
+ contract_sanity!(f64);
+ }
+
+ #[test]
+ fn unsigned_integer_binsearch_simplify_complicate_contract_upheld() {
+ check_strategy_sanity(0u32..1000u32, None);
+ check_strategy_sanity(0u32..1u32, None);
+ }
+
+ #[test]
+ fn signed_integer_binsearch_simplify_complicate_contract_upheld() {
+ check_strategy_sanity(0i32..1000i32, None);
+ check_strategy_sanity(0i32..1i32, None);
+ }
+
+ #[test]
+ fn positive_float_simplifies_to_zero() {
+ let mut runner = TestRunner::default();
+ let mut value = (0.0f64..2.0).new_tree(&mut runner).unwrap();
+
+ while value.simplify() {}
+
+ assert_eq!(0.0, value.current());
+ }
+
+ #[test]
+ fn positive_float_simplifies_to_base() {
+ let mut runner = TestRunner::default();
+ let mut value = (1.0f64..2.0).new_tree(&mut runner).unwrap();
+
+ while value.simplify() {}
+
+ assert_eq!(1.0, value.current());
+ }
+
+ #[test]
+ fn negative_float_simplifies_to_zero() {
+ let mut runner = TestRunner::default();
+ let mut value = (-2.0f64..0.0).new_tree(&mut runner).unwrap();
+
+ while value.simplify() {}
+
+ assert_eq!(0.0, value.current());
+ }
+
+ #[test]
+ fn positive_float_complicates_to_original() {
+ let mut runner = TestRunner::default();
+ let mut value = (1.0f64..2.0).new_tree(&mut runner).unwrap();
+ let orig = value.current();
+
+ assert!(value.simplify());
+ while value.complicate() {}
+
+ assert_eq!(orig, value.current());
+ }
+
+ #[test]
+ fn positive_infinity_simplifies_directly_to_zero() {
+ let mut value = f64::BinarySearch::new(::std::f64::INFINITY);
+
+ assert!(value.simplify());
+ assert_eq!(0.0, value.current());
+ assert!(value.complicate());
+ assert_eq!(::std::f64::INFINITY, value.current());
+ assert!(!value.clone().complicate());
+ assert!(!value.clone().simplify());
+ }
+
+ #[test]
+ fn negative_infinity_simplifies_directly_to_zero() {
+ let mut value = f64::BinarySearch::new(::std::f64::NEG_INFINITY);
+
+ assert!(value.simplify());
+ assert_eq!(0.0, value.current());
+ assert!(value.complicate());
+ assert_eq!(::std::f64::NEG_INFINITY, value.current());
+ assert!(!value.clone().complicate());
+ assert!(!value.clone().simplify());
+ }
+
+ #[test]
+ fn nan_simplifies_directly_to_zero() {
+ let mut value = f64::BinarySearch::new(::std::f64::NAN);
+
+ assert!(value.simplify());
+ assert_eq!(0.0, value.current());
+ assert!(value.complicate());
+ assert!(value.current().is_nan());
+ assert!(!value.clone().complicate());
+ assert!(!value.clone().simplify());
+ }
+
+ #[test]
+ fn float_simplifies_to_smallest_normal() {
+ let mut runner = TestRunner::default();
+ let mut value = (::std::f64::MIN_POSITIVE..2.0)
+ .new_tree(&mut runner)
+ .unwrap();
+
+ while value.simplify() {}
+
+ assert_eq!(::std::f64::MIN_POSITIVE, value.current());
+ }
+
+ macro_rules! float_generation_test_body {
+ ($strategy:ident, $typ:ident) => {
+ use std::num::FpCategory;
+
+ let strategy = $strategy;
+ let bits = strategy.normal_bits();
+
+ let mut seen_positive = 0;
+ let mut seen_negative = 0;
+ let mut seen_normal = 0;
+ let mut seen_subnormal = 0;
+ let mut seen_zero = 0;
+ let mut seen_infinite = 0;
+ let mut seen_quiet_nan = 0;
+ let mut seen_signaling_nan = 0;
+ let mut runner = TestRunner::deterministic();
+
+ // Check whether this version of Rust honours the NaN payload in
+ // from_bits
+ let fidelity_1 = f32::from_bits(0x7F80_0001).to_bits();
+ let fidelity_2 = f32::from_bits(0xFF80_0001).to_bits();
+ let nan_fidelity = fidelity_1 != fidelity_2;
+
+ for _ in 0..1024 {
+ let mut tree = strategy.new_tree(&mut runner).unwrap();
+ let mut increment = 1;
+
+ loop {
+ let value = tree.current();
+
+ let sign = value.signum(); // So we correctly handle -0
+ if sign < 0.0 {
+ prop_assert!(bits.contains(FloatTypes::NEGATIVE));
+ seen_negative += increment;
+ } else if sign > 0.0 {
+ // i.e., not NaN
+ prop_assert!(bits.contains(FloatTypes::POSITIVE));
+ seen_positive += increment;
+ }
+
+ match value.classify() {
+ FpCategory::Nan if nan_fidelity => {
+ let raw = value.to_bits();
+ let is_negative = raw << 1 >> 1 != raw;
+ if is_negative {
+ prop_assert!(
+ bits.contains(FloatTypes::NEGATIVE)
+ );
+ seen_negative += increment;
+ } else {
+ prop_assert!(
+ bits.contains(FloatTypes::POSITIVE)
+ );
+ seen_positive += increment;
+ }
+
+ let is_quiet = raw & ($typ::EXP_MASK >> 1)
+ == ::std::$typ::NAN.to_bits()
+ & ($typ::EXP_MASK >> 1);
+ if is_quiet {
+ // x86/AMD64 turn signalling NaNs into quiet
+ // NaNs quite aggressively depending on what
+ // registers LLVM decides to use to pass the
+ // value around, so accept either case here.
+ prop_assert!(
+ bits.contains(FloatTypes::QUIET_NAN)
+ || bits.contains(
+ FloatTypes::SIGNALING_NAN
+ )
+ );
+ seen_quiet_nan += increment;
+ seen_signaling_nan += increment;
+ } else {
+ prop_assert!(
+ bits.contains(FloatTypes::SIGNALING_NAN)
+ );
+ seen_signaling_nan += increment;
+ }
+ }
+
+ FpCategory::Nan => {
+ // Since safe Rust doesn't currently allow
+ // generating any NaN other than one particular
+ // payload, don't check the sign or signallingness
+ // and consider this to be both signs and
+ // signallingness for counting purposes.
+ seen_positive += increment;
+ seen_negative += increment;
+ seen_quiet_nan += increment;
+ seen_signaling_nan += increment;
+ prop_assert!(
+ bits.contains(FloatTypes::QUIET_NAN)
+ || bits.contains(FloatTypes::SIGNALING_NAN)
+ );
+ }
+ FpCategory::Infinite => {
+ prop_assert!(bits.contains(FloatTypes::INFINITE));
+ seen_infinite += increment;
+ }
+ FpCategory::Zero => {
+ prop_assert!(bits.contains(FloatTypes::ZERO));
+ seen_zero += increment;
+ }
+ FpCategory::Subnormal => {
+ prop_assert!(bits.contains(FloatTypes::SUBNORMAL));
+ seen_subnormal += increment;
+ }
+ FpCategory::Normal => {
+ prop_assert!(bits.contains(FloatTypes::NORMAL));
+ seen_normal += increment;
+ }
+ }
+
+ // Don't count simplified values towards the counts
+ increment = 0;
+ if !tree.simplify() {
+ break;
+ }
+ }
+ }
+
+ if bits.contains(FloatTypes::POSITIVE) {
+ prop_assert!(seen_positive > 200);
+ }
+ if bits.contains(FloatTypes::NEGATIVE) {
+ prop_assert!(seen_negative > 200);
+ }
+ if bits.contains(FloatTypes::NORMAL) {
+ prop_assert!(seen_normal > 100);
+ }
+ if bits.contains(FloatTypes::SUBNORMAL) {
+ prop_assert!(seen_subnormal > 5);
+ }
+ if bits.contains(FloatTypes::ZERO) {
+ prop_assert!(seen_zero > 5);
+ }
+ if bits.contains(FloatTypes::INFINITE) {
+ prop_assert!(seen_infinite > 0);
+ }
+ if bits.contains(FloatTypes::QUIET_NAN) {
+ prop_assert!(seen_quiet_nan > 0);
+ }
+ if bits.contains(FloatTypes::SIGNALING_NAN) {
+ prop_assert!(seen_signaling_nan > 0);
+ }
+ };
+ }
+
+ proptest! {
+ #![proptest_config(crate::test_runner::Config::with_cases(1024))]
+
+ #[test]
+ fn f32_any_generates_desired_values(
+ strategy in crate::bits::u32::ANY.prop_map(f32::Any::from_bits)
+ ) {
+ float_generation_test_body!(strategy, f32);
+ }
+
+ #[test]
+ fn f32_any_sanity(
+ strategy in crate::bits::u32::ANY.prop_map(f32::Any::from_bits)
+ ) {
+ check_strategy_sanity(strategy, Some(CheckStrategySanityOptions {
+ strict_complicate_after_simplify: false,
+ .. CheckStrategySanityOptions::default()
+ }));
+ }
+
+ #[test]
+ fn f64_any_generates_desired_values(
+ strategy in crate::bits::u32::ANY.prop_map(f64::Any::from_bits)
+ ) {
+ float_generation_test_body!(strategy, f64);
+ }
+
+ #[test]
+ fn f64_any_sanity(
+ strategy in crate::bits::u32::ANY.prop_map(f64::Any::from_bits)
+ ) {
+ check_strategy_sanity(strategy, Some(CheckStrategySanityOptions {
+ strict_complicate_after_simplify: false,
+ .. CheckStrategySanityOptions::default()
+ }));
+ }
+ }
+}
diff --git a/vendor/proptest/src/num/float_samplers.rs b/vendor/proptest/src/num/float_samplers.rs
new file mode 100644
index 000000000..55b6cd03b
--- /dev/null
+++ b/vendor/proptest/src/num/float_samplers.rs
@@ -0,0 +1,463 @@
+//-
+// Copyright 2022 The proptest 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.
+
+//! Alternative uniform float samplers.
+//! These samplers are used over the ones from `rand` because the ones provided by the
+//! rand crate are prone to overflow. In addition, these are 'high precision' samplers
+//! that are more appropriate for test data.
+//! The samplers work by splitting the range into equally sized intervals and selecting
+//! an iterval at random. That interval is then itself split and a new interval is
+//! selected at random. The process repeats until the interval only contains two
+//! floating point values at the bounds. At that stage, one is selected at random and
+//! returned.
+
+pub(crate) use self::f32::F32U;
+pub(crate) use self::f64::F64U;
+
+macro_rules! float_sampler {
+ ($typ: ident, $int_typ: ident, $wrapper: ident) => {
+ pub mod $typ {
+ use rand::prelude::*;
+ use rand::distributions::uniform::{
+ SampleBorrow, SampleUniform, UniformSampler,
+ };
+ #[cfg(not(feature = "std"))]
+ use num_traits::float::Float;
+
+ #[must_use]
+ // Returns the previous float value. In other words the greatest value representable
+ // as a float such that `next_down(a) < a`. `-0.` is treated as `0.`.
+ fn next_down(a: $typ) -> $typ {
+ debug_assert!(a.is_finite() && a > $typ::MIN, "`next_down` invalid input: {}", a);
+ if a == (0.) {
+ -$typ::from_bits(1)
+ } else if a < 0. {
+ $typ::from_bits(a.to_bits() + 1)
+ } else {
+ $typ::from_bits(a.to_bits() - 1)
+ }
+ }
+
+ #[must_use]
+ // Returns the unit in last place using the definition by John Harrison.
+ // This is the distance between `a` and the next closest float. Note that
+ // `ulp(1) = $typ::EPSILON/2`.
+ fn ulp(a: $typ) -> $typ {
+ debug_assert!(a.is_finite() && a > $typ::MIN, "`ulp` invalid input: {}", a);
+ a.abs() - next_down(a.abs())
+ }
+
+ #[derive(Copy, Clone, Debug)]
+ pub(crate) struct $wrapper($typ);
+
+ impl From<$typ> for $wrapper {
+ fn from(x: $typ) -> Self {
+ $wrapper(x)
+ }
+ }
+ impl From<$wrapper> for $typ {
+ fn from(x: $wrapper) -> Self {
+ x.0
+ }
+ }
+
+ #[derive(Clone, Copy, Debug)]
+ pub(crate) struct FloatUniform {
+ low: $typ,
+ high: $typ,
+ intervals: IntervalCollection,
+ inclusive: bool,
+ }
+
+ impl UniformSampler for FloatUniform {
+
+ type X = $wrapper;
+
+ fn new<B1, B2>(low: B1, high: B2) -> Self
+ where
+ B1: SampleBorrow<Self::X> + Sized,
+ B2: SampleBorrow<Self::X> + Sized,
+ {
+ let low = low.borrow().0;
+ let high = high.borrow().0;
+ FloatUniform {
+ low,
+ high,
+ intervals: split_interval([low, high]),
+ inclusive: false,
+ }
+ }
+
+ fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
+ where
+ B1: SampleBorrow<Self::X> + Sized,
+ B2: SampleBorrow<Self::X> + Sized,
+ {
+ let low = low.borrow().0;
+ let high = high.borrow().0;
+
+ FloatUniform {
+ low,
+ high,
+ intervals: split_interval([low, high]),
+ inclusive: true,
+ }
+ }
+
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
+ let mut intervals = self.intervals;
+ while intervals.count > 1 {
+ let new_interval = intervals.get(rng.gen_range(0..intervals.count));
+ intervals = split_interval(new_interval);
+ }
+ let last = intervals.get(0);
+ let result = *last.choose(rng).expect("Slice is not empty");
+
+ // These results could happen because the first split might
+ // overshoot one of the bounds. We could resample in this
+ // case but for testing data this is not a problem.
+ let clamped_result = if result < self.low {
+ debug_assert!(self.low - result < self.intervals.step);
+ self.low
+ } else if result > self.high{
+ debug_assert!(result - self.high < self.intervals.step);
+ self.high
+ } else {
+ result
+ };
+
+ if !self.inclusive && clamped_result == self.high {
+ return $wrapper(next_down(self.high));
+ };
+
+ $wrapper(clamped_result)
+ }
+ }
+
+ impl SampleUniform for $wrapper {
+ type Sampler = FloatUniform;
+ }
+
+ // Divides the range [low, high] into intervals of size epsilon * max(abs(low, high));
+ // Note that the one interval may extend out of the range.
+ #[derive(Clone, Copy, Debug)]
+ struct IntervalCollection {
+ start: $typ,
+ step: $typ,
+ count: $int_typ,
+ }
+
+ fn split_interval([low, high]: [$typ; 2]) -> IntervalCollection {
+ assert!(low.is_finite(), "low finite");
+ assert!(high.is_finite(), "high finite");
+ assert!(high - low > 0., "invalid range");
+
+ let min_abs = $typ::min(low.abs(), high.abs());
+ let max_abs = $typ::max(low.abs(), high.abs());
+
+ let gap = ulp(max_abs);
+
+ let (start, step) = if low.abs() < high.abs() {
+ (high, -gap)
+ } else {
+ (low, gap)
+ };
+
+ let min_gaps = min_abs / gap;
+ let max_gaps = max_abs / gap;
+ debug_assert!(
+ max_gaps.floor() == max_gaps,
+ "max_gaps is an integer"
+ );
+
+ let count = if low.signum() == high.signum() {
+ max_gaps as $int_typ - min_gaps.floor() as $int_typ
+ } else {
+ // `step` is a power of two so `min_gaps` won't be rounded
+ // except possibly to 0.
+ if min_gaps == 0. && min_abs > 0. {
+ max_gaps as $int_typ + 1
+ } else {
+ max_gaps as $int_typ + min_gaps.ceil() as $int_typ
+ }
+ };
+
+ debug_assert!(count - 1 <= 2 * MAX_PRECISE_INT);
+
+ IntervalCollection {
+ start,
+ step,
+ count,
+ }
+ }
+
+
+ impl IntervalCollection {
+ fn get(&self, index: $int_typ) -> [$typ; 2] {
+ assert!(index < self.count, "index out of bounds");
+
+ // `index` might be greater that `MAX_PERCISE_INT`
+ // which means `MAX_PRECIST_INT as $typ` would round
+ // to a different number. Fortunately, `index` will
+ // never be larger than `2 * MAX_PRECISE_INT` (as
+ // asserted above).
+ let x = ((index / 2) as $typ).mul_add(
+ 2. * self.step,
+ (index % 2) as $typ * self.step + self.start,
+ );
+
+ let y = x + self.step;
+
+ if self.step > 0. {
+ [x, y]
+ } else {
+ [y, x]
+ }
+ }
+ }
+
+
+ // Values greater than MAX_PRECISE_INT may be rounded when converted to float.
+ const MAX_PRECISE_INT: $int_typ =
+ (2 as $int_typ).pow($typ::MANTISSA_DIGITS);
+
+ #[cfg(test)]
+ mod test {
+
+ use super::*;
+ use crate::prelude::*;
+
+ fn sort((left, right): ($typ, $typ)) -> ($typ, $typ) {
+ if left < right {
+ (left, right)
+ } else {
+ (right, left)
+ }
+ }
+
+ fn finite() -> impl Strategy<Value = $typ> {
+ prop::num::$typ::NEGATIVE
+ | prop::num::$typ::POSITIVE
+ | prop::num::$typ::NORMAL
+ | prop::num::$typ::SUBNORMAL
+ | prop::num::$typ::ZERO
+ }
+
+ fn bounds() -> impl Strategy<Value = ($typ, $typ)> {
+ (finite(), finite())
+ .prop_filter("Bounds can't be equal", |(a, b)| a != b)
+ .prop_map(sort)
+ }
+
+ #[test]
+ fn range_test() {
+ use crate::test_runner::{RngAlgorithm, TestRng};
+
+ let mut test_rng = TestRng::deterministic_rng(RngAlgorithm::default());
+ let (low, high) = (-1., 10.);
+ let uniform = FloatUniform::new($wrapper(low), $wrapper(high));
+
+ let samples = (0..100)
+ .map(|_| $typ::from(uniform.sample(&mut test_rng)));
+ for s in samples {
+ assert!(low <= s && s < high);
+ }
+ }
+
+ #[test]
+ fn range_end_bound_test() {
+ use crate::test_runner::{RngAlgorithm, TestRng};
+
+ let mut test_rng = TestRng::deterministic_rng(RngAlgorithm::default());
+ let (low, high) = (1., 1. + $typ::EPSILON);
+ let uniform = FloatUniform::new($wrapper(low), $wrapper(high));
+
+ let mut samples = (0..100)
+ .map(|_| $typ::from(uniform.sample(&mut test_rng)));
+ assert!(samples.all(|x| x == 1.));
+ }
+
+ #[test]
+ fn inclusive_range_test() {
+ use crate::test_runner::{RngAlgorithm, TestRng};
+
+ let mut test_rng = TestRng::deterministic_rng(RngAlgorithm::default());
+ let (low, high) = (-1., 10.);
+ let uniform = FloatUniform::new_inclusive($wrapper(low), $wrapper(high));
+
+ let samples = (0..100)
+ .map(|_| $typ::from(uniform.sample(&mut test_rng)));
+ for s in samples {
+ assert!(low <= s && s <= high);
+ }
+ }
+
+ #[test]
+ fn inclusive_range_end_bound_test() {
+ use crate::test_runner::{RngAlgorithm, TestRng};
+
+ let mut test_rng = TestRng::deterministic_rng(RngAlgorithm::default());
+ let (low, high) = (1., 1. + $typ::EPSILON);
+ let uniform = FloatUniform::new_inclusive($wrapper(low), $wrapper(high));
+
+ let mut samples = (0..100)
+ .map(|_| $typ::from(uniform.sample(&mut test_rng)));
+ assert!(samples.any(|x| x == 1. + $typ::EPSILON));
+ }
+
+ #[test]
+ fn all_floats_in_range_are_possible_1() {
+ use crate::test_runner::{RngAlgorithm, TestRng};
+
+ let mut test_rng = TestRng::deterministic_rng(RngAlgorithm::default());
+ let (low, high) = (1. - $typ::EPSILON, 1. + $typ::EPSILON);
+ let uniform = FloatUniform::new_inclusive($wrapper(low), $wrapper(high));
+
+ let mut samples = (0..100)
+ .map(|_| $typ::from(uniform.sample(&mut test_rng)));
+ assert!(samples.any(|x| x == 1. - $typ::EPSILON / 2.));
+ }
+
+ #[test]
+ fn all_floats_in_range_are_possible_2() {
+ use crate::test_runner::{RngAlgorithm, TestRng};
+
+ let mut test_rng = TestRng::deterministic_rng(RngAlgorithm::default());
+ let (low, high) = (0., MAX_PRECISE_INT as $typ);
+ let uniform = FloatUniform::new_inclusive($wrapper(low), $wrapper(high));
+
+ let mut samples = (0..100)
+ .map(|_| $typ::from(uniform.sample(&mut test_rng)))
+ .map(|x| x.fract());
+
+ assert!(samples.any(|x| x != 0.));
+ }
+
+ #[test]
+ fn max_precise_int_plus_one_is_rounded_down() {
+ assert_eq!(((MAX_PRECISE_INT + 1) as $typ) as $int_typ, MAX_PRECISE_INT);
+ }
+
+ proptest! {
+ #[test]
+ fn next_down_less_than_float(val in finite()) {
+ prop_assume!(val > $typ::MIN);
+ prop_assert!(next_down(val) < val);
+ }
+
+ #[test]
+ fn no_value_between_float_and_next_down(val in finite()) {
+ prop_assume!(val > $typ::MIN);
+ let prev = next_down(val);
+ let avg = prev / 2. + val / 2.;
+ prop_assert!(avg == prev || avg == val);
+ }
+
+ #[test]
+ fn values_less_than_or_equal_to_max_precise_int_are_not_rounded(i in 0..=MAX_PRECISE_INT) {
+ prop_assert_eq!((i as $typ) as $int_typ, i);
+ }
+
+ #[test]
+ fn indivisible_intervals_are_split_to_self(val in finite()) {
+ prop_assume!(val > $typ::MIN);
+ let prev = next_down(val);
+ let intervals = split_interval([prev, val]);
+ prop_assert_eq!(intervals.count, 1);
+ }
+
+ #[test]
+ fn split_intervals_are_the_same_size(
+ (low, high) in bounds(),
+ indices: [prop::sample::Index; 32]) {
+
+ let intervals = split_interval([low, high]);
+
+ let size = (intervals.count - 1) as usize;
+ prop_assume!(size > 0);
+
+ let mut it = indices.iter()
+ .map(|i| i.index(size) as $int_typ)
+ .map(|i| intervals.get(i))
+ .map(|[low, high]| high - low);
+
+ let interval_size = it.next().unwrap();
+ let all_equal = it.all(|g| g == interval_size);
+ prop_assert!(all_equal);
+ }
+
+ #[test]
+ fn split_intervals_are_consecutive(
+ (low, high) in bounds(),
+ indices: [prop::sample::Index; 32]) {
+
+ let intervals = split_interval([low, high]);
+
+ let size = (intervals.count - 1) as usize;
+ prop_assume!(size > 1);
+
+ let mut it = indices.iter()
+ .map(|i| i.index(size - 1) as $int_typ)
+ .map(|i| (intervals.get(i), intervals.get(i + 1)));
+
+ let ascending = it.all(|([_, h1], [l2, _])| h1 == l2);
+ let descending = it.all(|([l1, _], [_, h2])| l1 == h2);
+
+ prop_assert!(ascending || descending);
+ }
+
+ #[test]
+ fn first_split_might_slightly_overshoot_one_bound((low, high) in bounds()) {
+ let intervals = split_interval([low, high]);
+ let start = intervals.get(0);
+ let end = intervals.get(intervals.count - 1);
+ let (low_interval, high_interval) = if start[0] < end[0] {
+ (start, end)
+ } else {
+ (end, start)
+ };
+
+ prop_assert!(
+ low == low_interval[0] && high_interval[0] < high && high <= high_interval[1] ||
+ low_interval[0] <= low && low < low_interval[1] && high == high_interval[1]);
+ }
+
+ #[test]
+ fn subsequent_splits_always_match_bounds(
+ (low, high) in bounds(),
+ index: prop::sample::Index) {
+ // This property is true because the distances of split intervals of
+ // are powers of two so the smaller one always divides the larger.
+
+ let intervals = split_interval([low, high]);
+ let size = (intervals.count - 1) as usize;
+
+ let interval = intervals.get(index.index(size) as $int_typ);
+ let small_intervals = split_interval(interval);
+
+ let start = small_intervals.get(0);
+ let end = small_intervals.get(small_intervals.count - 1);
+ let (low_interval, high_interval) = if start[0] < end[0] {
+ (start, end)
+ } else {
+ (end, start)
+ };
+
+ prop_assert!(
+ interval[0] == low_interval[0] &&
+ interval[1] == high_interval[1]);
+ }
+ }
+ }
+ }
+ };
+}
+
+float_sampler!(f32, u32, F32U);
+float_sampler!(f64, u64, F64U);
diff --git a/vendor/proptest/src/option.rs b/vendor/proptest/src/option.rs
new file mode 100644
index 000000000..466ada687
--- /dev/null
+++ b/vendor/proptest/src/option.rs
@@ -0,0 +1,271 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+//! Strategies for generating `std::Option` values.
+
+#![cfg_attr(feature = "cargo-clippy", allow(expl_impl_clone_on_copy))]
+
+use core::fmt;
+use core::marker::PhantomData;
+
+use crate::std_facade::Arc;
+use crate::strategy::*;
+use crate::test_runner::*;
+
+//==============================================================================
+// Probability
+//==============================================================================
+
+/// Creates a `Probability` from some value that is convertible into it.
+///
+/// # Panics
+///
+/// Panics if the converted to probability would lie
+/// outside interval `[0.0, 1.0]`. Consult the `Into` (or `From`)
+/// implementations for more details.
+pub fn prob(from: impl Into<Probability>) -> Probability {
+ from.into()
+}
+
+impl Default for Probability {
+ /// The default probability is 0.5, or 50% chance.
+ fn default() -> Self {
+ prob(0.5)
+ }
+}
+
+impl From<f64> for Probability {
+ /// Creates a `Probability` from a `f64`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the probability is outside interval `[0.0, 1.0]`.
+ fn from(prob: f64) -> Self {
+ Probability::new(prob)
+ }
+}
+
+impl Probability {
+ /// Creates a `Probability` from a `f64`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the probability is outside interval `[0.0, 1.0]`.
+ pub fn new(prob: f64) -> Self {
+ assert!(prob >= 0.0 && prob <= 1.0);
+ Probability(prob)
+ }
+
+ // Don't rely on these existing internally:
+
+ /// Merges self together with some other argument producing a product
+ /// type expected by some implementations of `A: Arbitrary` in
+ /// `A::Parameters`. This can be more ergonomic to work with and may
+ /// help type inference.
+ pub fn with<X>(self, and: X) -> product_type![Self, X] {
+ product_pack![self, and]
+ }
+
+ /// Merges self together with some other argument generated with a
+ /// default value producing a product type expected by some
+ /// implementations of `A: Arbitrary` in `A::Parameters`.
+ /// This can be more ergonomic to work with and may help type inference.
+ pub fn lift<X: Default>(self) -> product_type![Self, X] {
+ self.with(Default::default())
+ }
+}
+
+#[cfg(feature = "frunk")]
+use frunk_core::generic::Generic;
+
+#[cfg(feature = "frunk")]
+impl Generic for Probability {
+ type Repr = f64;
+
+ /// Converts the `Probability` into an `f64`.
+ fn into(self) -> Self::Repr {
+ self.0
+ }
+
+ /// Creates a `Probability` from a `f64`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the probability is outside interval `[0.0, 1.0]`.
+ fn from(r: Self::Repr) -> Self {
+ r.into()
+ }
+}
+
+impl From<Probability> for f64 {
+ fn from(p: Probability) -> Self {
+ p.0
+ }
+}
+
+/// A probability in the range `[0.0, 1.0]` with a default of `0.5`.
+#[derive(Clone, Copy, PartialEq, Debug)]
+pub struct Probability(f64);
+
+//==============================================================================
+// Strategies for Option
+//==============================================================================
+
+mapfn! {
+ [] fn WrapSome[<T : fmt::Debug>](t: T) -> Option<T> {
+ Some(t)
+ }
+}
+
+#[must_use = "strategies do nothing unless used"]
+struct NoneStrategy<T>(PhantomData<T>);
+impl<T> Clone for NoneStrategy<T> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+impl<T> Copy for NoneStrategy<T> {}
+impl<T> fmt::Debug for NoneStrategy<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "NoneStrategy")
+ }
+}
+impl<T: fmt::Debug> Strategy for NoneStrategy<T> {
+ type Tree = Self;
+ type Value = Option<T>;
+
+ fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
+ Ok(*self)
+ }
+}
+impl<T: fmt::Debug> ValueTree for NoneStrategy<T> {
+ type Value = Option<T>;
+
+ fn current(&self) -> Option<T> {
+ None
+ }
+ fn simplify(&mut self) -> bool {
+ false
+ }
+ fn complicate(&mut self) -> bool {
+ false
+ }
+}
+
+opaque_strategy_wrapper! {
+ /// Strategy which generates `Option` values whose inner `Some` values are
+ /// generated by another strategy.
+ ///
+ /// Constructed by other functions in this module.
+ #[derive(Clone)]
+ pub struct OptionStrategy[<T>][where T : Strategy]
+ (TupleUnion<(WA<NoneStrategy<T::Value>>,
+ WA<statics::Map<T, WrapSome>>)>)
+ -> OptionValueTree<T>;
+ /// `ValueTree` type corresponding to `OptionStrategy`.
+ pub struct OptionValueTree[<T>][where T : Strategy]
+ (TupleUnionValueTree<(
+ LazyValueTree<NoneStrategy<T::Value>>,
+ Option<LazyValueTree<statics::Map<T, WrapSome>>>,
+ )>)
+ -> Option<T::Value>;
+}
+
+// XXX Unclear why this is necessary; #[derive(Debug)] *should* generate
+// exactly this, but for some reason it adds a `T::Value : Debug` constraint as
+// well.
+impl<T: Strategy + fmt::Debug> fmt::Debug for OptionStrategy<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "OptionStrategy({:?})", self.0)
+ }
+}
+
+impl<T: Strategy> Clone for OptionValueTree<T>
+where
+ T::Tree: Clone,
+{
+ fn clone(&self) -> Self {
+ OptionValueTree(self.0.clone())
+ }
+}
+
+impl<T: Strategy> fmt::Debug for OptionValueTree<T>
+where
+ T::Tree: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "OptionValueTree({:?})", self.0)
+ }
+}
+
+/// Return a strategy producing `Optional` values wrapping values from the
+/// given delegate strategy.
+///
+/// `Some` values shrink to `None`.
+///
+/// `Some` and `None` are each chosen with 50% probability.
+pub fn of<T: Strategy>(t: T) -> OptionStrategy<T> {
+ weighted(Probability::default(), t)
+}
+
+/// Return a strategy producing `Optional` values wrapping values from the
+/// given delegate strategy.
+///
+/// `Some` values shrink to `None`.
+///
+/// `Some` is chosen with a probability given by `probability_of_some`, which
+/// must be between 0.0 and 1.0, both exclusive.
+pub fn weighted<T: Strategy>(
+ probability_of_some: impl Into<Probability>,
+ t: T,
+) -> OptionStrategy<T> {
+ let prob = probability_of_some.into().into();
+ let (weight_some, weight_none) = float_to_weight(prob);
+
+ OptionStrategy(TupleUnion::new((
+ (weight_none, Arc::new(NoneStrategy(PhantomData))),
+ (weight_some, Arc::new(statics::Map::new(t, WrapSome))),
+ )))
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ fn count_some_of_1000(s: OptionStrategy<Just<i32>>) -> u32 {
+ let mut runner = TestRunner::deterministic();
+ let mut count = 0;
+ for _ in 0..1000 {
+ count +=
+ s.new_tree(&mut runner).unwrap().current().is_some() as u32;
+ }
+
+ count
+ }
+
+ #[test]
+ fn probability_defaults_to_0p5() {
+ let count = count_some_of_1000(of(Just(42i32)));
+ assert!(count > 450 && count < 550);
+ }
+
+ #[test]
+ fn probability_handled_correctly() {
+ let count = count_some_of_1000(weighted(0.9, Just(42i32)));
+ assert!(count > 800 && count < 950);
+
+ let count = count_some_of_1000(weighted(0.1, Just(42i32)));
+ assert!(count > 50 && count < 150);
+ }
+
+ #[test]
+ fn test_sanity() {
+ check_strategy_sanity(of(0i32..1000i32), None);
+ }
+}
diff --git a/vendor/proptest/src/prelude.rs b/vendor/proptest/src/prelude.rs
new file mode 100644
index 000000000..8bdfd5db5
--- /dev/null
+++ b/vendor/proptest/src/prelude.rs
@@ -0,0 +1,53 @@
+//-
+// Copyright 2017, 2018, 2019 The proptest 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.
+
+//! Re-exports the most commonly-needed APIs of proptest.
+//!
+//! This module is intended to be wildcard-imported, i.e.,
+//! `use proptest::prelude::*;`. Note that it re-exports the whole crate itself
+//! under the name `prop`, so you don't need a separate `use proptest;` line.
+//!
+//! In addition to Proptest's own APIs, this also reexports a small portion of
+//! the `rand` crate sufficient to easily use `prop_perturb` and other
+//! functionality that exposes random number generators. Please note that this
+//! is will always be a direct reexport; using these in preference to using the
+//! `rand` crate directly will not provide insulation from the upcoming
+//! revision to the `rand` crate.
+
+pub use crate::arbitrary::{any, any_with, Arbitrary};
+pub use crate::strategy::{BoxedStrategy, Just, SBoxedStrategy, Strategy};
+pub use crate::test_runner::Config as ProptestConfig;
+pub use crate::test_runner::TestCaseError;
+pub use crate::{
+ prop_assert, prop_assert_eq, prop_assert_ne, prop_assume, prop_compose,
+ prop_oneof, proptest,
+};
+
+pub use rand::{Rng, RngCore};
+
+/// Re-exports the entire public API of proptest so that an import of `prelude`
+/// allows simply writing, for example, `prop::num::i32::ANY` rather than
+/// `proptest::num::i32::ANY` plus a separate `use proptest;`.
+pub mod prop {
+ pub use crate::arbitrary;
+ pub use crate::array;
+ pub use crate::bits;
+ pub use crate::bool;
+ pub use crate::char;
+ pub use crate::collection;
+ pub use crate::num;
+ pub use crate::option;
+ pub use crate::result;
+ pub use crate::sample;
+ pub use crate::strategy;
+ #[cfg(feature = "std")]
+ pub use crate::string;
+ pub use crate::test_runner;
+ pub use crate::tuple;
+}
diff --git a/vendor/proptest/src/product_frunk.rs b/vendor/proptest/src/product_frunk.rs
new file mode 100644
index 000000000..b12524d1c
--- /dev/null
+++ b/vendor/proptest/src/product_frunk.rs
@@ -0,0 +1,49 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Defines macros for product type creation, extraction, and the type signature
+//! itself. This version uses `frunk_core`. This mechanism is used to be very
+//! loosely coupled with `frunk_core` so that only `lib.rs` has to be changed
+//! in the event that Rust gets tuple-variadic generics.
+
+macro_rules! product_type {
+ ($factor: ty) => {
+ Hlist![$factor]
+ };
+ ($($factor: ty),*) => {
+ Hlist![$( $factor, )*]
+ };
+ ($($factor: ty),*,) => {
+ Hlist![$( $factor, )*]
+ };
+}
+
+macro_rules! product_pack {
+ ($factor: expr) => {
+ hlist![$factor]
+ };
+ ($($factor: expr),*) => {
+ hlist![$( $factor ),*]
+ };
+ ($($factor: expr),*,) => {
+ hlist![$( $factor ),*]
+ };
+}
+
+macro_rules! product_unpack {
+ ($factor: pat) => {
+ hlist_pat![$factor]
+ };
+ ($($factor: pat),*) => {
+ hlist_pat![$( $factor ),*]
+ };
+ ($($factor: pat),*,) => {
+ hlist_pat![$( $factor ),*]
+ };
+}
diff --git a/vendor/proptest/src/product_tuple.rs b/vendor/proptest/src/product_tuple.rs
new file mode 100644
index 000000000..1c32d9541
--- /dev/null
+++ b/vendor/proptest/src/product_tuple.rs
@@ -0,0 +1,49 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Defines macros for product type creation, extraction, and the type signature
+//! itself. This version uses tuples. This mechanism is used to be very
+//! loosely coupled with `frunk_core` so that only `lib.rs` has to be changed
+//! in the event that Rust gets tuple-variadic generics.
+
+macro_rules! product_type {
+ ($factor: ty) => {
+ ($factor,)
+ };
+ ($($factor: ty),*) => {
+ ( $( $factor, )* )
+ };
+ ($($factor: ty),*,) => {
+ ( $( $factor, )* )
+ };
+}
+
+macro_rules! product_pack {
+ ($factor: expr) => {
+ ($factor,)
+ };
+ ($($factor: expr),*) => {
+ ( $( $factor ),* )
+ };
+ ($($factor: expr),*,) => {
+ ( $( $factor ),* )
+ };
+}
+
+macro_rules! product_unpack {
+ ($factor: pat) => {
+ ($factor,)
+ };
+ ($($factor: pat),*) => {
+ ( $( $factor ),* )
+ };
+ ($($factor: pat),*,) => {
+ ( $( $factor ),* )
+ };
+}
diff --git a/vendor/proptest/src/regex-contrib/README.md b/vendor/proptest/src/regex-contrib/README.md
new file mode 100644
index 000000000..f438d2047
--- /dev/null
+++ b/vendor/proptest/src/regex-contrib/README.md
@@ -0,0 +1,3 @@
+Files in this directory are copied verbatim from the
+https://github.com/rust-lang/regex repository and are used for generating test
+data. They do not become part of the proptest binary.
diff --git a/vendor/proptest/src/regex-contrib/crates_regex.rs b/vendor/proptest/src/regex-contrib/crates_regex.rs
new file mode 100644
index 000000000..1ccfe4710
--- /dev/null
+++ b/vendor/proptest/src/regex-contrib/crates_regex.rs
@@ -0,0 +1,3129 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// 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.
+
+// DO NOT EDIT. Automatically generated by 'scripts/scrape_crates_io.py'
+// on 2018-06-20 09:56:32.820354.
+
+
+
+// autoshutdown-0.1.0: r"\s*(\d+)(\w)\s*"
+consistent!(autoshutdown_0, r"\s*(\d+)(\w)\s*");
+
+// epub-1.1.1: r"/"
+consistent!(epub_0, r"/");
+
+// rpi-info-0.2.0: "^Revision\t+: ([0-9a-fA-F]+)"
+consistent!(rpi_info_0, "^Revision\t+: ([0-9a-fA-F]+)");
+
+// rpi-info-0.2.0: "Serial\t+: ([0-9a-fA-F]+)"
+consistent!(rpi_info_1, "Serial\t+: ([0-9a-fA-F]+)");
+
+// pnet_macros-0.21.0: r"^u([0-9]+)(be|le|he)?$"
+consistent!(pnet_macros_0, r"^u([0-9]+)(be|le|he)?$");
+
+// iban_validate-1.0.3: r"^[A-Z]{2}\d{2}[A-Z\d]{1,30}$"
+consistent!(iban_validate_0, r"^[A-Z]{2}\d{2}[A-Z\d]{1,30}$");
+
+// markifier-0.1.0: r".*\[(?P<percent>.+)%.*\].*"
+consistent!(markifier_0, r".*\[(?P<percent>.+)%.*\].*");
+
+// mallumo-0.3.0: r"(#include) (\S*)(.*)"
+consistent!(mallumo_0, r"(#include) (\S*)(.*)");
+
+// mallumo-0.3.0: r"(ERROR: \d+:)(\d+)(: )(.+)"
+consistent!(mallumo_1, r"(ERROR: \d+:)(\d+)(: )(.+)");
+
+// mallumo-0.3.0: r"(\d+\()(\d+)(?:\) : )(.+)"
+consistent!(mallumo_2, r"(\d+\()(\d+)(?:\) : )(.+)");
+
+// magnet_more-0.0.1: r"(.+?)(\[.*?\])?"
+consistent!(magnet_more_0, r"(.+?)(\[.*?\])?");
+
+// magnet_app-0.0.1: r":(?P<k>[a-zA-Z_]+)"
+consistent!(magnet_app_0, r":(?P<k>[a-zA-Z_]+)");
+
+// yubibomb-0.2.0: r"^\d{6}(?:\s*,\s*\d{6})*$"
+consistent!(yubibomb_0, r"^\d{6}(?:\s*,\s*\d{6})*$");
+
+// multirust-rs-0.0.4: r"[\\/]([^\\/?]+)(\?.*)?$"
+consistent!(multirust_rs_0, r"[\\/]([^\\/?]+)(\?.*)?$");
+
+// hueclient-0.3.2: "\"[a-z]*\":null"
+consistent!(hueclient_0, "\"[a-z]*\":null");
+
+// hueclient-0.3.2: ",+"
+consistent!(hueclient_1, ",+");
+
+// hueclient-0.3.2: ",\\}"
+consistent!(hueclient_2, ",\\}");
+
+// hueclient-0.3.2: "\\{,"
+consistent!(hueclient_3, "\\{,");
+
+// aerial-0.1.0: r"[a-zA-Z_\$][a-zA-Z_0-9]*"
+consistent!(aerial_0, r"[a-zA-Z_\$][a-zA-Z_0-9]*");
+
+// aerial-0.1.0: r"thi[sng]+"
+consistent!(aerial_1, r"thi[sng]+");
+
+// rvue-0.1.0: r"(.+)\s+\((.+?)\)"
+consistent!(rvue_0, r"(.+)\s+\((.+?)\)");
+
+// rvue-0.1.0: r"([\d\.]+)\s*out\s*of\s*([\d\.]+)"
+consistent!(rvue_1, r"([\d\.]+)\s*out\s*of\s*([\d\.]+)");
+
+// rvue-0.1.0: r"^([\d\.]+)\s*(?:\(\))?$"
+consistent!(rvue_2, r"^([\d\.]+)\s*(?:\(\))?$");
+
+// rvue-0.1.0: r"([\d\.]+)\s*Points\s*Possible"
+consistent!(rvue_3, r"([\d\.]+)\s*Points\s*Possible");
+
+// rvue-0.1.0: r"([\d\.]+)\s*/\s*([\d\.]+)"
+consistent!(rvue_4, r"([\d\.]+)\s*/\s*([\d\.]+)");
+
+// rvsim-0.1.0: r"_?([_a-z0-9]+)\s*:\s*([_a-z0-9]+)\s*[,)]"
+consistent!(rvsim_0, r"_?([_a-z0-9]+)\s*:\s*([_a-z0-9]+)\s*[,)]");
+
+// nereon-0.1.4: "(.*[^\\\\])\\{\\}(.*)"
+consistent!(nereon_0, "(.*[^\\\\])\\{\\}(.*)");
+
+// next_episode-0.3.0: r"((?i)^(.+).s(\d+)e(\d+).*)$"
+consistent!(next_episode_0, r"((?i)^(.+).s(\d+)e(\d+).*)$");
+
+// migrant_lib-0.19.2: r"[^a-z0-9-]+"
+consistent!(migrant_lib_0, r"[^a-z0-9-]+");
+
+// migrant_lib-0.19.2: r"[0-9]{14}_[a-z0-9-]+"
+consistent!(migrant_lib_1, r"[0-9]{14}_[a-z0-9-]+");
+
+// migrant_lib-0.19.2: r"([0-9]{14}_)?[a-z0-9-]+"
+consistent!(migrant_lib_2, r"([0-9]{14}_)?[a-z0-9-]+");
+
+// minipre-0.2.0: "$_"
+consistent!(minipre_0, "$_");
+
+// minifier-0.0.13: r">\s+<"
+consistent!(minifier_0, r">\s+<");
+
+// minifier-0.0.13: r"\s{2,}|[\r\n]"
+consistent!(minifier_1, r"\s{2,}|[\r\n]");
+
+// minifier-0.0.13: r"<(style|script)[\w|\s].*?>"
+consistent!(minifier_2, r"<(style|script)[\w|\s].*?>");
+
+// minifier-0.0.13: "<!--(.|\n)*?-->"
+consistent!(minifier_3, "<!--(.|\n)*?-->");
+
+// minifier-0.0.13: r"<\w.*?>"
+consistent!(minifier_4, r"<\w.*?>");
+
+// minifier-0.0.13: r" \s+|\s +"
+consistent!(minifier_5, r" \s+|\s +");
+
+// minifier-0.0.13: r"\w\s+\w"
+consistent!(minifier_6, r"\w\s+\w");
+
+// minifier-0.0.13: r"'\s+>"
+consistent!(minifier_7, r"'\s+>");
+
+// minifier-0.0.13: r"\d\s+>"
+consistent!(minifier_8, r"\d\s+>");
+
+// ggp-rs-0.1.2: r"(?P<relation>\([^)]+\))|(?P<prop>[a-zA-Z0-9_]+)"
+consistent!(ggp_rs_0, r"(?P<relation>\([^)]+\))|(?P<prop>[a-zA-Z0-9_]+)");
+
+// ggp-rs-0.1.2: r"\((.*)\)."
+consistent!(ggp_rs_1, r"\((.*)\).");
+
+// poe-superfilter-0.2.0: "[A-Za-z0-9_]"
+consistent!(poe_superfilter_0, "[A-Za-z0-9_]");
+
+// poke-a-mango-0.5.0: r"(\d+)x(\d+)"
+consistent!(poke_a_mango_0, r"(\d+)x(\d+)");
+
+// pop3-rs-0.1.0: r"(?P<nmsg>\d+) (?P<size>\d+)"
+consistent!(pop3_rs_0, r"(?P<nmsg>\d+) (?P<size>\d+)");
+
+// pop3-rs-0.1.0: r"(?P<msgid>\d+) (?P<uidl>[\x21-\x7E]{1,70})"
+consistent!(pop3_rs_1, r"(?P<msgid>\d+) (?P<uidl>[\x21-\x7E]{1,70})");
+
+// pop3-rs-0.1.0: r"(<.*>)\r\n$"
+consistent!(pop3_rs_2, r"(<.*>)\r\n$");
+
+// pop3-rs-0.1.0: r"^(?P<status>\+OK|-ERR) (?P<statustext>.*)"
+consistent!(pop3_rs_3, r"^(?P<status>\+OK|-ERR) (?P<statustext>.*)");
+
+// pop3-1.0.6: r"^\.\r\n$"
+consistent!(pop3_0, r"^\.\r\n$");
+
+// pop3-1.0.6: r"\+OK(.*)"
+consistent!(pop3_1, r"\+OK(.*)");
+
+// pop3-1.0.6: r"-ERR(.*)"
+consistent!(pop3_2, r"-ERR(.*)");
+
+// pop3-1.0.6: r"\+OK (\d+) (\d+)\r\n"
+consistent!(pop3_3, r"\+OK (\d+) (\d+)\r\n");
+
+// pop3-1.0.6: r"(\d+) ([\x21-\x7e]+)\r\n"
+consistent!(pop3_4, r"(\d+) ([\x21-\x7e]+)\r\n");
+
+// pop3-1.0.6: r"\+OK (\d+) ([\x21-\x7e]+)\r\n"
+consistent!(pop3_5, r"\+OK (\d+) ([\x21-\x7e]+)\r\n");
+
+// pop3-1.0.6: r"(\d+) (\d+)\r\n"
+consistent!(pop3_6, r"(\d+) (\d+)\r\n");
+
+// pop3-1.0.6: r"\+OK (\d+) (\d+)\r\n"
+consistent!(pop3_7, r"\+OK (\d+) (\d+)\r\n");
+
+// polk-1.1.3: "github:(\\w+)/?(\\w+)?"
+consistent!(polk_0, "github:(\\w+)/?(\\w+)?");
+
+// geochunk-0.1.5: "^[0-9]{5}"
+consistent!(geochunk_0, "^[0-9]{5}");
+
+// generic-dns-update-1.1.4: r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))"
+consistent!(generic_dns_update_0, r"((?:(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?)\.){3}(?:0|1[\d]{0,2}|2(?:[0-4]\d?|5[0-5]?|[6-9])?|[3-9]\d?))");
+
+// generic-dns-update-1.1.4: r"((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(([0-9A-Fa-f]{1,4}:){0,5}:((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(::([0-9A-Fa-f]{1,4}:){0,5}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))"
+consistent!(generic_dns_update_1, r"((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(([0-9A-Fa-f]{1,4}:){0,5}:((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|(::([0-9A-Fa-f]{1,4}:){0,5}((\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d)\.){3}(\d((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\d))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))");
+
+// generic-dns-update-1.1.4: r"<value><string>([0-9.]*)</string></value>"
+consistent!(generic_dns_update_2, r"<value><string>([0-9.]*)</string></value>");
+
+// generic-dns-update-1.1.4: r"<int>([0-9]+)</int>"
+consistent!(generic_dns_update_3, r"<int>([0-9]+)</int>");
+
+// generic-dns-update-1.1.4: r"<int>([0-9]+)</int>"
+consistent!(generic_dns_update_4, r"<int>([0-9]+)</int>");
+
+// generic-dns-update-1.1.4: r"<boolean>([0-1]*)</boolean>"
+consistent!(generic_dns_update_5, r"<boolean>([0-1]*)</boolean>");
+
+// generate-nix-pkg-0.3.0: r"(\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(generate_nix_pkg_0, r"(\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// generate-nix-pkg-0.3.0: r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(generate_nix_pkg_1, r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// genact-0.6.0: r"arch/([a-z0-9_])+/"
+consistent!(genact_0, r"arch/([a-z0-9_])+/");
+
+// genact-0.6.0: r"arch/([a-z0-9_])+/"
+consistent!(genact_1, r"arch/([a-z0-9_])+/");
+
+// cron_rs-0.1.6: r"^\s*((\*(/\d+)?)|[0-9-,/]+)(\s+((\*(/\d+)?)|[0-9-,/]+)){4,5}\s*$"
+consistent!(cron_rs_0, r"^\s*((\*(/\d+)?)|[0-9-,/]+)(\s+((\*(/\d+)?)|[0-9-,/]+)){4,5}\s*$");
+
+// systemfd-0.3.0: r"^([a-zA-Z]+)::(.+)$"
+consistent!(systemfd_0, r"^([a-zA-Z]+)::(.+)$");
+
+// symbolic-debuginfo-5.0.2: "__?hidden#\\d+_"
+consistent!(symbolic_debuginfo_0, "__?hidden#\\d+_");
+
+// symbolic-minidump-5.0.2: r"^Linux ([^ ]+) (.*) \w+(?: GNU/Linux)?$"
+consistent!(symbolic_minidump_0, r"^Linux ([^ ]+) (.*) \w+(?: GNU/Linux)?$");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\#)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+"
+consistent!(graphql_idl_parser_0, "^(?u:\\#)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+");
+
+// graphql-idl-parser-0.1.1: "^(?u:=)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+"
+consistent!(graphql_idl_parser_1, "^(?u:=)(?u:[\t-\r - \u{85}-\u{85}\u{a0}-\u{a0}\u{1680}-\u{1680}\u{2000}-\u{200a}\u{2028}-\u{2029}\u{202f}-\u{202f}\u{205f}-\u{205f}\u{3000}-\u{3000}])*(?u:.)+");
+
+// graphql-idl-parser-0.1.1: "^(?u:[A-Z_-_a-z])(?u:[0-9A-Z_-_a-z])*"
+consistent!(graphql_idl_parser_2, "^(?u:[A-Z_-_a-z])(?u:[0-9A-Z_-_a-z])*");
+
+// graphql-idl-parser-0.1.1: "^(?u:!)"
+consistent!(graphql_idl_parser_3, "^(?u:!)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\()"
+consistent!(graphql_idl_parser_4, "^(?u:\\()");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\))"
+consistent!(graphql_idl_parser_5, "^(?u:\\))");
+
+// graphql-idl-parser-0.1.1: "^(?u:,)"
+consistent!(graphql_idl_parser_6, "^(?u:,)");
+
+// graphql-idl-parser-0.1.1: "^(?u::)"
+consistent!(graphql_idl_parser_7, "^(?u::)");
+
+// graphql-idl-parser-0.1.1: "^(?u:@)"
+consistent!(graphql_idl_parser_8, "^(?u:@)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\[)"
+consistent!(graphql_idl_parser_9, "^(?u:\\[)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\])"
+consistent!(graphql_idl_parser_10, "^(?u:\\])");
+
+// graphql-idl-parser-0.1.1: "^(?u:enum)"
+consistent!(graphql_idl_parser_11, "^(?u:enum)");
+
+// graphql-idl-parser-0.1.1: "^(?u:implements)"
+consistent!(graphql_idl_parser_12, "^(?u:implements)");
+
+// graphql-idl-parser-0.1.1: "^(?u:input)"
+consistent!(graphql_idl_parser_13, "^(?u:input)");
+
+// graphql-idl-parser-0.1.1: "^(?u:interface)"
+consistent!(graphql_idl_parser_14, "^(?u:interface)");
+
+// graphql-idl-parser-0.1.1: "^(?u:scalar)"
+consistent!(graphql_idl_parser_15, "^(?u:scalar)");
+
+// graphql-idl-parser-0.1.1: "^(?u:type)"
+consistent!(graphql_idl_parser_16, "^(?u:type)");
+
+// graphql-idl-parser-0.1.1: "^(?u:union)"
+consistent!(graphql_idl_parser_17, "^(?u:union)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\{)"
+consistent!(graphql_idl_parser_18, "^(?u:\\{)");
+
+// graphql-idl-parser-0.1.1: "^(?u:\\})"
+consistent!(graphql_idl_parser_19, "^(?u:\\})");
+
+// grimoire-0.1.0: r"(?s)/\*(?P<config>.*?)\*/"
+consistent!(grimoire_0, r"(?s)/\*(?P<config>.*?)\*/");
+
+// phonenumber-0.2.0+8.9.0: r"[\d]+(?:[~\x{2053}\x{223C}\x{FF5E}][\d]+)?"
+consistent!(phonenumber_0, r"[\d]+(?:[~\x{2053}\x{223C}\x{FF5E}][\d]+)?");
+
+// phonenumber-0.2.0+8.9.0: r"[, \[\]]"
+consistent!(phonenumber_1, r"[, \[\]]");
+
+// phonenumber-0.2.0+8.9.0: r"[\\/] *x"
+consistent!(phonenumber_2, r"[\\/] *x");
+
+// phonenumber-0.2.0+8.9.0: r"[[\P{N}&&\P{L}]&&[^#]]+$"
+consistent!(phonenumber_3, r"[[\P{N}&&\P{L}]&&[^#]]+$");
+
+// phonenumber-0.2.0+8.9.0: r"(?:.*?[A-Za-z]){3}.*"
+consistent!(phonenumber_4, r"(?:.*?[A-Za-z]){3}.*");
+
+// phonenumber-0.2.0+8.9.0: r"(\D+)"
+consistent!(phonenumber_5, r"(\D+)");
+
+// phonenumber-0.2.0+8.9.0: r"(\$\d)"
+consistent!(phonenumber_6, r"(\$\d)");
+
+// phonenumber-0.2.0+8.9.0: r"\(?\$1\)?"
+consistent!(phonenumber_7, r"\(?\$1\)?");
+
+// phone_number-0.1.0: r"\D"
+consistent!(phone_number_0, r"\D");
+
+// phone_number-0.1.0: r"^0+"
+consistent!(phone_number_1, r"^0+");
+
+// phone_number-0.1.0: r"^89"
+consistent!(phone_number_2, r"^89");
+
+// phone_number-0.1.0: r"^8+"
+consistent!(phone_number_3, r"^8+");
+
+// phile-0.1.4: r"^ *(\^_*\^) *$"
+consistent!(phile_0, r"^ *(\^_*\^) *$");
+
+// phile-0.1.4: r"^[_\p{XID_Start}]$"
+consistent!(phile_1, r"^[_\p{XID_Start}]$");
+
+// phile-0.1.4: r"^\p{XID_Continue}$"
+consistent!(phile_2, r"^\p{XID_Continue}$");
+
+// uritemplate-0.1.2: "%25(?P<hex>[0-9a-fA-F][0-9a-fA-F])"
+consistent!(uritemplate_0, "%25(?P<hex>[0-9a-fA-F][0-9a-fA-F])");
+
+// urdf-rs-0.4.2: "^package://(\\w+)/"
+consistent!(urdf_rs_0, "^package://(\\w+)/");
+
+// url-match-0.1.7: r"(?P<key>[?&.])"
+consistent!(url_match_0, r"(?P<key>[?&.])");
+
+// url-match-0.1.7: r":(?P<key>[a-zA-Z0-9_-]+)"
+consistent!(url_match_1, r":(?P<key>[a-zA-Z0-9_-]+)");
+
+// tsm-sys-0.1.0: r"hello world"
+consistent!(tsm_sys_0, r"hello world");
+
+// deb-version-0.1.0: "^(?:(?:(?:\\d+:).+)|(?:[^:]+))$"
+consistent!(deb_version_0, "^(?:(?:(?:\\d+:).+)|(?:[^:]+))$");
+
+// debcargo-2.1.0: r"^(?i)(a|an|the)\s+"
+consistent!(debcargo_0, r"^(?i)(a|an|the)\s+");
+
+// debcargo-2.1.0: r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+"
+consistent!(debcargo_1, r"^(?i)(rust\s+)?(implementation|library|tool|crate)\s+(of|to|for)\s+");
+
+// feaders-0.2.0: r"^.*\.h$"
+consistent!(feaders_0, r"^.*\.h$");
+
+// feaders-0.2.0: r"^.*\.c$"
+consistent!(feaders_1, r"^.*\.c$");
+
+// feaders-0.2.0: r"^.*\.hpp$"
+consistent!(feaders_2, r"^.*\.hpp$");
+
+// feaders-0.2.0: r"^.*\.cc$"
+consistent!(feaders_3, r"^.*\.cc$");
+
+// feaders-0.2.0: r"^.*\.cpp$"
+consistent!(feaders_4, r"^.*\.cpp$");
+
+// hyperscan-0.1.6: r"CPtr\(\w+\)"
+consistent!(hyperscan_0, r"CPtr\(\w+\)");
+
+// hyperscan-0.1.6: r"^Version:\s(\d\.\d\.\d)\sFeatures:\s+(\w+)?\sMode:\s(\w+)$"
+consistent!(hyperscan_1, r"^Version:\s(\d\.\d\.\d)\sFeatures:\s+(\w+)?\sMode:\s(\w+)$");
+
+// hyperscan-0.1.6: r"RawDatabase<Block>\{db: \w+\}"
+consistent!(hyperscan_2, r"RawDatabase<Block>\{db: \w+\}");
+
+// hyperscan-0.1.6: r"RawSerializedDatabase\{p: \w+, len: \d+\}"
+consistent!(hyperscan_3, r"RawSerializedDatabase\{p: \w+, len: \d+\}");
+
+// ucd-parse-0.1.1: r"[0-9A-F]+"
+consistent!(ucd_parse_0, r"[0-9A-F]+");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_0, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_1, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_2, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_3, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_4, r".*");
+
+// afsort-0.2.0: r".*"
+consistent!(afsort_5, r".*");
+
+// afsort-0.2.0: r"^[a-z]+$"
+consistent!(afsort_6, r"^[a-z]+$");
+
+// afsort-0.2.0: r"^[a-z]+$"
+consistent!(afsort_7, r"^[a-z]+$");
+
+// tin-summer-1.21.4: r"(\.git|\.pijul|_darcs|\.hg)$"
+consistent!(tin_summer_0, r"(\.git|\.pijul|_darcs|\.hg)$");
+
+// tin-drummer-1.0.1: r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(tin_drummer_0, r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// tin-drummer-1.0.1: r".*?\.(stats|conf|h|out|cache.*|dat|pc|info|\.js)$"
+consistent!(tin_drummer_1, r".*?\.(stats|conf|h|out|cache.*|dat|pc|info|\.js)$");
+
+// tin-drummer-1.0.1: r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(tin_drummer_2, r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// tin-drummer-1.0.1: r".*?\.(stats|conf|h|out|cache.*|\.js)$"
+consistent!(tin_drummer_3, r".*?\.(stats|conf|h|out|cache.*|\.js)$");
+
+// tin-drummer-1.0.1: r"(\.git|\.pijul|_darcs|\.hg)$"
+consistent!(tin_drummer_4, r"(\.git|\.pijul|_darcs|\.hg)$");
+
+// tin-drummer-1.0.1: r".*?\.(dyn_o|out|d|hi|dyn_hi|dump-.*|p_hi|p_o|prof|tix)$"
+consistent!(tin_drummer_5, r".*?\.(dyn_o|out|d|hi|dyn_hi|dump-.*|p_hi|p_o|prof|tix)$");
+
+// tin-drummer-1.0.1: r".*?\.(ibc)$"
+consistent!(tin_drummer_6, r".*?\.(ibc)$");
+
+// tin-drummer-1.0.1: r"\.stack-work|dist-newstyle"
+consistent!(tin_drummer_7, r"\.stack-work|dist-newstyle");
+
+// timmy-0.3.0: r"_NET_WM_PID\(CARDINAL\) = (\d+)"
+consistent!(timmy_0, r"_NET_WM_PID\(CARDINAL\) = (\d+)");
+
+// timmy-0.3.0: r"today|yesterday|now"
+consistent!(timmy_1, r"today|yesterday|now");
+
+// timmy-0.3.0: r"(?P<day>\d{1,2})/(?P<month>\d{1,2})(/(?P<year>\d{4}|\d{2}))?"
+consistent!(timmy_2, r"(?P<day>\d{1,2})/(?P<month>\d{1,2})(/(?P<year>\d{4}|\d{2}))?");
+
+// timmy-0.3.0: r"(?P<n>\d+) (days?|ds?)(?P<ago>( ago)?)"
+consistent!(timmy_3, r"(?P<n>\d+) (days?|ds?)(?P<ago>( ago)?)");
+
+// timmy-0.3.0: r"(?P<hr>\d{2}):(?P<mins>\d{2})"
+consistent!(timmy_4, r"(?P<hr>\d{2}):(?P<mins>\d{2})");
+
+// tinfo-0.5.0: r"^(\d+): \d+ windows \(.*\) \[\d+x\d+\]( \(attached\))?"
+consistent!(tinfo_0, r"^(\d+): \d+ windows \(.*\) \[\d+x\d+\]( \(attached\))?");
+
+// tinfo-0.5.0: r"^(\d+):(\d+): (.*) \((\d+) panes\) \[(\d+)x(\d+)\]"
+consistent!(tinfo_1, r"^(\d+):(\d+): (.*) \((\d+) panes\) \[(\d+)x(\d+)\]");
+
+// timespan-0.0.4: r"(?:\\\{start\\\}|\\\{end\\\})"
+consistent!(timespan_0, r"(?:\\\{start\\\}|\\\{end\\\})");
+
+// timespan-0.0.4: r"(.*)\s+-\s+(.*)"
+consistent!(timespan_1, r"(.*)\s+-\s+(.*)");
+
+// timespan-0.0.4: r"(.*)\s+(\w+)$"
+consistent!(timespan_2, r"(.*)\s+(\w+)$");
+
+// timespan-0.0.4: r"(.*)\s+(\w+)$"
+consistent!(timespan_3, r"(.*)\s+(\w+)$");
+
+// timespan-0.0.4: r"(.*)\s+-\s+(.*)"
+consistent!(timespan_4, r"(.*)\s+-\s+(.*)");
+
+// titlecase-0.10.0: r"[[:lower:]]"
+consistent!(titlecase_0, r"[[:lower:]]");
+
+// tight-0.1.3: r"^\d+ (day|week|month|year)s?$"
+consistent!(tight_0, r"^\d+ (day|week|month|year)s?$");
+
+// tight-0.1.3: r"^\d+ (day|week|month|year)s?$"
+consistent!(tight_1, r"^\d+ (day|week|month|year)s?$");
+
+// yaml-0.2.1: r"^[-+]?(0|[1-9][0-9_]*)$"
+consistent!(yaml_0, r"^[-+]?(0|[1-9][0-9_]*)$");
+
+// yaml-0.2.1: r"^([-+]?)0o?([0-7_]+)$"
+consistent!(yaml_1, r"^([-+]?)0o?([0-7_]+)$");
+
+// yaml-0.2.1: r"^([-+]?)0x([0-9a-fA-F_]+)$"
+consistent!(yaml_2, r"^([-+]?)0x([0-9a-fA-F_]+)$");
+
+// yaml-0.2.1: r"^([-+]?)0b([0-1_]+)$"
+consistent!(yaml_3, r"^([-+]?)0b([0-1_]+)$");
+
+// yaml-0.2.1: r"^([-+]?)(\.[0-9]+|[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)$"
+consistent!(yaml_4, r"^([-+]?)(\.[0-9]+|[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)$");
+
+// yaml-0.2.1: r"^[+]?(\.inf|\.Inf|\.INF)$"
+consistent!(yaml_5, r"^[+]?(\.inf|\.Inf|\.INF)$");
+
+// yaml-0.2.1: r"^-(\.inf|\.Inf|\.INF)$"
+consistent!(yaml_6, r"^-(\.inf|\.Inf|\.INF)$");
+
+// yaml-0.2.1: r"^(\.nan|\.NaN|\.NAN)$"
+consistent!(yaml_7, r"^(\.nan|\.NaN|\.NAN)$");
+
+// yaml-0.2.1: r"^(null|Null|NULL|~)$"
+consistent!(yaml_8, r"^(null|Null|NULL|~)$");
+
+// yaml-0.2.1: r"^(true|True|TRUE|yes|Yes|YES)$"
+consistent!(yaml_9, r"^(true|True|TRUE|yes|Yes|YES)$");
+
+// yaml-0.2.1: r"^(false|False|FALSE|no|No|NO)$"
+consistent!(yaml_10, r"^(false|False|FALSE|no|No|NO)$");
+
+// kefia-0.1.0: r"(?m)^(\S+)/(\S+) (\S+)(?: \((.*)\))?$"
+consistent!(kefia_0, r"(?m)^(\S+)/(\S+) (\S+)(?: \((.*)\))?$");
+
+// risp-0.7.0: "^(\\s+|;.*?(\n|$))+"
+consistent!(risp_0, "^(\\s+|;.*?(\n|$))+");
+
+// risp-0.7.0: "^\".*?\""
+consistent!(risp_1, "^\".*?\"");
+
+// risp-0.7.0: r"^[^\s\{\}()\[\]]+"
+consistent!(risp_2, r"^[^\s\{\}()\[\]]+");
+
+// risp-0.7.0: r"^-?\d+"
+consistent!(risp_3, r"^-?\d+");
+
+// ripgrep-0.8.1: "^([0-9]+)([KMG])?$"
+consistent!(ripgrep_0, "^([0-9]+)([KMG])?$");
+
+// riquid-0.0.1: r"^\w+"
+consistent!(riquid_0, r"^\w+");
+
+// riquid-0.0.1: r"^\d+"
+consistent!(riquid_1, r"^\d+");
+
+// recursive_disassembler-2.1.2: r"\A(0x)?([a-fA-F0-9]+)\z"
+consistent!(recursive_disassembler_0, r"\A(0x)?([a-fA-F0-9]+)\z");
+
+// remake-0.1.0: r"^[a-zA-Z_][a-zA-Z0-9_]*"
+consistent!(remake_0, r"^[a-zA-Z_][a-zA-Z0-9_]*");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_0, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_1, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_2, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_3, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_4, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_5, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{2})\)"
+consistent!(regex_decode_6, r"'(?P<title>[^']+)'\s+\((?P<year>\d{2})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_7, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)"
+consistent!(regex_decode_8, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_9, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_10, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_11, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_12, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-decode-0.1.0: r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)"
+consistent!(regex_decode_13, r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})?\)");
+
+// regex-cache-0.2.0: "[0-9]{3}-[0-9]{3}-[0-9]{4}"
+consistent!(regex_cache_0, "[0-9]{3}-[0-9]{3}-[0-9]{4}");
+
+// regex-cache-0.2.0: r"^\d+$"
+consistent!(regex_cache_1, r"^\d+$");
+
+// regex-cache-0.2.0: r"^[a-z]+$"
+consistent!(regex_cache_2, r"^[a-z]+$");
+
+// regex-cache-0.2.0: r"^\d+$"
+consistent!(regex_cache_3, r"^\d+$");
+
+// regex-cache-0.2.0: r"^\d+$"
+consistent!(regex_cache_4, r"^\d+$");
+
+// regex_dfa-0.5.0: r"\d{4}-\d{2}-\d{2}"
+consistent!(regex_dfa_0, r"\d{4}-\d{2}-\d{2}");
+
+// reaper-2.0.0: r"^[0-9\p{L} _\\.]{3,16}$"
+consistent!(reaper_0, r"^[0-9\p{L} _\\.]{3,16}$");
+
+// retdec-0.1.0: r"^attachment; filename=(.+)$"
+consistent!(retdec_0, r"^attachment; filename=(.+)$");
+
+// renvsubst-0.1.2: r"(\\)(?P<head>\$[0-9A-Za-z_{])"
+consistent!(renvsubst_0, r"(\\)(?P<head>\$[0-9A-Za-z_{])");
+
+// renvsubst-0.1.2: r"\$([[:word:]]+)"
+consistent!(renvsubst_1, r"\$([[:word:]]+)");
+
+// renvsubst-0.1.2: r"\$\{([[:word:]]+)\}"
+consistent!(renvsubst_2, r"\$\{([[:word:]]+)\}");
+
+// rexpect-0.3.0: r"'[a-z]+'"
+consistent!(rexpect_0, r"'[a-z]+'");
+
+// rexpect-0.3.0: r"^\d{4}-\d{2}-\d{2}$"
+consistent!(rexpect_1, r"^\d{4}-\d{2}-\d{2}$");
+
+// rexpect-0.3.0: r"-\d{2}-"
+consistent!(rexpect_2, r"-\d{2}-");
+
+// luther-0.1.0: "^a(b|c)c*$"
+consistent!(luther_0, "^a(b|c)c*$");
+
+// little_boxes-1.6.0: r"(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]"
+consistent!(little_boxes_0, r"(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]");
+
+// libimagentrytag-0.8.0: "^[a-zA-Z]([a-zA-Z0-9_-]*)$"
+consistent!(libimagentrytag_0, "^[a-zA-Z]([a-zA-Z0-9_-]*)$");
+
+// libimaginteraction-0.8.0: r"^[Yy](\n?)$"
+consistent!(libimaginteraction_0, r"^[Yy](\n?)$");
+
+// libimaginteraction-0.8.0: r"^[Nn](\n?)$"
+consistent!(libimaginteraction_1, r"^[Nn](\n?)$");
+
+// libimagutil-0.8.0: "^(?P<KEY>([^=]*))=(.*)$"
+consistent!(libimagutil_0, "^(?P<KEY>([^=]*))=(.*)$");
+
+// libimagutil-0.8.0: "(.*)=(\"(?P<QVALUE>([^\"]*))\"|(?P<VALUE>(.*)))$"
+consistent!(libimagutil_1, "(.*)=(\"(?P<QVALUE>([^\"]*))\"|(?P<VALUE>(.*)))$");
+
+// linux_ip-0.1.0: r"\s+"
+consistent!(linux_ip_0, r"\s+");
+
+// linux_ip-0.1.0: r"\s*[\n\r]+\s*"
+consistent!(linux_ip_1, r"\s*[\n\r]+\s*");
+
+// linux_ip-0.1.0: r"^([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$"
+consistent!(linux_ip_2, r"^([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$");
+
+// linux_ip-0.1.0: r"^([0-9a-fA-F\.:/]+|default)\s+via\s+([a-z0-9\.:]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$"
+consistent!(linux_ip_3, r"^([0-9a-fA-F\.:/]+|default)\s+via\s+([a-z0-9\.:]+)\s+dev\s+([a-z0-9\.]+)\s*(.*)$");
+
+// linux_ip-0.1.0: r"^(blackhole)\s+([0-9a-fA-F\.:/]+)$"
+consistent!(linux_ip_4, r"^(blackhole)\s+([0-9a-fA-F\.:/]+)$");
+
+// linux_ip-0.1.0: r"^(unreachable)\s+([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s+(.*)$"
+consistent!(linux_ip_5, r"^(unreachable)\s+([0-9a-fA-F\.:/]+)\s+dev\s+([a-z0-9\.]+)\s+(.*)$");
+
+// linux_ip-0.1.0: r"\s*[\n\r]+\s*"
+consistent!(linux_ip_6, r"\s*[\n\r]+\s*");
+
+// linux_ip-0.1.0: r"^\d+:\s+([a-zA-Z0-9\.-]+)(@\S+)*:\s+(.*)$"
+consistent!(linux_ip_7, r"^\d+:\s+([a-zA-Z0-9\.-]+)(@\S+)*:\s+(.*)$");
+
+// linux_ip-0.1.0: r"\s*link/ether\s+([a-f0-9:]+)\s+.*"
+consistent!(linux_ip_8, r"\s*link/ether\s+([a-f0-9:]+)\s+.*");
+
+// linux_ip-0.1.0: r"\s*inet[6]*\s+([0-9a-f:\./]+)\s+.*"
+consistent!(linux_ip_9, r"\s*inet[6]*\s+([0-9a-f:\./]+)\s+.*");
+
+// linky-0.1.4: r"[^\w -]"
+consistent!(linky_0, r"[^\w -]");
+
+// linky-0.1.4: r"^(.*):(\d+): [^ ]* ([^ ]*)$"
+consistent!(linky_1, r"^(.*):(\d+): [^ ]* ([^ ]*)$");
+
+// limonite-0.2.1: r"^(\d{4}-\d{2}-\d{2})-(\d{3})-(.+)$"
+consistent!(limonite_0, r"^(\d{4}-\d{2}-\d{2})-(\d{3})-(.+)$");
+
+// process-queue-0.1.1: r"^[a-zA-Z]+$"
+consistent!(process_queue_0, r"^[a-zA-Z]+$");
+
+// pronghorn-0.1.2: r"^\{([a-zA-Z_]+)\}$"
+consistent!(pronghorn_0, r"^\{([a-zA-Z_]+)\}$");
+
+// protocol-ftp-client-0.1.1: "(?m:^(\\d{3}) (.+)\r$)"
+consistent!(protocol_ftp_client_0, "(?m:^(\\d{3}) (.+)\r$)");
+
+// protocol-ftp-client-0.1.1: "\"(.+)\""
+consistent!(protocol_ftp_client_1, "\"(.+)\"");
+
+// protocol-ftp-client-0.1.1: "(\\w+) [Tt]ype: (\\w+)"
+consistent!(protocol_ftp_client_2, "(\\w+) [Tt]ype: (\\w+)");
+
+// protocol-ftp-client-0.1.1: "(?m:^(\\d{3})-.+\r$)"
+consistent!(protocol_ftp_client_3, "(?m:^(\\d{3})-.+\r$)");
+
+// protocol-ftp-client-0.1.1: "Entering Passive Mode \\((\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)\\)"
+consistent!(protocol_ftp_client_4, "Entering Passive Mode \\((\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)\\)");
+
+// protocol-ftp-client-0.1.1: "(?m:^(.+)\r$)"
+consistent!(protocol_ftp_client_5, "(?m:^(.+)\r$)");
+
+// protocol-ftp-client-0.1.1: "^([d-])(?:[rwx-]{3}){3} +\\d+ +\\w+ +\\w+ +(\\d+) +(.+) +(.+)$"
+consistent!(protocol_ftp_client_6, "^([d-])(?:[rwx-]{3}){3} +\\d+ +\\w+ +\\w+ +(\\d+) +(.+) +(.+)$");
+
+// article-date-extractor-0.1.1: r"([\./\-_]{0,1}(19|20)\d{2})[\./\-_]{0,1}(([0-3]{0,1}[0-9][\./\-_])|(\w{3,5}[\./\-_]))([0-3]{0,1}[0-9][\./\-]{0,1})"
+consistent!(article_date_extractor_0, r"([\./\-_]{0,1}(19|20)\d{2})[\./\-_]{0,1}(([0-3]{0,1}[0-9][\./\-_])|(\w{3,5}[\./\-_]))([0-3]{0,1}[0-9][\./\-]{0,1})");
+
+// article-date-extractor-0.1.1: r"(?i)publishdate|pubdate|timestamp|article_date|articledate|date"
+consistent!(article_date_extractor_1, r"(?i)publishdate|pubdate|timestamp|article_date|articledate|date");
+
+// arthas_plugin-0.1.1: r"type\((.*)\)"
+consistent!(arthas_plugin_0, r"type\((.*)\)");
+
+// arthas_plugin-0.1.1: r"Vec<(.*)>"
+consistent!(arthas_plugin_1, r"Vec<(.*)>");
+
+// arthas_plugin-0.1.1: r"Option<(.*)>"
+consistent!(arthas_plugin_2, r"Option<(.*)>");
+
+// arthas_plugin-0.1.1: r"HashMap<[a-z0-9A-Z]+, *(.*)>"
+consistent!(arthas_plugin_3, r"HashMap<[a-z0-9A-Z]+, *(.*)>");
+
+// arthas_derive-0.1.0: "Vec *< *(.*) *>"
+consistent!(arthas_derive_0, "Vec *< *(.*) *>");
+
+// arthas_derive-0.1.0: r"Option *< *(.*) *>"
+consistent!(arthas_derive_1, r"Option *< *(.*) *>");
+
+// arthas_derive-0.1.0: r"HashMap *< *[a-z0-9A-Z]+ *, *(.*) *>"
+consistent!(arthas_derive_2, r"HashMap *< *[a-z0-9A-Z]+ *, *(.*) *>");
+
+// arpabet-0.2.0: r"^([\w\-\(\)\.']+)\s+([^\s].*)\s*$"
+consistent!(arpabet_0, r"^([\w\-\(\)\.']+)\s+([^\s].*)\s*$");
+
+// arpabet-0.2.0: r"^;;;\s+"
+consistent!(arpabet_1, r"^;;;\s+");
+
+// glossy_codegen-0.2.0: r"/\*.*?\*/|//.*"
+consistent!(glossy_codegen_0, r"/\*.*?\*/|//.*");
+
+// glossy_codegen-0.2.0: "^\\s*#\\s*include\\s+<([:print:]+)>\\s*$"
+consistent!(glossy_codegen_1, "^\\s*#\\s*include\\s+<([:print:]+)>\\s*$");
+
+// glossy_codegen-0.2.0: "^\\s*#\\s*include\\s+\"([:print:]+)\"\\s*$"
+consistent!(glossy_codegen_2, "^\\s*#\\s*include\\s+\"([:print:]+)\"\\s*$");
+
+// glossy_codegen-0.2.0: r"^\s*#\s*version\s+(\d+)"
+consistent!(glossy_codegen_3, r"^\s*#\s*version\s+(\d+)");
+
+// glossy_codegen-0.2.0: r"^\s*$"
+consistent!(glossy_codegen_4, r"^\s*$");
+
+// gluster-1.0.1: r"(?P<addr>via \S+)"
+consistent!(gluster_0, r"(?P<addr>via \S+)");
+
+// gluster-1.0.1: r"(?P<src>src \S+)"
+consistent!(gluster_1, r"(?P<src>src \S+)");
+
+// gl_helpers-0.1.7: r"(.*)\[\d+\]"
+consistent!(gl_helpers_0, r"(.*)\[\d+\]");
+
+// gl_helpers-0.1.7: r"(\d+).(\d+)"
+consistent!(gl_helpers_1, r"(\d+).(\d+)");
+
+// glr-parser-0.0.1: r"(?P<c>[\\\.\+\*\?\(\)\|\[\]\{\}\^\$])"
+consistent!(glr_parser_0, r"(?P<c>[\\\.\+\*\?\(\)\|\[\]\{\}\^\$])");
+
+// glr-parser-0.0.1: r"^\w+$"
+consistent!(glr_parser_1, r"^\w+$");
+
+// glr-parser-0.0.1: "'[^']+'"
+consistent!(glr_parser_2, "'[^']+'");
+
+// hoodlum-0.5.0: r"(?m)//.*"
+consistent!(hoodlum_0, r"(?m)//.*");
+
+// form-checker-0.2.2: r"^1\d{10}$"
+consistent!(form_checker_0, r"^1\d{10}$");
+
+// form-checker-0.2.2: r"(?i)^[\w.%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$"
+consistent!(form_checker_1, r"(?i)^[\w.%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$");
+
+// wikibase-0.2.0: r"(?P<user_agent>[a-zA-Z0-9-_]+/[0-9\.]+)"
+consistent!(wikibase_0, r"(?P<user_agent>[a-zA-Z0-9-_]+/[0-9\.]+)");
+
+// wifiscanner-0.3.6: r"Cell [0-9]{2,} - Address:"
+consistent!(wifiscanner_0, r"Cell [0-9]{2,} - Address:");
+
+// wifiscanner-0.3.6: r"([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}"
+consistent!(wifiscanner_1, r"([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}");
+
+// wifiscanner-0.3.6: r"Signal level=(\d+)/100"
+consistent!(wifiscanner_2, r"Signal level=(\d+)/100");
+
+// bbcode-1.0.2: r"(?s)\[b\](.*?)\[/b\]"
+consistent!(bbcode_0, r"(?s)\[b\](.*?)\[/b\]");
+
+// bbcode-1.0.2: r"(?s)\[i\](.*?)\[/i\]"
+consistent!(bbcode_1, r"(?s)\[i\](.*?)\[/i\]");
+
+// bbcode-1.0.2: r"(?s)\[u\](.*?)\[/u\]"
+consistent!(bbcode_2, r"(?s)\[u\](.*?)\[/u\]");
+
+// bbcode-1.0.2: r"(?s)\[s\](.*?)\[/s\]"
+consistent!(bbcode_3, r"(?s)\[s\](.*?)\[/s\]");
+
+// bbcode-1.0.2: r"(?s)\[size=(\d+)](.*?)\[/size\]"
+consistent!(bbcode_4, r"(?s)\[size=(\d+)](.*?)\[/size\]");
+
+// bbcode-1.0.2: r"(?s)\[color=(.+)](.*?)\[/color\]"
+consistent!(bbcode_5, r"(?s)\[color=(.+)](.*?)\[/color\]");
+
+// bbcode-1.0.2: r"(?s)\[center\](.*?)\[/center\]"
+consistent!(bbcode_6, r"(?s)\[center\](.*?)\[/center\]");
+
+// bbcode-1.0.2: r"(?s)\[left\](.*?)\[/left\]"
+consistent!(bbcode_7, r"(?s)\[left\](.*?)\[/left\]");
+
+// bbcode-1.0.2: r"(?s)\[right\](.*?)\[/right\]"
+consistent!(bbcode_8, r"(?s)\[right\](.*?)\[/right\]");
+
+// bbcode-1.0.2: r"(?s)\[table\](.*?)\[/table\]"
+consistent!(bbcode_9, r"(?s)\[table\](.*?)\[/table\]");
+
+// bbcode-1.0.2: r"(?s)\[td\](.*?)\[/td\]"
+consistent!(bbcode_10, r"(?s)\[td\](.*?)\[/td\]");
+
+// bbcode-1.0.2: r"(?s)\[tr\](.*?)\[/tr\]"
+consistent!(bbcode_11, r"(?s)\[tr\](.*?)\[/tr\]");
+
+// bbcode-1.0.2: r"(?s)\[th\](.*?)\[/th\]"
+consistent!(bbcode_12, r"(?s)\[th\](.*?)\[/th\]");
+
+// bbcode-1.0.2: r"(?s)\[url\](.*?)\[/url\]"
+consistent!(bbcode_13, r"(?s)\[url\](.*?)\[/url\]");
+
+// bbcode-1.0.2: r"(?s)\[url=(.+)\](.*?)\[/url\]"
+consistent!(bbcode_14, r"(?s)\[url=(.+)\](.*?)\[/url\]");
+
+// bbcode-1.0.2: r"(?s)\[quote\](.*?)\[/quote\]"
+consistent!(bbcode_15, r"(?s)\[quote\](.*?)\[/quote\]");
+
+// bbcode-1.0.2: r"(?s)\[quote=(.+)\](.*?)\[/quote\]"
+consistent!(bbcode_16, r"(?s)\[quote=(.+)\](.*?)\[/quote\]");
+
+// bbcode-1.0.2: r"(?s)\[img=(\d+)x(\d+)(\b.*)?\](.*?)\[/img\]"
+consistent!(bbcode_17, r"(?s)\[img=(\d+)x(\d+)(\b.*)?\](.*?)\[/img\]");
+
+// bbcode-1.0.2: r"(?s)\[img=(.+)(\b.*)?\](.*?)\[/img\]"
+consistent!(bbcode_18, r"(?s)\[img=(.+)(\b.*)?\](.*?)\[/img\]");
+
+// bbcode-1.0.2: r"(?s)\[img(\b.*)?\](.*?)\[/img\]"
+consistent!(bbcode_19, r"(?s)\[img(\b.*)?\](.*?)\[/img\]");
+
+// bbcode-1.0.2: r"(?s)\[ol\](.*?)\[/ol\]"
+consistent!(bbcode_20, r"(?s)\[ol\](.*?)\[/ol\]");
+
+// bbcode-1.0.2: r"(?s)\[ul\](.*?)\[/ul\]"
+consistent!(bbcode_21, r"(?s)\[ul\](.*?)\[/ul\]");
+
+// bbcode-1.0.2: r"(?s)\[list\](.*?)\[/list\]"
+consistent!(bbcode_22, r"(?s)\[list\](.*?)\[/list\]");
+
+// bbcode-1.0.2: r"(?s)\[youtube\](.*?)\[/youtube\]"
+consistent!(bbcode_23, r"(?s)\[youtube\](.*?)\[/youtube\]");
+
+// bbcode-1.0.2: r"(?s)\[youtube=(\d+)x(\d+)\](.*?)\[/youtube\]"
+consistent!(bbcode_24, r"(?s)\[youtube=(\d+)x(\d+)\](.*?)\[/youtube\]");
+
+// bbcode-1.0.2: r"(?s)\[li\](.*?)\[/li\]"
+consistent!(bbcode_25, r"(?s)\[li\](.*?)\[/li\]");
+
+// block-utils-0.5.0: r"loop\d+"
+consistent!(block_utils_0, r"loop\d+");
+
+// block-utils-0.5.0: r"ram\d+"
+consistent!(block_utils_1, r"ram\d+");
+
+// block-utils-0.5.0: r"md\d+"
+consistent!(block_utils_2, r"md\d+");
+
+// kvvliveapi-0.1.0: r"^([1-9]) min$"
+consistent!(kvvliveapi_0, r"^([1-9]) min$");
+
+// rfc822_sanitizer-0.3.3: r"(\d{2}):(\d{2}):(\d{2})"
+consistent!(rfc822_sanitizer_0, r"(\d{2}):(\d{2}):(\d{2})");
+
+// rfc822_sanitizer-0.3.3: r"(\d{1,2}):(\d{1,2}):(\d{1,2})"
+consistent!(rfc822_sanitizer_1, r"(\d{1,2}):(\d{1,2}):(\d{1,2})");
+
+// faker-0.0.4: r"[2-9]"
+consistent!(faker_0, r"[2-9]");
+
+// faker-0.0.4: r"[1-9]"
+consistent!(faker_1, r"[1-9]");
+
+// faker-0.0.4: r"[0-9]"
+consistent!(faker_2, r"[0-9]");
+
+// faker-0.0.4: r"\d{10}"
+consistent!(faker_3, r"\d{10}");
+
+// faker-0.0.4: r"\d{1}"
+consistent!(faker_4, r"\d{1}");
+
+// faker-0.0.4: r"^\w+"
+consistent!(faker_5, r"^\w+");
+
+// faker-0.0.4: r"^\w+"
+consistent!(faker_6, r"^\w+");
+
+// faker-0.0.4: r"^(\w+\.? ?){2,3}$"
+consistent!(faker_7, r"^(\w+\.? ?){2,3}$");
+
+// faker-0.0.4: r"^[A-Z][a-z]+\.?$"
+consistent!(faker_8, r"^[A-Z][a-z]+\.?$");
+
+// faker-0.0.4: r"^[A-Z][A-Za-z]*\.?$"
+consistent!(faker_9, r"^[A-Z][A-Za-z]*\.?$");
+
+// faker-0.0.4: r"http://lorempixel.com/100/100/\w+"
+consistent!(faker_10, r"http://lorempixel.com/100/100/\w+");
+
+// faker-0.0.4: r"http://lorempixel.com/100/100/cats"
+consistent!(faker_11, r"http://lorempixel.com/100/100/cats");
+
+// fancy-regex-0.1.0: "(?i:ß)"
+consistent!(fancy_regex_0, "(?i:ß)");
+
+// fancy-regex-0.1.0: "(?i:\\x{0587})"
+consistent!(fancy_regex_1, "(?i:\\x{0587})");
+
+// fancy-regex-0.1.0: "^\\\\([!-/:-@\\[-`\\{-~aftnrv]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\\{[0-9a-fA-F]{1,6}\\})"
+consistent!(fancy_regex_2, "^\\\\([!-/:-@\\[-`\\{-~aftnrv]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\\{[0-9a-fA-F]{1,6}\\})");
+
+// fancy-prompt-0.1.5: r"/([^/])[^/]+/"
+consistent!(fancy_prompt_0, r"/([^/])[^/]+/");
+
+// fancy-prompt-0.1.5: r"^([^:]+):.*?(?::([^:]+))?$"
+consistent!(fancy_prompt_1, r"^([^:]+):.*?(?::([^:]+))?$");
+
+// fanta-0.2.0: r"^(/?__\w+__)/(.*)"
+consistent!(fanta_0, r"^(/?__\w+__)/(.*)");
+
+// fanta-cli-0.1.1: r"(.)([A-Z])"
+consistent!(fanta_cli_0, r"(.)([A-Z])");
+
+// fanta-cli-0.1.1: "\\{:[^\\s]+\\}"
+consistent!(fanta_cli_1, "\\{:[^\\s]+\\}");
+
+// amethyst_tools-0.7.1: "(?P<last>[^\r])\n"
+consistent!(amethyst_tools_0, "(?P<last>[^\r])\n");
+
+// amigo-0.3.1: r"^-?\d+(\.\d)?"
+consistent!(amigo_0, r"^-?\d+(\.\d)?");
+
+// amigo-0.3.1: r"^[a-zA-Z_]+[\w-]*[!?_]?"
+consistent!(amigo_1, r"^[a-zA-Z_]+[\w-]*[!?_]?");
+
+// amigo-0.3.1: r"^\("
+consistent!(amigo_2, r"^\(");
+
+// amigo-0.3.1: r"^\)"
+consistent!(amigo_3, r"^\)");
+
+// amigo-0.3.1: r"^\s+"
+consistent!(amigo_4, r"^\s+");
+
+// ethcore-logger-1.12.0: "\x1b\\[[^m]+m"
+consistent!(ethcore_logger_0, "\x1b\\[[^m]+m");
+
+// dash2html-1.0.1: r"__.*?__"
+consistent!(dash2html_0, r"__.*?__");
+
+// dash2html-1.0.1: r"(?i)@(?:time|clipboard|cursor|date)"
+consistent!(dash2html_1, r"(?i)@(?:time|clipboard|cursor|date)");
+
+// os_type-2.0.0: r"^Microsoft Windows \[Version\s(\d+\.\d+\.\d+)\]$"
+consistent!(os_type_0, r"^Microsoft Windows \[Version\s(\d+\.\d+\.\d+)\]$");
+
+// os_type-2.0.0: r"ProductName:\s([\w\s]+)\n"
+consistent!(os_type_1, r"ProductName:\s([\w\s]+)\n");
+
+// os_type-2.0.0: r"ProductVersion:\s(\w+\.\w+\.\w+)"
+consistent!(os_type_2, r"ProductVersion:\s(\w+\.\w+\.\w+)");
+
+// os_type-2.0.0: r"BuildVersion:\s(\w+)"
+consistent!(os_type_3, r"BuildVersion:\s(\w+)");
+
+// os_type-2.0.0: r"(\w+) Linux release"
+consistent!(os_type_4, r"(\w+) Linux release");
+
+// os_type-2.0.0: r"release\s([\w\.]+)"
+consistent!(os_type_5, r"release\s([\w\.]+)");
+
+// os_type-2.0.0: r"Distributor ID:\s(\w+)"
+consistent!(os_type_6, r"Distributor ID:\s(\w+)");
+
+// os_type-2.0.0: r"Release:\s([\w\.]+)"
+consistent!(os_type_7, r"Release:\s([\w\.]+)");
+
+// bindgen-0.37.0: r"typename type\-parameter\-\d+\-\d+::.+"
+consistent!(bindgen_0, r"typename type\-parameter\-\d+\-\d+::.+");
+
+// imap-0.8.1: "^+(.*)\r\n"
+consistent!(imap_0, "^+(.*)\r\n");
+
+// image-base64-0.1.0: r"^ffd8ffe0"
+consistent!(image_base64_0, r"^ffd8ffe0");
+
+// image-base64-0.1.0: r"^89504e47"
+consistent!(image_base64_1, r"^89504e47");
+
+// image-base64-0.1.0: r"^47494638"
+consistent!(image_base64_2, r"^47494638");
+
+// json-pointer-0.3.2: "^(/([^/~]|~[01])*)*$"
+consistent!(json_pointer_0, "^(/([^/~]|~[01])*)*$");
+
+// json-pointer-0.3.2: "^#(/([^/~%]|~[01]|%[0-9a-fA-F]{2})*)*$"
+consistent!(json_pointer_1, "^#(/([^/~%]|~[01]|%[0-9a-fA-F]{2})*)*$");
+
+// mysql_common-0.7.0: r"^5.5.5-(\d{1,2})\.(\d{1,2})\.(\d{1,3})-MariaDB"
+consistent!(mysql_common_0, r"^5.5.5-(\d{1,2})\.(\d{1,2})\.(\d{1,3})-MariaDB");
+
+// mysql_common-0.7.0: r"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)"
+consistent!(mysql_common_1, r"^(\d{1,2})\.(\d{1,2})\.(\d{1,3})(.*)");
+
+// government_id-0.1.0: r"^[0-9]{4}[0-9A-Z]{2}[0-9]{3}$"
+consistent!(government_id_0, r"^[0-9]{4}[0-9A-Z]{2}[0-9]{3}$");
+
+// ohmers-0.1.1: r"UniqueIndexViolation: (\w+)"
+consistent!(ohmers_0, r"UniqueIndexViolation: (\w+)");
+
+// eliza-1.0.0: r"(.*) you are (.*)"
+consistent!(eliza_0, r"(.*) you are (.*)");
+
+// eliza-1.0.0: r"(.*) you are (.*)"
+consistent!(eliza_1, r"(.*) you are (.*)");
+
+// eliza-1.0.0: r"(.*) you are (.*)"
+consistent!(eliza_2, r"(.*) you are (.*)");
+
+// chema-0.0.5: "^\\s*\\*"
+consistent!(chema_0, "^\\s*\\*");
+
+// chema-0.0.5: "^\\s*@(\\w+)\\s+(.*)"
+consistent!(chema_1, "^\\s*@(\\w+)\\s+(.*)");
+
+// chord3-0.3.0: r"^\s*#"
+consistent!(chord3_0, r"^\s*#");
+
+// chord3-0.3.0: r"\{(?P<cmd>\w+)(?::?\s*(?P<arg>.*))?\}"
+consistent!(chord3_1, r"\{(?P<cmd>\w+)(?::?\s*(?P<arg>.*))?\}");
+
+// chord3-0.3.0: r"\{(eot|end_of_tab):?\s*"
+consistent!(chord3_2, r"\{(eot|end_of_tab):?\s*");
+
+// chord3-0.3.0: r"([^\[]*)(?:\[([^\]]*)\])?"
+consistent!(chord3_3, r"([^\[]*)(?:\[([^\]]*)\])?");
+
+// checkmail-0.1.1: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
+consistent!(checkmail_0, "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$");
+
+// cntk-0.2.1: r"\b\w\w+\b"
+consistent!(cntk_0, r"\b\w\w+\b");
+
+// cntk-0.2.1: r"\b\w\w+\b"
+consistent!(cntk_1, r"\b\w\w+\b");
+
+// cniguru-0.1.0: r"\(id: (\d+)\)"
+consistent!(cniguru_0, r"\(id: (\d+)\)");
+
+// upm_lib-0.3.0: r"^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$"
+consistent!(upm_lib_0, r"^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$");
+
+// avro-0.2.1: r"^\s*(\*+(\s+))?"
+consistent!(avro_0, r"^\s*(\*+(\s+))?");
+
+// avro-0.2.1: r"^\s*(\*+)?"
+consistent!(avro_1, r"^\s*(\*+)?");
+
+// nomi-0.0.2: "[0-9]+"
+consistent!(nomi_0, "[0-9]+");
+
+// nodes-0.1.0: "([0-9]+)@(?:nodes|n)?:([^@]+)?"
+consistent!(nodes_0, "([0-9]+)@(?:nodes|n)?:([^@]+)?");
+
+// not-stakkr-1.0.0: r"(?i)in (\d+) (second|minute|hour|day|week)s?"
+consistent!(not_stakkr_0, r"(?i)in (\d+) (second|minute|hour|day|week)s?");
+
+// notetxt-0.0.1: "^([A-Za-z0-9 -_:]+)\n-+\n"
+consistent!(notetxt_0, "^([A-Za-z0-9 -_:]+)\n-+\n");
+
+// nail-0.1.0-pre.0: r"^-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?$"
+consistent!(nail_0, r"^-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?$");
+
+// nail-0.1.0-pre.0: r"^-?[0-9]+$"
+consistent!(nail_1, r"^-?[0-9]+$");
+
+// askalono-0.2.0: r"[^\w\s\pP]+"
+consistent!(askalono_0, r"[^\w\s\pP]+");
+
+// askalono-0.2.0: r"(?x)[ \t\p{Zs} \\ / \| \x2044 ]+"
+consistent!(askalono_1, r"(?x)[ \t\p{Zs} \\ / \| \x2044 ]+");
+
+// askalono-0.2.0: r"\p{Pd}+"
+consistent!(askalono_2, r"\p{Pd}+");
+
+// askalono-0.2.0: r"\p{Ps}+"
+consistent!(askalono_3, r"\p{Ps}+");
+
+// askalono-0.2.0: r"\p{Pe}+"
+consistent!(askalono_4, r"\p{Pe}+");
+
+// askalono-0.2.0: r"\p{Pc}+"
+consistent!(askalono_5, r"\p{Pc}+");
+
+// askalono-0.2.0: r"[©Ⓒⓒ]"
+consistent!(askalono_6, r"[©Ⓒⓒ]");
+
+// askalono-0.2.0: r"[\r\n\v\f]"
+consistent!(askalono_7, r"[\r\n\v\f]");
+
+// askalono-0.2.0: r"\n{3,}"
+consistent!(askalono_8, r"\n{3,}");
+
+// askalono-0.2.0: r"[^\w\s]+"
+consistent!(askalono_9, r"[^\w\s]+");
+
+// askalono-0.2.0: r"\s+"
+consistent!(askalono_10, r"\s+");
+
+// assembunny_plus-0.0.3: r"[^0-9a-zA-Z_]"
+consistent!(assembunny_plus_0, r"[^0-9a-zA-Z_]");
+
+// assembunny_plus-0.0.3: r"[0-9]"
+consistent!(assembunny_plus_1, r"[0-9]");
+
+// salt-compressor-0.4.0: r"(?m)^Minion (\S*) did not respond\. No job will be sent\.$"
+consistent!(salt_compressor_0, r"(?m)^Minion (\S*) did not respond\. No job will be sent\.$");
+
+// sabisabi-0.4.1: r"</?[^>]+?>"
+consistent!(sabisabi_0, r"</?[^>]+?>");
+
+// sabisabi-0.4.1: r"\([^)]*\)"
+consistent!(sabisabi_1, r"\([^)]*\)");
+
+// sassers-0.13.5-h28: "@import \"([^\"]*)\";"
+consistent!(sassers_0, "@import \"([^\"]*)\";");
+
+// shadowsocks-0.6.2: r"[A-Za-z\d-]{1,63}$"
+consistent!(shadowsocks_0, r"[A-Za-z\d-]{1,63}$");
+
+// shkeleton-0.1.5: "[abc]+"
+consistent!(shkeleton_0, "[abc]+");
+
+// shellwords-0.1.0: r"([^A-Za-z0-9_\-.,:/@\n])"
+consistent!(shellwords_0, r"([^A-Za-z0-9_\-.,:/@\n])");
+
+// shellwords-0.1.0: r"\n"
+consistent!(shellwords_1, r"\n");
+
+// shush-0.1.5: "(?P<num>[0-9]+)(?P<units>[dhms])"
+consistent!(shush_0, "(?P<num>[0-9]+)(?P<units>[dhms])");
+
+// woothee-0.8.0: r"(?:Chrome|CrMo|CriOS)/([.0-9]+)"
+consistent!(woothee_0, r"(?:Chrome|CrMo|CriOS)/([.0-9]+)");
+
+// woothee-0.8.0: r"Vivaldi/([.0-9]+)"
+consistent!(woothee_1, r"Vivaldi/([.0-9]+)");
+
+// woothee-0.8.0: r"Firefox/([.0-9]+)"
+consistent!(woothee_2, r"Firefox/([.0-9]+)");
+
+// woothee-0.8.0: r"^Mozilla/[.0-9]+ \((?:Mobile|Tablet);(?:.*;)? rv:([.0-9]+)\) Gecko/[.0-9]+ Firefox/[.0-9]+$"
+consistent!(woothee_3, r"^Mozilla/[.0-9]+ \((?:Mobile|Tablet);(?:.*;)? rv:([.0-9]+)\) Gecko/[.0-9]+ Firefox/[.0-9]+$");
+
+// woothee-0.8.0: r"FxiOS/([.0-9]+)"
+consistent!(woothee_4, r"FxiOS/([.0-9]+)");
+
+// woothee-0.8.0: r"\(([^;)]+);FOMA;"
+consistent!(woothee_5, r"\(([^;)]+);FOMA;");
+
+// woothee-0.8.0: r"jig browser[^;]+; ([^);]+)"
+consistent!(woothee_6, r"jig browser[^;]+; ([^);]+)");
+
+// woothee-0.8.0: r"(?i)rss(?:reader|bar|[-_ /;()]|[ +]*/)"
+consistent!(woothee_7, r"(?i)rss(?:reader|bar|[-_ /;()]|[ +]*/)");
+
+// woothee-0.8.0: r"(?i)(?:bot|crawler|spider)(?:[-_ ./;@()]|$)"
+consistent!(woothee_8, r"(?i)(?:bot|crawler|spider)(?:[-_ ./;@()]|$)");
+
+// woothee-0.8.0: r"(?i)(?:feed|web) ?parser"
+consistent!(woothee_9, r"(?i)(?:feed|web) ?parser");
+
+// woothee-0.8.0: r"(?i)watch ?dog"
+consistent!(woothee_10, r"(?i)watch ?dog");
+
+// woothee-0.8.0: r"Edge/([.0-9]+)"
+consistent!(woothee_11, r"Edge/([.0-9]+)");
+
+// woothee-0.8.0: r"MSIE ([.0-9]+);"
+consistent!(woothee_12, r"MSIE ([.0-9]+);");
+
+// woothee-0.8.0: r"Version/([.0-9]+)"
+consistent!(woothee_13, r"Version/([.0-9]+)");
+
+// woothee-0.8.0: r"Opera[/ ]([.0-9]+)"
+consistent!(woothee_14, r"Opera[/ ]([.0-9]+)");
+
+// woothee-0.8.0: r"OPR/([.0-9]+)"
+consistent!(woothee_15, r"OPR/([.0-9]+)");
+
+// woothee-0.8.0: r"Version/([.0-9]+)"
+consistent!(woothee_16, r"Version/([.0-9]+)");
+
+// woothee-0.8.0: r"(?:SoftBank|Vodafone|J-PHONE)/[.0-9]+/([^ /;()]+)"
+consistent!(woothee_17, r"(?:SoftBank|Vodafone|J-PHONE)/[.0-9]+/([^ /;()]+)");
+
+// woothee-0.8.0: r"Trident/([.0-9]+);"
+consistent!(woothee_18, r"Trident/([.0-9]+);");
+
+// woothee-0.8.0: r" rv:([.0-9]+)"
+consistent!(woothee_19, r" rv:([.0-9]+)");
+
+// woothee-0.8.0: r"IEMobile/([.0-9]+);"
+consistent!(woothee_20, r"IEMobile/([.0-9]+);");
+
+// woothee-0.8.0: r"(?:WILLCOM|DDIPOCKET);[^/]+/([^ /;()]+)"
+consistent!(woothee_21, r"(?:WILLCOM|DDIPOCKET);[^/]+/([^ /;()]+)");
+
+// woothee-0.8.0: r"Windows ([ .a-zA-Z0-9]+)[;\\)]"
+consistent!(woothee_22, r"Windows ([ .a-zA-Z0-9]+)[;\\)]");
+
+// woothee-0.8.0: r"^Phone(?: OS)? ([.0-9]+)"
+consistent!(woothee_23, r"^Phone(?: OS)? ([.0-9]+)");
+
+// woothee-0.8.0: r"iP(hone;|ad;|od) .*like Mac OS X"
+consistent!(woothee_24, r"iP(hone;|ad;|od) .*like Mac OS X");
+
+// woothee-0.8.0: r"Version/([.0-9]+)"
+consistent!(woothee_25, r"Version/([.0-9]+)");
+
+// woothee-0.8.0: r"rv:(\d+\.\d+\.\d+)"
+consistent!(woothee_26, r"rv:(\d+\.\d+\.\d+)");
+
+// woothee-0.8.0: r"FreeBSD ([^;\)]+);"
+consistent!(woothee_27, r"FreeBSD ([^;\)]+);");
+
+// woothee-0.8.0: r"CrOS ([^\)]+)\)"
+consistent!(woothee_28, r"CrOS ([^\)]+)\)");
+
+// woothee-0.8.0: r"Android[- ](\d+\.\d+(?:\.\d+)?)"
+consistent!(woothee_29, r"Android[- ](\d+\.\d+(?:\.\d+)?)");
+
+// woothee-0.8.0: r"PSP \(PlayStation Portable\); ([.0-9]+)\)"
+consistent!(woothee_30, r"PSP \(PlayStation Portable\); ([.0-9]+)\)");
+
+// woothee-0.8.0: r"PLAYSTATION 3;? ([.0-9]+)\)"
+consistent!(woothee_31, r"PLAYSTATION 3;? ([.0-9]+)\)");
+
+// woothee-0.8.0: r"PlayStation Vita ([.0-9]+)\)"
+consistent!(woothee_32, r"PlayStation Vita ([.0-9]+)\)");
+
+// woothee-0.8.0: r"PlayStation 4 ([.0-9]+)\)"
+consistent!(woothee_33, r"PlayStation 4 ([.0-9]+)\)");
+
+// woothee-0.8.0: r"BB10(?:.+)Version/([.0-9]+) "
+consistent!(woothee_34, r"BB10(?:.+)Version/([.0-9]+) ");
+
+// woothee-0.8.0: r"BlackBerry(?:\d+)/([.0-9]+) "
+consistent!(woothee_35, r"BlackBerry(?:\d+)/([.0-9]+) ");
+
+// woothee-0.8.0: r"; CPU(?: iPhone)? OS (\d+_\d+(?:_\d+)?) like Mac OS X"
+consistent!(woothee_36, r"; CPU(?: iPhone)? OS (\d+_\d+(?:_\d+)?) like Mac OS X");
+
+// woothee-0.8.0: r"Mac OS X (10[._]\d+(?:[._]\d+)?)(?:\)|;)"
+consistent!(woothee_37, r"Mac OS X (10[._]\d+(?:[._]\d+)?)(?:\)|;)");
+
+// woothee-0.8.0: r"^(?:Apache-HttpClient/|Jakarta Commons-HttpClient/|Java/)"
+consistent!(woothee_38, r"^(?:Apache-HttpClient/|Jakarta Commons-HttpClient/|Java/)");
+
+// woothee-0.8.0: r"[- ]HttpClient(/|$)"
+consistent!(woothee_39, r"[- ]HttpClient(/|$)");
+
+// woothee-0.8.0: r"^(?:PHP|WordPress|CakePHP|PukiWiki|PECL::HTTP)(?:/| |$)"
+consistent!(woothee_40, r"^(?:PHP|WordPress|CakePHP|PukiWiki|PECL::HTTP)(?:/| |$)");
+
+// woothee-0.8.0: r"(?:PEAR HTTP_Request|HTTP_Request)(?: class|2)"
+consistent!(woothee_41, r"(?:PEAR HTTP_Request|HTTP_Request)(?: class|2)");
+
+// woothee-0.8.0: r"(?:Rome Client |UnwindFetchor/|ia_archiver |Summify |PostRank/)"
+consistent!(woothee_42, r"(?:Rome Client |UnwindFetchor/|ia_archiver |Summify |PostRank/)");
+
+// woothee-0.8.0: r"Sleipnir/([.0-9]+)"
+consistent!(woothee_43, r"Sleipnir/([.0-9]+)");
+
+// word_replace-0.0.3: r"@@[a-z|A-Z|\d]+@@"
+consistent!(word_replace_0, r"@@[a-z|A-Z|\d]+@@");
+
+// wordcount-0.1.0: r"\w+"
+consistent!(wordcount_0, r"\w+");
+
+// just-0.3.12: "^([^=]+)=(.*)$"
+consistent!(just_0, "^([^=]+)=(.*)$");
+
+// emote-0.1.0: r":[a-zA-Z_]+?:"
+consistent!(emote_0, r":[a-zA-Z_]+?:");
+
+// emojicons-1.0.1: r":([a-zA-Z0-9_+-]+):"
+consistent!(emojicons_0, r":([a-zA-Z0-9_+-]+):");
+
+// git2_codecommit-0.1.2: r"git-codecommit\.([a-z0-9-]+)\.amazonaws\.com"
+consistent!(git2_codecommit_0, r"git-codecommit\.([a-z0-9-]+)\.amazonaws\.com");
+
+// git-workarea-3.1.2: r"^submodule\.(?P<name>.*)\.(?P<key>[^=]*)=(?P<value>.*)$"
+consistent!(git_workarea_0, r"^submodule\.(?P<name>.*)\.(?P<key>[^=]*)=(?P<value>.*)$");
+
+// git-shell-enforce-directory-1.0.0: r"^(?P<command>git-(?:receive|upload)-pack) '(?P<path>.+)'$"
+consistent!(git_shell_enforce_directory_0, r"^(?P<command>git-(?:receive|upload)-pack) '(?P<path>.+)'$");
+
+// git-journal-1.6.3: r"[ \n]:(.*?):"
+consistent!(git_journal_0, r"[ \n]:(.*?):");
+
+// git-find-0.3.2: r"^git@(?P<host>[[:alnum:]\._-]+):(?P<path>[[:alnum:]\._\-/]+).git$"
+consistent!(git_find_0, r"^git@(?P<host>[[:alnum:]\._-]+):(?P<path>[[:alnum:]\._\-/]+).git$");
+
+// gitlab-api-0.6.0: r"private_token=\w{20}"
+consistent!(gitlab_api_0, r"private_token=\w{20}");
+
+// td-client-0.7.0: "^(http://|https://)"
+consistent!(td_client_0, "^(http://|https://)");
+
+// karaconv-0.3.0: r"--(?P<type>[a-zA-Z]+)-- (?P<contents>.*)"
+consistent!(karaconv_0, r"--(?P<type>[a-zA-Z]+)-- (?P<contents>.*)");
+
+// katana-1.0.2: r"(?P<comp>et al\.)(?:\.)"
+consistent!(katana_0, r"(?P<comp>et al\.)(?:\.)");
+
+// katana-1.0.2: r"\.{3}"
+consistent!(katana_1, r"\.{3}");
+
+// katana-1.0.2: r"(?P<number>[0-9]+)\.(?P<decimal>[0-9]+)"
+consistent!(katana_2, r"(?P<number>[0-9]+)\.(?P<decimal>[0-9]+)");
+
+// katana-1.0.2: r"\s\.(?P<nums>[0-9]+)"
+consistent!(katana_3, r"\s\.(?P<nums>[0-9]+)");
+
+// katana-1.0.2: r"(?:[A-Za-z]\.){2,}"
+consistent!(katana_4, r"(?:[A-Za-z]\.){2,}");
+
+// katana-1.0.2: r"(?P<init>[A-Z])(?P<point>\.)"
+consistent!(katana_5, r"(?P<init>[A-Z])(?P<point>\.)");
+
+// katana-1.0.2: r"(?P<title>[A-Z][a-z]{1,3})(\.)"
+consistent!(katana_6, r"(?P<title>[A-Z][a-z]{1,3})(\.)");
+
+// katana-1.0.2: r"&==&(?P<p>[.!?])"
+consistent!(katana_7, r"&==&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&\^&(?P<p>[.!?])"
+consistent!(katana_8, r"&\^&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&\*\*&(?P<p>[.!?])"
+consistent!(katana_9, r"&\*\*&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&=&(?P<p>[.!?])"
+consistent!(katana_10, r"&=&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&##&(?P<p>[.!?])"
+consistent!(katana_11, r"&##&(?P<p>[.!?])");
+
+// katana-1.0.2: r"&\$&(?P<p>[.!?])"
+consistent!(katana_12, r"&\$&(?P<p>[.!?])");
+
+// kailua_syntax-1.1.0: r"@(?:_|\d+(?:/\d+(?:-\d+)?)?)"
+consistent!(kailua_syntax_0, r"@(?:_|\d+(?:/\d+(?:-\d+)?)?)");
+
+// kailua_syntax-1.1.0: r"<(\d+)>"
+consistent!(kailua_syntax_1, r"<(\d+)>");
+
+// ftp-3.0.1: r"\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)"
+consistent!(ftp_0, r"\((\d+),(\d+),(\d+),(\d+),(\d+),(\d+)\)");
+
+// ftp-3.0.1: r"\b(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\b"
+consistent!(ftp_1, r"\b(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\b");
+
+// ftp-3.0.1: r"\s+(\d+)\s*$"
+consistent!(ftp_2, r"\s+(\d+)\s*$");
+
+// vat-0.1.0: r"<countryCode>(.*?)</countryCode>"
+consistent!(vat_0, r"<countryCode>(.*?)</countryCode>");
+
+// vat-0.1.0: r"<vatNumber>(.*?)</vatNumber>"
+consistent!(vat_1, r"<vatNumber>(.*?)</vatNumber>");
+
+// vat-0.1.0: r"<name>(.*?)</name>"
+consistent!(vat_2, r"<name>(.*?)</name>");
+
+// vat-0.1.0: r"<address>(?s)(.*?)(?-s)</address>"
+consistent!(vat_3, r"<address>(?s)(.*?)(?-s)</address>");
+
+// vat-0.1.0: r"<valid>(true|false)</valid>"
+consistent!(vat_4, r"<valid>(true|false)</valid>");
+
+// vat-0.1.0: r"^ATU\d{8}$"
+consistent!(vat_5, r"^ATU\d{8}$");
+
+// vat-0.1.0: r"^BE0?\d{9, 10}$"
+consistent!(vat_6, r"^BE0?\d{9, 10}$");
+
+// vat-0.1.0: r"^BG\d{9,10}$"
+consistent!(vat_7, r"^BG\d{9,10}$");
+
+// vat-0.1.0: r"^HR\d{11}$"
+consistent!(vat_8, r"^HR\d{11}$");
+
+// vat-0.1.0: r"^CY\d{8}[A-Z]$"
+consistent!(vat_9, r"^CY\d{8}[A-Z]$");
+
+// vat-0.1.0: r"^CZ\d{8,10}$"
+consistent!(vat_10, r"^CZ\d{8,10}$");
+
+// vat-0.1.0: r"^DK\d{8}$"
+consistent!(vat_11, r"^DK\d{8}$");
+
+// vat-0.1.0: r"^EE\d{9}$"
+consistent!(vat_12, r"^EE\d{9}$");
+
+// vat-0.1.0: r"^FI\d{8}$"
+consistent!(vat_13, r"^FI\d{8}$");
+
+// vat-0.1.0: r"^FR[A-HJ-NP-Z0-9][A-HJ-NP-Z0-9]\d{9}$"
+consistent!(vat_14, r"^FR[A-HJ-NP-Z0-9][A-HJ-NP-Z0-9]\d{9}$");
+
+// vat-0.1.0: r"^DE\d{9}$"
+consistent!(vat_15, r"^DE\d{9}$");
+
+// vat-0.1.0: r"^EL\d{9}$"
+consistent!(vat_16, r"^EL\d{9}$");
+
+// vat-0.1.0: r"^HU\d{8}$"
+consistent!(vat_17, r"^HU\d{8}$");
+
+// vat-0.1.0: r"^IE\d[A-Z0-9\+\*]\d{5}[A-Z]{1,2}$"
+consistent!(vat_18, r"^IE\d[A-Z0-9\+\*]\d{5}[A-Z]{1,2}$");
+
+// vat-0.1.0: r"^IT\d{11}$"
+consistent!(vat_19, r"^IT\d{11}$");
+
+// vat-0.1.0: r"^LV\d{11}$"
+consistent!(vat_20, r"^LV\d{11}$");
+
+// vat-0.1.0: r"^LT(\d{9}|\d{12})$"
+consistent!(vat_21, r"^LT(\d{9}|\d{12})$");
+
+// vat-0.1.0: r"^LU\d{8}$"
+consistent!(vat_22, r"^LU\d{8}$");
+
+// vat-0.1.0: r"^MT\d{8}$"
+consistent!(vat_23, r"^MT\d{8}$");
+
+// vat-0.1.0: r"^NL\d{9}B\d{2}$"
+consistent!(vat_24, r"^NL\d{9}B\d{2}$");
+
+// vat-0.1.0: r"^PL\d{10}$"
+consistent!(vat_25, r"^PL\d{10}$");
+
+// vat-0.1.0: r"^PT\d{9}$"
+consistent!(vat_26, r"^PT\d{9}$");
+
+// vat-0.1.0: r"^RO\d{2,10}$"
+consistent!(vat_27, r"^RO\d{2,10}$");
+
+// vat-0.1.0: r"^SK\d{10}$"
+consistent!(vat_28, r"^SK\d{10}$");
+
+// vat-0.1.0: r"^SI\d{8}$"
+consistent!(vat_29, r"^SI\d{8}$");
+
+// vat-0.1.0: r"^ES[A-Z0-9]\d{7}[A-Z0-9]$"
+consistent!(vat_30, r"^ES[A-Z0-9]\d{7}[A-Z0-9]$");
+
+// vat-0.1.0: r"^SE\d{10}01$"
+consistent!(vat_31, r"^SE\d{10}01$");
+
+// vat-0.1.0: r"^(GB(GD|HA)\d{3}|GB\d{9}|GB\d{12})$"
+consistent!(vat_32, r"^(GB(GD|HA)\d{3}|GB\d{9}|GB\d{12})$");
+
+// eve-0.1.1: r"\{\{(.*)\}\}"
+consistent!(eve_0, r"\{\{(.*)\}\}");
+
+// egc-0.1.2: "^mio"
+consistent!(egc_0, "^mio");
+
+// pew-0.2.3: ""
+consistent!(pew_0, "");
+
+// pew-0.2.3: ""
+consistent!(pew_1, "");
+
+// mob-0.4.3: "y"
+consistent!(mob_0, "y");
+
+// lit-0.2.8: "@([a-z]+)"
+consistent!(lit_0, "@([a-z]+)");
+
+// lit-0.2.8: "([A-Z-]+):(.*)"
+consistent!(lit_1, "([A-Z-]+):(.*)");
+
+// lit-0.2.8: "^[a-zA-Z_][a-zA-Z0-9_]*$"
+consistent!(lit_2, "^[a-zA-Z_][a-zA-Z0-9_]*$");
+
+// avm-1.0.1: r"\d+\.\d+\.\d+"
+consistent!(avm_0, r"\d+\.\d+\.\d+");
+
+// avm-1.0.1: r"\d+\.\d+\.\d+"
+consistent!(avm_1, r"\d+\.\d+\.\d+");
+
+// orm-0.2.0: r"^Vec<(.+)>$"
+consistent!(orm_0, r"^Vec<(.+)>$");
+
+// sgf-0.1.5: r"\\(\r\n|\n\r|\n|\r)"
+consistent!(sgf_0, r"\\(\r\n|\n\r|\n|\r)");
+
+// sgf-0.1.5: r"\\(.)"
+consistent!(sgf_1, r"\\(.)");
+
+// sgf-0.1.5: r"\r\n|\n\r|\n|\r"
+consistent!(sgf_2, r"\r\n|\n\r|\n|\r");
+
+// sgf-0.1.5: r"([\]\\:])"
+consistent!(sgf_3, r"([\]\\:])");
+
+// dok-0.2.0: "^Bearer realm=\"(.+?)\",service=\"(.+?)\",scope=\"(.+?)\"$"
+consistent!(dok_0, "^Bearer realm=\"(.+?)\",service=\"(.+?)\",scope=\"(.+?)\"$");
+
+// d20-0.1.0: r"([+-]?\s*\d+[dD]\d+|[+-]?\s*\d+)"
+consistent!(d20_0, r"([+-]?\s*\d+[dD]\d+|[+-]?\s*\d+)");
+
+// dvb-0.3.0: "E"
+consistent!(dvb_0, "E");
+
+// dvb-0.3.0: "^F"
+consistent!(dvb_1, "^F");
+
+// dvb-0.3.0: "^S"
+consistent!(dvb_2, "^S");
+
+// ger-0.2.0: r"Change-Id: (I[a-f0-9]{40})$"
+consistent!(ger_0, r"Change-Id: (I[a-f0-9]{40})$");
+
+// ger-0.2.0: r"(refs|ref|fix|fixes|close|closes)\s+([A-Z]{2,5}-[0-9]{1,5})$"
+consistent!(ger_1, r"(refs|ref|fix|fixes|close|closes)\s+([A-Z]{2,5}-[0-9]{1,5})$");
+
+// n5-0.2.1: r"(\d+)(\.(\d+))?(\.(\d+))?(.*)"
+consistent!(n5_0, r"(\d+)(\.(\d+))?(\.(\d+))?(.*)");
+
+// po-0.1.4: r"[A-Za-z0-9]"
+consistent!(po_0, r"[A-Za-z0-9]");
+
+// carnix-0.8.5: "path is (‘|')?([^’'\n]*)(’|')?"
+consistent!(carnix_0, "path is (‘|')?([^’'\n]*)(’|')?");
+
+// carnix-0.8.5: r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?(.*)?"
+consistent!(carnix_1, r"^(\S*) (\d*)\.(\d*)\.(\d*)(-(\S*))?(.*)?");
+
+// carnix-0.8.5: r"(\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(carnix_2, r"(\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// carnix-0.8.5: r"(\S*)-(\d*)\.(\d*)\.(\d*)(-(\S*))?"
+consistent!(carnix_3, r"(\S*)-(\d*)\.(\d*)\.(\d*)(-(\S*))?");
+
+// caseless-0.2.1: r"^# CaseFolding-(\d+)\.(\d+)\.(\d+).txt$"
+consistent!(caseless_0, r"^# CaseFolding-(\d+)\.(\d+)\.(\d+).txt$");
+
+// caseless-0.2.1: r"^([0-9A-F]+); [CF]; ([0-9A-F ]+);"
+consistent!(caseless_1, r"^([0-9A-F]+); [CF]; ([0-9A-F ]+);");
+
+// cabot-0.2.0: "\r?\n\r?\n"
+consistent!(cabot_0, "\r?\n\r?\n");
+
+// cabot-0.2.0: "\r?\n"
+consistent!(cabot_1, "\r?\n");
+
+// card-validate-2.2.1: r"^600"
+consistent!(card_validate_0, r"^600");
+
+// card-validate-2.2.1: r"^5019"
+consistent!(card_validate_1, r"^5019");
+
+// card-validate-2.2.1: r"^4"
+consistent!(card_validate_2, r"^4");
+
+// card-validate-2.2.1: r"^(5[1-5]|2[2-7])"
+consistent!(card_validate_3, r"^(5[1-5]|2[2-7])");
+
+// card-validate-2.2.1: r"^3[47]"
+consistent!(card_validate_4, r"^3[47]");
+
+// card-validate-2.2.1: r"^3[0689]"
+consistent!(card_validate_5, r"^3[0689]");
+
+// card-validate-2.2.1: r"^6([045]|22)"
+consistent!(card_validate_6, r"^6([045]|22)");
+
+// card-validate-2.2.1: r"^(62|88)"
+consistent!(card_validate_7, r"^(62|88)");
+
+// card-validate-2.2.1: r"^35"
+consistent!(card_validate_8, r"^35");
+
+// card-validate-2.2.1: r"^[0-9]+$"
+consistent!(card_validate_9, r"^[0-9]+$");
+
+// cargo-testify-0.3.0: r"\d{1,} passed.*filtered out"
+consistent!(cargo_testify_0, r"\d{1,} passed.*filtered out");
+
+// cargo-testify-0.3.0: r"error(:|\[).*"
+consistent!(cargo_testify_1, r"error(:|\[).*");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_0, r"<(.*?)>");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_1, r"<(.*?)>");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_2, r"<(.*?)>");
+
+// cargo-wix-0.0.5: r"<(.*?)>"
+consistent!(cargo_wix_3, r"<(.*?)>");
+
+// cargo-incremental-0.1.23: r"(?m)^incremental: re-using (\d+) out of (\d+) modules$"
+consistent!(cargo_incremental_0, r"(?m)^incremental: re-using (\d+) out of (\d+) modules$");
+
+// cargo-incremental-0.1.23: "(?m)(warning|error): (.*)\n --> ([^:]:\\d+:\\d+)$"
+consistent!(cargo_incremental_1, "(?m)(warning|error): (.*)\n --> ([^:]:\\d+:\\d+)$");
+
+// cargo-incremental-0.1.23: r"(?m)^test (.*) \.\.\. (\w+)"
+consistent!(cargo_incremental_2, r"(?m)^test (.*) \.\.\. (\w+)");
+
+// cargo-incremental-0.1.23: r"(?m)(\d+) passed; (\d+) failed; (\d+) ignored; \d+ measured"
+consistent!(cargo_incremental_3, r"(?m)(\d+) passed; (\d+) failed; (\d+) ignored; \d+ measured");
+
+// cargo-testjs-0.1.2: r"^[^-]+-[0-9a-f]+\.js$"
+consistent!(cargo_testjs_0, r"^[^-]+-[0-9a-f]+\.js$");
+
+// cargo-tarpaulin-0.6.2: r"\s*//"
+consistent!(cargo_tarpaulin_0, r"\s*//");
+
+// cargo-tarpaulin-0.6.2: r"/\*"
+consistent!(cargo_tarpaulin_1, r"/\*");
+
+// cargo-tarpaulin-0.6.2: r"\*/"
+consistent!(cargo_tarpaulin_2, r"\*/");
+
+// cargo-culture-kit-0.1.0: r"^fo"
+consistent!(cargo_culture_kit_0, r"^fo");
+
+// cargo-screeps-0.1.3: "\\s+"
+consistent!(cargo_screeps_0, "\\s+");
+
+// cargo-brew-0.1.4: r"`(\S+) v([0-9.]+)"
+consistent!(cargo_brew_0, r"`(\S+) v([0-9.]+)");
+
+// cargo-release-0.10.2: "^\\[.+\\]"
+consistent!(cargo_release_0, "^\\[.+\\]");
+
+// cargo-release-0.10.2: "^\\[\\[.+\\]\\]"
+consistent!(cargo_release_1, "^\\[\\[.+\\]\\]");
+
+// cargo-edit-0.3.0-beta.1: r"^https://github.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
+consistent!(cargo_edit_0, r"^https://github.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$");
+
+// cargo-edit-0.3.0-beta.1: r"^https://gitlab.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$"
+consistent!(cargo_edit_1, r"^https://gitlab.com/([-_0-9a-zA-Z]+)/([-_0-9a-zA-Z]+)(/|.git)?$");
+
+// cargo-disassemble-0.1.1: ".*"
+consistent!(cargo_disassemble_0, ".*");
+
+// cargo-demangle-0.1.2: r"(?m)(?P<symbol>_ZN[0-9]+.*E)"
+consistent!(cargo_demangle_0, r"(?m)(?P<symbol>_ZN[0-9]+.*E)");
+
+// cargo-coverage-annotations-0.1.5: r"^\s*\}(?:\)*;?|\s*else\s*\{)$"
+consistent!(cargo_coverage_annotations_0, r"^\s*\}(?:\)*;?|\s*else\s*\{)$");
+
+// cargo-urlcrate-1.0.1: "[\u{001b}\u{009b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]"
+consistent!(cargo_urlcrate_0, "[\u{001b}\u{009b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]");
+
+// cargo-script-0.2.8: r"^\s*\*( |$)"
+consistent!(cargo_script_0, r"^\s*\*( |$)");
+
+// cargo-script-0.2.8: r"^(\s+)"
+consistent!(cargo_script_1, r"^(\s+)");
+
+// cargo-script-0.2.8: r"/\*|\*/"
+consistent!(cargo_script_2, r"/\*|\*/");
+
+// cargo-script-0.2.8: r"^\s*//!"
+consistent!(cargo_script_3, r"^\s*//!");
+
+// cargo-script-0.2.8: r"^#![^\[].*?(\r\n|\n)"
+consistent!(cargo_script_4, r"^#![^\[].*?(\r\n|\n)");
+
+// cargo-update-1.5.2: r"cargo-install-update\.exe-v.+"
+consistent!(cargo_update_0, r"cargo-install-update\.exe-v.+");
+
+// canteen-0.4.1: r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$"
+consistent!(canteen_0, r"^<(?:(int|uint|str|float|path):)?([\w_][a-zA-Z0-9_]*)>$");
+
+// thruster-cli-0.1.3: r"(.)([A-Z])"
+consistent!(thruster_cli_0, r"(.)([A-Z])");
+
+// thieves-cant-0.1.0: "([Z]+)$"
+consistent!(thieves_cant_0, "([Z]+)$");
+
+// codeowners-0.1.3: r"^@\S+/\S+"
+consistent!(codeowners_0, r"^@\S+/\S+");
+
+// codeowners-0.1.3: r"^@\S+"
+consistent!(codeowners_1, r"^@\S+");
+
+// codeowners-0.1.3: r"^\S+@\S+"
+consistent!(codeowners_2, r"^\S+@\S+");
+
+// conserve-0.4.2: r"^b0000 {21} complete 20[-0-9T:+]+\s +\d+s\n$"
+consistent!(conserve_0, r"^b0000 {21} complete 20[-0-9T:+]+\s +\d+s\n$");
+
+// commodore-0.3.0: r"(?P<greeting>\S+?) (?P<name>\S+?)$"
+consistent!(commodore_0, r"(?P<greeting>\S+?) (?P<name>\S+?)$");
+
+// corollary-0.3.0: r"([ \t]*)```haskell([\s\S]*?)```"
+consistent!(corollary_0, r"([ \t]*)```haskell([\s\S]*?)```");
+
+// corollary-0.3.0: r"\b((?:a|b|t)\d*)\b"
+consistent!(corollary_1, r"\b((?:a|b|t)\d*)\b");
+
+// colorizex-0.1.3: "NB"
+consistent!(colorizex_0, "NB");
+
+// colorstring-0.0.1: r"(?i)\[[a-z0-9_-]+\]"
+consistent!(colorstring_0, r"(?i)\[[a-z0-9_-]+\]");
+
+// colorstring-0.0.1: r"^(?i)(\[[a-z0-9_-]+\])+"
+consistent!(colorstring_1, r"^(?i)(\[[a-z0-9_-]+\])+");
+
+// cosmogony-0.3.0: "name:(.+)"
+consistent!(cosmogony_0, "name:(.+)");
+
+// cobalt-bin-0.12.1: r"(?m:^ {0,3}\[[^\]]+\]:.+$)"
+consistent!(cobalt_bin_0, r"(?m:^ {0,3}\[[^\]]+\]:.+$)");
+
+// comrak-0.2.12: r"[^\p{L}\p{M}\p{N}\p{Pc} -]"
+consistent!(comrak_0, r"[^\p{L}\p{M}\p{N}\p{Pc} -]");
+
+// content-blocker-0.2.3: ""
+consistent!(content_blocker_0, "");
+
+// content-blocker-0.2.3: "(?i)hi"
+consistent!(content_blocker_1, "(?i)hi");
+
+// content-blocker-0.2.3: "http[s]?://domain.org"
+consistent!(content_blocker_2, "http[s]?://domain.org");
+
+// content-blocker-0.2.3: "(?i)http[s]?://domain.org"
+consistent!(content_blocker_3, "(?i)http[s]?://domain.org");
+
+// content-blocker-0.2.3: "http://domain.org"
+consistent!(content_blocker_4, "http://domain.org");
+
+// content-blocker-0.2.3: "http://domain.org"
+consistent!(content_blocker_5, "http://domain.org");
+
+// content-blocker-0.2.3: "ad.html"
+consistent!(content_blocker_6, "ad.html");
+
+// content-blocker-0.2.3: "ad.html"
+consistent!(content_blocker_7, "ad.html");
+
+// content-blocker-0.2.3: "http://domain.org"
+consistent!(content_blocker_8, "http://domain.org");
+
+// content-blocker-0.2.3: "http://domain.org/nocookies.sjs"
+consistent!(content_blocker_9, "http://domain.org/nocookies.sjs");
+
+// content-blocker-0.2.3: "http://domain.org/nocookies.sjs"
+consistent!(content_blocker_10, "http://domain.org/nocookies.sjs");
+
+// content-blocker-0.2.3: "http://domain.org/hideme.jpg"
+consistent!(content_blocker_11, "http://domain.org/hideme.jpg");
+
+// content-blocker-0.2.3: "http://domain.org/ok.html"
+consistent!(content_blocker_12, "http://domain.org/ok.html");
+
+// content-blocker-0.2.3: "http://domain.org/ok.html\\?except_this=1"
+consistent!(content_blocker_13, "http://domain.org/ok.html\\?except_this=1");
+
+// victoria-dom-0.1.2: "[A-Za-z0-9=]"
+consistent!(victoria_dom_0, "[A-Za-z0-9=]");
+
+// numbat-1.0.0: r"^nsq://"
+consistent!(numbat_0, r"^nsq://");
+
+// airkorea-0.1.2: r"[\s\t\r\n]"
+consistent!(airkorea_0, r"[\s\t\r\n]");
+
+// airkorea-0.1.2: r"([\{\[,])|([\}\]])"
+consistent!(airkorea_1, r"([\{\[,])|([\}\]])");
+
+// airkorea-0.1.2: r"[^.\d]+$"
+consistent!(airkorea_2, r"[^.\d]+$");
+
+// rofl-0.0.1: r"\b"
+// consistent!(rofl_0, r"\b");
+
+// rogcat-0.2.15: r"--------- beginning of.*"
+consistent!(rogcat_0, r"--------- beginning of.*");
+
+// rogcat-0.2.15: r"a|e|i|o|u"
+consistent!(rogcat_1, r"a|e|i|o|u");
+
+// rogcat-0.2.15: r"^(\d+)([kMG])$"
+consistent!(rogcat_2, r"^(\d+)([kMG])$");
+
+// media_filename-0.1.4: "\\.([A-Za-z0-9]{2,4})$"
+consistent!(media_filename_0, "\\.([A-Za-z0-9]{2,4})$");
+
+// media_filename-0.1.4: "([0-9]{3,4}p|[0-9]{3,4}x[0-9]{3,4})"
+consistent!(media_filename_1, "([0-9]{3,4}p|[0-9]{3,4}x[0-9]{3,4})");
+
+// media_filename-0.1.4: "(?:^\\[([^]]+)\\]|- ?([^-]+)$)"
+consistent!(media_filename_2, "(?:^\\[([^]]+)\\]|- ?([^-]+)$)");
+
+// media_filename-0.1.4: "(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])"
+consistent!(media_filename_3, "(?:[eE]([0-9]{2,3})|[^0-9A-Za-z]([0-9]{2,3})(?:v[0-9])?[^0-9A-Za-z])");
+
+// media_filename-0.1.4: "[sS]([0-9]{1,2})"
+consistent!(media_filename_4, "[sS]([0-9]{1,2})");
+
+// media_filename-0.1.4: "((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|[^a-z]TS[^a-z]|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|BD|DVD|DvDScr|hdtv)"
+consistent!(media_filename_5, "((?i)(?:PPV.)?[HP]DTV|(?:HD)?CAM|BRRIP|[^a-z]TS[^a-z]|(?:PPV )?WEB.?DL(?: DVDRip)?|HDRip|DVDRip|CamRip|W[EB]BRip|BluRay|BD|DVD|DvDScr|hdtv)");
+
+// media_filename-0.1.4: "((19[0-9]|20[01])[0-9])"
+consistent!(media_filename_6, "((19[0-9]|20[01])[0-9])");
+
+// media_filename-0.1.4: "((?i)xvid|x264|h\\.?264)"
+consistent!(media_filename_7, "((?i)xvid|x264|h\\.?264)");
+
+// media_filename-0.1.4: "((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)"
+consistent!(media_filename_8, "((?i)MP3|DD5\\.?1|Dual[- ]Audio|LiNE|DTS|AAC(?:\\.?2\\.0)?|AC3(?:\\.5\\.1)?)");
+
+// media_filename-0.1.4: "\\[([0-9A-F]{8})\\]"
+consistent!(media_filename_9, "\\[([0-9A-F]{8})\\]");
+
+// termimage-0.3.2: r"(\d+)[xX](\d+)"
+consistent!(termimage_0, r"(\d+)[xX](\d+)");
+
+// teensy-0.1.0: r".*(\d{4}-\d{2}-\d{2}).*"
+consistent!(teensy_0, r".*(\d{4}-\d{2}-\d{2}).*");
+
+// telescreen-0.1.3: r"<@(.+)>"
+consistent!(telescreen_0, r"<@(.+)>");
+
+// tempus_fugit-0.4.4: r"^(\d+)"
+consistent!(tempus_fugit_0, r"^(\d+)");
+
+// fselect-0.4.1: "(\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)"
+consistent!(fselect_0, "(\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)");
+
+// fselect-0.4.1: "(%|_|\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)"
+consistent!(fselect_1, "(%|_|\\?|\\.|\\*|\\[|\\]|\\(|\\)|\\^|\\$)");
+
+// fs_eventbridge-0.1.0: r"^([A-Z]+)(?:\s(.+))?\s*"
+consistent!(fs_eventbridge_0, r"^([A-Z]+)(?:\s(.+))?\s*");
+
+// joseki-0.0.1: r"(\w{1,2})\[(.+?)\]"
+consistent!(joseki_0, r"(\w{1,2})\[(.+?)\]");
+
+// tweetr-0.2.1: r"(?i)in (\d+) (second|minute|hour|day|week)s?"
+consistent!(tweetr_0, r"(?i)in (\d+) (second|minute|hour|day|week)s?");
+
+// bullet_core-0.1.1: "^(?u:[0-9])+"
+consistent!(bullet_core_0, "^(?u:[0-9])+");
+
+// bullet_core-0.1.1: "^(?u:[0-9])+(?u:\\.)(?u:[0-9])+"
+consistent!(bullet_core_1, "^(?u:[0-9])+(?u:\\.)(?u:[0-9])+");
+
+// bullet_core-0.1.1: "^(?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+"
+consistent!(bullet_core_2, "^(?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+");
+
+// bullet_core-0.1.1: "^(?u:d/d)((?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+)"
+consistent!(bullet_core_3, "^(?u:d/d)((?u:[A-Za-zª-ªµ-µº-ºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬ-ˬˮ-ˮͰ-ʹͶ-ͷͺ-ͽͿ-ͿΆ-ΆΈ-ΊΌ-ΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙ-ՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓە-ەۥ-ۦۮ-ۯۺ-ۼۿ-ۿܐ-ܐܒ-ܯݍ-ޥޱ-ޱߊ-ߪߴ-ߵߺ-ߺࠀ-ࠕࠚ-ࠚࠤ-ࠤࠨ-ࠨࡀ-ࡘࢠ-ࢴऄ-हऽ-ऽॐ-ॐक़-ॡॱ-ঀঅ-ঌএ-ঐও-নপ-রল-লশ-হঽ-ঽৎ-ৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼-ਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽ-ઽૐ-ૐૠ-ૡૹ-ૹଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽ-ଽଡ଼-ଢ଼ୟ-ୡୱ-ୱஃ-ஃஅ-ஊஎ-ஐஒ-கங-சஜ-ஜஞ-டண-தந-பம-ஹௐ-ௐఅ-ఌఎ-ఐఒ-నప-హఽ-ఽౘ-ౚౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ಽೞ-ೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽ-ഽൎ-ൎൟ-ൡൺ-ൿඅ-ඖක-නඳ-රල-ලව-ෆก-ะา-ำเ-ๆກ-ຂຄ-ຄງ-ຈຊ-ຊຍ-ຍດ-ທນ-ຟມ-ຣລ-ລວ-ວສ-ຫອ-ະາ-ຳຽ-ຽເ-ໄໆ-ໆໜ-ໟༀ-ༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿ-ဿၐ-ၕၚ-ၝၡ-ၡၥ-ၦၮ-ၰၵ-ႁႎ-ႎႠ-ჅჇ-ჇჍ-Ⴭა-ჺჼ-ቈቊ-ቍቐ-ቖቘ-ቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀ-ዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛱ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗ-ៗៜ-ៜᠠ-ᡷᢀ-ᢨᢪ-ᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧ-ᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙ-ὙὛ-ὛὝ-ὝὟ-ώᾀ-ᾴᾶ-ᾼι-ιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱ-ⁱⁿ-ⁿₐ-ₜℂ-ℂℇ-ℇℊ-ℓℕ-ℕℙ-ℝℤ-ℤΩ-Ωℨ-ℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎ-ⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧ-ⴧⴭ-ⴭⴰ-ⵧⵯ-ⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ-ⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚝꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻ-ꣻꣽ-ꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏ-ꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺ-ꩺꩾ-ꪯꪱ-ꪱꪵ-ꪶꪹ-ꪽꫀ-ꫀꫂ-ꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-יִײַ-ﬨשׁ-זּטּ-לּמּ-מּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ𐀀-𐀋𐀍-𐀦𐀨-𐀺𐀼-𐀽𐀿-𐁍𐁐-𐁝𐂀-𐃺𐊀-𐊜𐊠-𐋐𐌀-𐌟𐌰-𐍀𐍂-𐍉𐍐-𐍵𐎀-𐎝𐎠-𐏃𐏈-𐏏𐐀-𐒝𐔀-𐔧𐔰-𐕣𐘀-𐜶𐝀-𐝕𐝠-𐝧𐠀-𐠅𐠈-𐠈𐠊-𐠵𐠷-𐠸𐠼-𐠼𐠿-𐡕𐡠-𐡶𐢀-𐢞𐣠-𐣲𐣴-𐣵𐤀-𐤕𐤠-𐤹𐦀-𐦷𐦾-𐦿𐨀-𐨀𐨐-𐨓𐨕-𐨗𐨙-𐨳𐩠-𐩼𐪀-𐪜𐫀-𐫇𐫉-𐫤𐬀-𐬵𐭀-𐭕𐭠-𐭲𐮀-𐮑𐰀-𐱈𐲀-𐲲𐳀-𐳲𑀃-𑀷𑂃-𑂯𑃐-𑃨𑄃-𑄦𑅐-𑅲𑅶-𑅶𑆃-𑆲𑇁-𑇄𑇚-𑇚𑇜-𑇜𑈀-𑈑𑈓-𑈫𑊀-𑊆𑊈-𑊈𑊊-𑊍𑊏-𑊝𑊟-𑊨𑊰-𑋞𑌅-𑌌𑌏-𑌐𑌓-𑌨𑌪-𑌰𑌲-𑌳𑌵-𑌹𑌽-𑌽𑍐-𑍐𑍝-𑍡𑒀-𑒯𑓄-𑓅𑓇-𑓇𑖀-𑖮𑗘-𑗛𑘀-𑘯𑙄-𑙄𑚀-𑚪𑜀-𑜙𑢠-𑣟𑣿-𑣿𑫀-𑫸𒀀-𒎙𒒀-𒕃𓀀-𓐮𔐀-𔙆𖠀-𖨸𖩀-𖩞𖫐-𖫭𖬀-𖬯𖭀-𖭃𖭣-𖭷𖭽-𖮏𖼀-𖽄𖽐-𖽐𖾓-𖾟𛀀-𛀁𛰀-𛱪𛱰-𛱼𛲀-𛲈𛲐-𛲙𝐀-𝑔𝑖-𝒜𝒞-𝒟𝒢-𝒢𝒥-𝒦𝒩-𝒬𝒮-𝒹𝒻-𝒻𝒽-𝓃𝓅-𝔅𝔇-𝔊𝔍-𝔔𝔖-𝔜𝔞-𝔹𝔻-𝔾𝕀-𝕄𝕆-𝕆𝕊-𝕐𝕒-𝚥𝚨-𝛀𝛂-𝛚𝛜-𝛺𝛼-𝜔𝜖-𝜴𝜶-𝝎𝝐-𝝮𝝰-𝞈𝞊-𝞨𝞪-𝟂𝟄-𝟋𞠀-𞣄𞸀-𞸃𞸅-𞸟𞸡-𞸢𞸤-𞸤𞸧-𞸧𞸩-𞸲𞸴-𞸷𞸹-𞸹𞸻-𞸻𞹂-𞹂𞹇-𞹇𞹉-𞹉𞹋-𞹋𞹍-𞹏𞹑-𞹒𞹔-𞹔𞹗-𞹗𞹙-𞹙𞹛-𞹛𞹝-𞹝𞹟-𞹟𞹡-𞹢𞹤-𞹤𞹧-𞹪𞹬-𞹲𞹴-𞹷𞹹-𞹼𞹾-𞹾𞺀-𞺉𞺋-𞺛𞺡-𞺣𞺥-𞺩𞺫-𞺻𠀀-𪛖𪜀-𫜴𫝀-𫠝𫠠-𬺡丽-𪘀])+)");
+
+// bullet_core-0.1.1: "^(?u:\\()"
+consistent!(bullet_core_4, "^(?u:\\()");
+
+// bullet_core-0.1.1: "^(?u:\\))"
+consistent!(bullet_core_5, "^(?u:\\))");
+
+// bullet_core-0.1.1: "^(?u:\\*)"
+consistent!(bullet_core_6, "^(?u:\\*)");
+
+// bullet_core-0.1.1: "^(?u:\\+)"
+consistent!(bullet_core_7, "^(?u:\\+)");
+
+// bullet_core-0.1.1: "^(?u:,)"
+consistent!(bullet_core_8, "^(?u:,)");
+
+// bullet_core-0.1.1: "^(?u:\\-)"
+consistent!(bullet_core_9, "^(?u:\\-)");
+
+// bullet_core-0.1.1: "^(?u:/)"
+consistent!(bullet_core_10, "^(?u:/)");
+
+// bullet_core-0.1.1: "^(?u:\\[)"
+consistent!(bullet_core_11, "^(?u:\\[)");
+
+// bullet_core-0.1.1: "^(?u:\\])"
+consistent!(bullet_core_12, "^(?u:\\])");
+
+// bullet_core-0.1.1: "^(?u:\\^)"
+consistent!(bullet_core_13, "^(?u:\\^)");
+
+// bullet_core-0.1.1: "^(?u:·)"
+consistent!(bullet_core_14, "^(?u:·)");
+
+// actix-web-0.6.13: "//+"
+consistent!(actix_web_0, "//+");
+
+// actix-web-0.6.13: "//+"
+consistent!(actix_web_1, "//+");
+
+// althea_kernel_interface-0.1.0: r"(\S*) .* (\S*) (REACHABLE|STALE|DELAY)"
+consistent!(althea_kernel_interface_0, r"(\S*) .* (\S*) (REACHABLE|STALE|DELAY)");
+
+// althea_kernel_interface-0.1.0: r"-s (.*) --ip6-dst (.*)/.* bcnt = (.*)"
+consistent!(althea_kernel_interface_1, r"-s (.*) --ip6-dst (.*)/.* bcnt = (.*)");
+
+// alcibiades-0.3.0: r"\buci(?:\s|$)"
+consistent!(alcibiades_0, r"\buci(?:\s|$)");
+
+// ruma-identifiers-0.11.0: r"\A[a-z0-9._=-]+\z"
+consistent!(ruma_identifiers_0, r"\A[a-z0-9._=-]+\z");
+
+// rusqbin-0.2.3: r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})$"
+consistent!(rusqbin_0, r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})$");
+
+// rusqbin-0.2.3: r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})/requests/?$"
+consistent!(rusqbin_1, r"/rusqbins/((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})/requests/?$");
+
+// rust-install-0.0.4: r"^(nightly|beta|stable)(?:-(\d{4}-\d{2}-\d{2}))?$"
+consistent!(rust_install_0, r"^(nightly|beta|stable)(?:-(\d{4}-\d{2}-\d{2}))?$");
+
+// rust_inbox-0.0.5: "^+(.*)\r\n"
+consistent!(rust_inbox_0, "^+(.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* CAPABILITY (.*)\r\n"
+consistent!(rust_inbox_1, r"^\* CAPABILITY (.*)\r\n");
+
+// rust_inbox-0.0.5: r"^([a-zA-Z0-9]+) (OK|NO|BAD)(.*)"
+consistent!(rust_inbox_2, r"^([a-zA-Z0-9]+) (OK|NO|BAD)(.*)");
+
+// rust_inbox-0.0.5: r"^\* (\d+) EXISTS\r\n"
+consistent!(rust_inbox_3, r"^\* (\d+) EXISTS\r\n");
+
+// rust_inbox-0.0.5: r"^\* (\d+) RECENT\r\n"
+consistent!(rust_inbox_4, r"^\* (\d+) RECENT\r\n");
+
+// rust_inbox-0.0.5: r"^\* FLAGS (.+)\r\n"
+consistent!(rust_inbox_5, r"^\* FLAGS (.+)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[UNSEEN (\d+)\](.*)\r\n"
+consistent!(rust_inbox_6, r"^\* OK \[UNSEEN (\d+)\](.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n"
+consistent!(rust_inbox_7, r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n"
+consistent!(rust_inbox_8, r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n");
+
+// rust_inbox-0.0.5: r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n"
+consistent!(rust_inbox_9, r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n");
+
+// rustml-0.0.7: r"^[a-z]+ (\d+)$"
+consistent!(rustml_0, r"^[a-z]+ (\d+)$");
+
+// rustml-0.0.7: r"^[a-z]+ (\d+)$"
+consistent!(rustml_1, r"^[a-z]+ (\d+)$");
+
+// rustml-0.0.7: r"^[a-z]+ (\d+)$"
+consistent!(rustml_2, r"^[a-z]+ (\d+)$");
+
+// rustfmt-0.10.0: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
+consistent!(rustfmt_0, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
+
+// rustfmt-core-0.4.0: r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)"
+consistent!(rustfmt_core_0, r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)");
+
+// rustfmt-core-0.4.0: r"^## `([^`]+)`"
+consistent!(rustfmt_core_1, r"^## `([^`]+)`");
+
+// rustfmt-core-0.4.0: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
+consistent!(rustfmt_core_2, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
+
+// rustfmt-core-0.4.0: r"\s;"
+consistent!(rustfmt_core_3, r"\s;");
+
+// rust-enum-derive-0.4.0: r"^(0x)?([:digit:]+)$"
+consistent!(rust_enum_derive_0, r"^(0x)?([:digit:]+)$");
+
+// rust-enum-derive-0.4.0: r"^([:digit:]+)[:space:]*<<[:space:]*([:digit:]+)$"
+consistent!(rust_enum_derive_1, r"^([:digit:]+)[:space:]*<<[:space:]*([:digit:]+)$");
+
+// rust-enum-derive-0.4.0: r"^[:space:]*([[:alnum:]_]+)([:space:]*=[:space:]*([:graph:]+))?[:space:]*,"
+consistent!(rust_enum_derive_2, r"^[:space:]*([[:alnum:]_]+)([:space:]*=[:space:]*([:graph:]+))?[:space:]*,");
+
+// rust-enum-derive-0.4.0: r"^#define[:space:]+([:graph:]+)[:space:]+([:graph:]+)"
+consistent!(rust_enum_derive_3, r"^#define[:space:]+([:graph:]+)[:space:]+([:graph:]+)");
+
+// rustsourcebundler-0.2.0: r"^\s*pub mod (.+);$"
+consistent!(rustsourcebundler_0, r"^\s*pub mod (.+);$");
+
+// rustsourcebundler-0.2.0: r"^\s*pub mod (.+);$"
+consistent!(rustsourcebundler_1, r"^\s*pub mod (.+);$");
+
+// rustfmt-nightly-0.8.2: r"([^\\](\\\\)*)\\[\n\r][[:space:]]*"
+consistent!(rustfmt_nightly_0, r"([^\\](\\\\)*)\\[\n\r][[:space:]]*");
+
+// rustfmt-nightly-0.8.2: r"\s;"
+consistent!(rustfmt_nightly_1, r"\s;");
+
+// rustache-0.1.0: r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)"
+consistent!(rustache_0, r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)");
+
+// rustfilt-0.2.0: r"_ZN[\$\._[:alnum:]]*"
+consistent!(rustfilt_0, r"_ZN[\$\._[:alnum:]]*");
+
+// rustache-lists-0.1.2: r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)"
+consistent!(rustache_lists_0, r"(?s)(.*?)([ \t\r\n]*)(\{\{(\{?\S?\s*?[\w\.\s]*.*?\s*?\}?)\}\})([ \t\r\n]*)");
+
+// rural-0.7.3: "(.+)=(.+)"
+consistent!(rural_0, "(.+)=(.+)");
+
+// rural-0.7.3: "(.*):(.+)"
+consistent!(rural_1, "(.*):(.+)");
+
+// rural-0.7.3: "(.+):=(.+)"
+consistent!(rural_2, "(.+):=(.+)");
+
+// rural-0.7.3: "(.*)==(.+)"
+consistent!(rural_3, "(.*)==(.+)");
+
+// rusoto_credential-0.11.0: r"^\[([^\]]+)\]$"
+consistent!(rusoto_credential_0, r"^\[([^\]]+)\]$");
+
+// rumblebars-0.3.0: "([:blank:]*)$"
+consistent!(rumblebars_0, "([:blank:]*)$");
+
+// rumblebars-0.3.0: "(\r?\n)[:blank:]*(\\{\\{~?[#!/](?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
+consistent!(rumblebars_1, "(\r?\n)[:blank:]*(\\{\\{~?[#!/](?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z");
+
+// rumblebars-0.3.0: "(\r?\n[:blank:]*)(\\{\\{~?>(?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z"
+consistent!(rumblebars_2, "(\r?\n[:blank:]*)(\\{\\{~?>(?:\\}?[^}])*\\}\\})[:blank:]*(:?\r?\n)?\\z");
+
+// rumblebars-0.3.0: "((?:[:blank:]|\r?\n)*)(\r?\n)[:blank:]*$"
+consistent!(rumblebars_3, "((?:[:blank:]|\r?\n)*)(\r?\n)[:blank:]*$");
+
+// rumblebars-0.3.0: "^([:blank:]*\r?\n)(.*)"
+consistent!(rumblebars_4, "^([:blank:]*\r?\n)(.*)");
+
+// diesel_cli-1.3.1: r"(?P<stamp>[\d-]*)_hello"
+consistent!(diesel_cli_0, r"(?P<stamp>[\d-]*)_hello");
+
+// dishub-0.1.1: r"(\d+)s"
+consistent!(dishub_0, r"(\d+)s");
+
+// spreadsheet_textconv-0.1.0: r"\n"
+consistent!(spreadsheet_textconv_0, r"\n");
+
+// spreadsheet_textconv-0.1.0: r"\r"
+consistent!(spreadsheet_textconv_1, r"\r");
+
+// spreadsheet_textconv-0.1.0: r"\t"
+consistent!(spreadsheet_textconv_2, r"\t");
+
+// split_aud-0.1.0: r"DELAY (-?\d+)ms"
+consistent!(split_aud_0, r"DELAY (-?\d+)ms");
+
+// split_aud-0.1.0: r"Trim\((\d+), ?(\d+)\)"
+consistent!(split_aud_1, r"Trim\((\d+), ?(\d+)\)");
+
+// spotrust-0.0.5: r"spotify:[a-z]+:[a-zA-Z0-9]+"
+consistent!(spotrust_0, r"spotify:[a-z]+:[a-zA-Z0-9]+");
+
+// spaceslugs-0.1.0: r"[^\x00-\x7F]"
+consistent!(spaceslugs_0, r"[^\x00-\x7F]");
+
+// spaceslugs-0.1.0: r"[']+"
+consistent!(spaceslugs_1, r"[']+");
+
+// spaceslugs-0.1.0: r"\W+"
+consistent!(spaceslugs_2, r"\W+");
+
+// spaceslugs-0.1.0: r"[ ]+"
+consistent!(spaceslugs_3, r"[ ]+");
+
+// space_email_api-0.1.1: "PHPSESSID=([0-9a-f]+)"
+consistent!(space_email_api_0, "PHPSESSID=([0-9a-f]+)");
+
+// lorikeet-0.7.0: "[^0-9.,]"
+consistent!(lorikeet_0, "[^0-9.,]");
+
+// claude-0.3.0: r"^(?:\b|(-)?)(\p{Currency_Symbol})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b$"
+consistent!(claude_0, r"^(?:\b|(-)?)(\p{Currency_Symbol})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b$");
+
+// clam-0.1.6: r"<%=\s*(.+?)\s*%>"
+consistent!(clam_0, r"<%=\s*(.+?)\s*%>");
+
+// classifier-0.0.3: r"(\s)"
+consistent!(classifier_0, r"(\s)");
+
+// click-0.3.2: r"(-----BEGIN .*-----\n)((?:(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)*\n)+)(-----END .*-----)"
+consistent!(click_0, r"(-----BEGIN .*-----\n)((?:(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)*\n)+)(-----END .*-----)");
+
+// click-0.3.2: r"-----BEGIN PRIVATE KEY-----"
+consistent!(click_1, r"-----BEGIN PRIVATE KEY-----");
+
+// ultrastar-txt-0.1.2: r"#([A-Z3a-z]*):(.*)"
+consistent!(ultrastar_txt_0, r"#([A-Z3a-z]*):(.*)");
+
+// ultrastar-txt-0.1.2: "^-\\s?(-?[0-9]+)\\s*$"
+consistent!(ultrastar_txt_1, "^-\\s?(-?[0-9]+)\\s*$");
+
+// ultrastar-txt-0.1.2: "^-\\s?(-?[0-9]+)\\s+(-?[0-9]+)"
+consistent!(ultrastar_txt_2, "^-\\s?(-?[0-9]+)\\s+(-?[0-9]+)");
+
+// ultrastar-txt-0.1.2: "^(.)\\s*(-?[0-9]+)\\s+(-?[0-9]+)\\s+(-?[0-9]+)\\s?(.*)"
+consistent!(ultrastar_txt_3, "^(.)\\s*(-?[0-9]+)\\s+(-?[0-9]+)\\s+(-?[0-9]+)\\s?(.*)");
+
+// ultrastar-txt-0.1.2: "^P\\s?(-?[0-9]+)"
+consistent!(ultrastar_txt_4, "^P\\s?(-?[0-9]+)");
+
+// db-accelerate-2.0.0: r"^template\.add($|\..+$)"
+consistent!(db_accelerate_0, r"^template\.add($|\..+$)");
+
+// db-accelerate-2.0.0: r"^template\.sub($|\..+$)"
+consistent!(db_accelerate_1, r"^template\.sub($|\..+$)");
+
+// sterling-0.3.0: r"(\d+)([cegps])"
+consistent!(sterling_0, r"(\d+)([cegps])");
+
+// stache-0.2.0: r"[^\w]"
+consistent!(stache_0, r"[^\w]");
+
+// strukt-0.1.0: "\"([<>]?)([xcbB\\?hHiIlLqQfdspP]*)\""
+consistent!(strukt_0, "\"([<>]?)([xcbB\\?hHiIlLqQfdspP]*)\"");
+
+// steamid-ng-0.3.1: r"^STEAM_([0-4]):([0-1]):([0-9]{1,10})$"
+consistent!(steamid_ng_0, r"^STEAM_([0-4]):([0-1]):([0-9]{1,10})$");
+
+// steamid-ng-0.3.1: r"^\[([AGMPCgcLTIUai]):([0-4]):([0-9]{1,10})(:([0-9]+))?\]$"
+consistent!(steamid_ng_1, r"^\[([AGMPCgcLTIUai]):([0-4]):([0-9]{1,10})(:([0-9]+))?\]$");
+
+// strscan-0.1.1: r"^\w+"
+consistent!(strscan_0, r"^\w+");
+
+// strscan-0.1.1: r"^\s+"
+consistent!(strscan_1, r"^\s+");
+
+// strscan-0.1.1: r"^\w+"
+consistent!(strscan_2, r"^\w+");
+
+// strscan-0.1.1: r"^\s+"
+consistent!(strscan_3, r"^\s+");
+
+// strscan-0.1.1: r"^(\w+)\s+"
+consistent!(strscan_4, r"^(\w+)\s+");
+
+// tk-carbon-0.2.0: r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$"
+consistent!(tk_carbon_0, r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$");
+
+// tk-carbon-0.2.0: r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$"
+consistent!(tk_carbon_1, r"^([a-zA-Z0-9\.-]+)(?:\s+(\d+))$");
+
+// evalrs-0.0.10: r"extern\s+crate\s+([a-z0-9_]+)\s*;(\s*//(.+))?"
+consistent!(evalrs_0, r"extern\s+crate\s+([a-z0-9_]+)\s*;(\s*//(.+))?");
+
+// evalrs-0.0.10: r"(?m)^# "
+consistent!(evalrs_1, r"(?m)^# ");
+
+// evalrs-0.0.10: r"(?m)^\s*fn +main *\( *\)"
+consistent!(evalrs_2, r"(?m)^\s*fn +main *\( *\)");
+
+// evalrs-0.0.10: r"(extern\s+crate\s+[a-z0-9_]+\s*;)"
+consistent!(evalrs_3, r"(extern\s+crate\s+[a-z0-9_]+\s*;)");
+
+// gate_build-0.5.0: "(.*)_t([0-9]+)"
+consistent!(gate_build_0, "(.*)_t([0-9]+)");
+
+// rake-0.1.1: r"[^\P{P}-]|\s+-\s+"
+consistent!(rake_0, r"[^\P{P}-]|\s+-\s+");
+
+// rafy-0.2.1: r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*"
+consistent!(rafy_0, r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*");
+
+// raven-0.2.1: r"^(?P<protocol>.*?)://(?P<public_key>.*?):(?P<secret_key>.*?)@(?P<host>.*?)/(?P<path>.*/)?(?P<project_id>.*)$"
+consistent!(raven_0, r"^(?P<protocol>.*?)://(?P<public_key>.*?):(?P<secret_key>.*?)@(?P<host>.*?)/(?P<path>.*/)?(?P<project_id>.*)$");
+
+// rargs-0.2.0: r"\{[[:space:]]*[^{}]*[[:space:]]*\}"
+consistent!(rargs_0, r"\{[[:space:]]*[^{}]*[[:space:]]*\}");
+
+// rargs-0.2.0: r"^\{[[:space:]]*(?P<name>[[:word:]]*)[[:space:]]*\}$"
+consistent!(rargs_1, r"^\{[[:space:]]*(?P<name>[[:word:]]*)[[:space:]]*\}$");
+
+// rargs-0.2.0: r"^\{[[:space:]]*(?P<num>-?\d+)[[:space:]]*\}$"
+consistent!(rargs_2, r"^\{[[:space:]]*(?P<num>-?\d+)[[:space:]]*\}$");
+
+// rargs-0.2.0: r"^\{(?P<left>-?\d*)?\.\.(?P<right>-?\d*)?(?::(?P<sep>.*))?\}$"
+consistent!(rargs_3, r"^\{(?P<left>-?\d*)?\.\.(?P<right>-?\d*)?(?::(?P<sep>.*))?\}$");
+
+// rargs-0.2.0: r"(.*?)[[:space:]]+|(.*?)$"
+consistent!(rargs_4, r"(.*?)[[:space:]]+|(.*?)$");
+
+// indradb-lib-0.15.0: r"[a-zA-Z0-9]{8}"
+consistent!(indradb_lib_0, r"[a-zA-Z0-9]{8}");
+
+// fungi-lang-0.1.50: r"::"
+consistent!(fungi_lang_0, r"::");
+
+// nickel-0.10.1: "/hello/(?P<name>[a-zA-Z]+)"
+consistent!(nickel_0, "/hello/(?P<name>[a-zA-Z]+)");
+
+// nickel-0.10.1: "/hello/(?P<name>[a-zA-Z]+)"
+consistent!(nickel_1, "/hello/(?P<name>[a-zA-Z]+)");
+
+// pact_verifier-0.4.0: r"\{(\w+)\}"
+consistent!(pact_verifier_0, r"\{(\w+)\}");
+
+// pact_matching-0.4.1: "application/.*json"
+consistent!(pact_matching_0, "application/.*json");
+
+// pact_matching-0.4.1: "application/json.*"
+consistent!(pact_matching_1, "application/json.*");
+
+// pact_matching-0.4.1: "application/.*xml"
+consistent!(pact_matching_2, "application/.*xml");
+
+// pangu-0.2.0: "([\"'\\(\\[\\{{<\u{201c}])(\\s*)(.+?)(\\s*)([\"'\\)\\]\\}}>\u{201d}])"
+consistent!(pangu_0, "([\"'\\(\\[\\{{<\u{201c}])(\\s*)(.+?)(\\s*)([\"'\\)\\]\\}}>\u{201d}])");
+
+// pangu-0.2.0: "([\\(\\[\\{{<\u{201c}]+)(\\s*)(.+?)(\\s*)([\\)\\]\\}}>\u{201d}]+)"
+consistent!(pangu_1, "([\\(\\[\\{{<\u{201c}]+)(\\s*)(.+?)(\\s*)([\\)\\]\\}}>\u{201d}]+)");
+
+// parser-haskell-0.2.0: r"\{-[\s\S]*?-\}"
+consistent!(parser_haskell_0, r"\{-[\s\S]*?-\}");
+
+// parser-haskell-0.2.0: r"(?m);+\s*$"
+consistent!(parser_haskell_1, r"(?m);+\s*$");
+
+// parser-haskell-0.2.0: r"(?m)^#(if|ifn?def|endif|else|include|elif).*"
+consistent!(parser_haskell_2, r"(?m)^#(if|ifn?def|endif|else|include|elif).*");
+
+// parser-haskell-0.2.0: r"'([^'\\]|\\[A-Z]{1,3}|\\.)'"
+consistent!(parser_haskell_3, r"'([^'\\]|\\[A-Z]{1,3}|\\.)'");
+
+// parser-haskell-0.2.0: r"forall\s+(.*?)\."
+consistent!(parser_haskell_4, r"forall\s+(.*?)\.");
+
+// html2md-0.2.1: "\\s{2,}"
+consistent!(html2md_0, "\\s{2,}");
+
+// html2md-0.2.1: "\\n{2,}"
+consistent!(html2md_1, "\\n{2,}");
+
+// html2md-0.2.1: "(?m)(\\S) $"
+consistent!(html2md_2, "(?m)(\\S) $");
+
+// html2md-0.2.1: "(?m)^[-*] "
+consistent!(html2md_3, "(?m)^[-*] ");
+
+// ovpnfile-0.1.2: r"#.*$"
+consistent!(ovpnfile_0, r"#.*$");
+
+// ovpnfile-0.1.2: r"^<(\S+)>"
+consistent!(ovpnfile_1, r"^<(\S+)>");
+
+// ovpnfile-0.1.2: r"^</(\S+)>"
+consistent!(ovpnfile_2, r"^</(\S+)>");
+
+// screenruster-saver-fractal-0.1.1: r"#([:xdigit:]{2})([:xdigit:]{2})([:xdigit:]{2})"
+consistent!(screenruster_saver_fractal_0, r"#([:xdigit:]{2})([:xdigit:]{2})([:xdigit:]{2})");
+
+// scarlet-0.2.2: r"rgb\((?: *(\d{1,3}),)(?: *(\d{1,3}),)(?: *(\d{1,3}))\)"
+consistent!(scarlet_0, r"rgb\((?: *(\d{1,3}),)(?: *(\d{1,3}),)(?: *(\d{1,3}))\)");
+
+// cpp_to_rust_generator-0.2.0: r"^([\w:]+)<(.+)>$"
+consistent!(cpp_to_rust_generator_0, r"^([\w:]+)<(.+)>$");
+
+// cpp_to_rust_generator-0.2.0: r"^type-parameter-(\d+)-(\d+)$"
+consistent!(cpp_to_rust_generator_1, r"^type-parameter-(\d+)-(\d+)$");
+
+// cpp_to_rust_generator-0.2.0: r"^([\w~]+)<[^<>]+>$"
+consistent!(cpp_to_rust_generator_2, r"^([\w~]+)<[^<>]+>$");
+
+// cpp_to_rust_generator-0.2.0: r"(signals|Q_SIGNALS)\s*:"
+consistent!(cpp_to_rust_generator_3, r"(signals|Q_SIGNALS)\s*:");
+
+// cpp_to_rust_generator-0.2.0: r"(slots|Q_SLOTS)\s*:"
+consistent!(cpp_to_rust_generator_4, r"(slots|Q_SLOTS)\s*:");
+
+// cpp_to_rust_generator-0.2.0: r"(public|protected|private)\s*:"
+consistent!(cpp_to_rust_generator_5, r"(public|protected|private)\s*:");
+
+// cpp_to_rust-0.5.3: r"^([\w:]+)<(.+)>$"
+consistent!(cpp_to_rust_0, r"^([\w:]+)<(.+)>$");
+
+// cpp_to_rust-0.5.3: r"^type-parameter-(\d+)-(\d+)$"
+consistent!(cpp_to_rust_1, r"^type-parameter-(\d+)-(\d+)$");
+
+// cpp_to_rust-0.5.3: r"^([\w~]+)<[^<>]+>$"
+consistent!(cpp_to_rust_2, r"^([\w~]+)<[^<>]+>$");
+
+// cpp_to_rust-0.5.3: r"(signals|Q_SIGNALS)\s*:"
+consistent!(cpp_to_rust_3, r"(signals|Q_SIGNALS)\s*:");
+
+// cpp_to_rust-0.5.3: r"(slots|Q_SLOTS)\s*:"
+consistent!(cpp_to_rust_4, r"(slots|Q_SLOTS)\s*:");
+
+// cpp_to_rust-0.5.3: r"(public|protected|private)\s*:"
+consistent!(cpp_to_rust_5, r"(public|protected|private)\s*:");
+
+// fritzbox_logs-0.2.0: "(\\d{2}\\.\\d{2}\\.\\d{2}) (\\d{2}:\\d{2}:\\d{2}) (.*)"
+consistent!(fritzbox_logs_0, "(\\d{2}\\.\\d{2}\\.\\d{2}) (\\d{2}:\\d{2}:\\d{2}) (.*)");
+
+// fractal-matrix-api-3.29.0: r"mxc://(?P<server>[^/]+)/(?P<media>.+)"
+consistent!(fractal_matrix_api_0, r"mxc://(?P<server>[^/]+)/(?P<media>.+)");
+
+// smtp2go-0.1.4: r"^api-[a-zA-Z0-9]{32}$"
+consistent!(smtp2go_0, r"^api-[a-zA-Z0-9]{32}$");
+
+// pusher-0.3.1: r"^[-a-zA-Z0-9_=@,.;]+$"
+consistent!(pusher_0, r"^[-a-zA-Z0-9_=@,.;]+$");
+
+// pusher-0.3.1: r"\A\d+\.\d+\z"
+consistent!(pusher_1, r"\A\d+\.\d+\z");
+
+// bakervm-0.9.0: r"^\.(.+?) +?(.+)$"
+consistent!(bakervm_0, r"^\.(.+?) +?(.+)$");
+
+// bakervm-0.9.0: r"^\.([^\s]+)$"
+consistent!(bakervm_1, r"^\.([^\s]+)$");
+
+// bakervm-0.9.0: r"^include! +([^\s]+)$"
+consistent!(bakervm_2, r"^include! +([^\s]+)$");
+
+// bakervm-0.9.0: r"^@(\d+)$"
+consistent!(bakervm_3, r"^@(\d+)$");
+
+// bakervm-0.9.0: r"^true|false$"
+consistent!(bakervm_4, r"^true|false$");
+
+// bakervm-0.9.0: r"^(-?\d+)?\.[0-9]+$"
+consistent!(bakervm_5, r"^(-?\d+)?\.[0-9]+$");
+
+// bakervm-0.9.0: r"^(-?\d+)?$"
+consistent!(bakervm_6, r"^(-?\d+)?$");
+
+// bakervm-0.9.0: r"^#([0-9abcdefABCDEF]{6})$"
+consistent!(bakervm_7, r"^#([0-9abcdefABCDEF]{6})$");
+
+// bakervm-0.9.0: r"^'(.)'$"
+consistent!(bakervm_8, r"^'(.)'$");
+
+// bakervm-0.9.0: r"^\$vi\((\d+)\)$"
+consistent!(bakervm_9, r"^\$vi\((\d+)\)$");
+
+// bakervm-0.9.0: r"^\$key\((\d+)\)$"
+consistent!(bakervm_10, r"^\$key\((\d+)\)$");
+
+// banana-0.0.2: "(?P<type>[A-Z^']+) (?P<route>[^']+) HTTP/(?P<http>[^']+)"
+consistent!(banana_0, "(?P<type>[A-Z^']+) (?P<route>[^']+) HTTP/(?P<http>[^']+)");
+
+// serial-key-2.0.0: r"[A-F0-9]{8}"
+consistent!(serial_key_0, r"[A-F0-9]{8}");
+
+// serde-hjson-0.8.1: "[\\\\\"\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
+consistent!(serde_hjson_0, "[\\\\\"\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
+
+// serde-hjson-0.8.1: "[\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
+consistent!(serde_hjson_1, "[\x00-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
+
+// serde-hjson-0.8.1: "'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]"
+consistent!(serde_hjson_2, "'''|[\x00-\x09\x0b\x0c\x0e-\x1f\x7f-\u{9f}\u{00ad}\u{0600}-\u{0604}\u{070f}\u{17b4}\u{17b5}\u{200c}-\u{200f}\u{2028}-\u{202f}\u{2060}-\u{206f}\u{feff}\u{fff0}-\u{ffff}]");
+
+// serde-odbc-0.1.0: r"/todos/(?P<id>\d+)"
+consistent!(serde_odbc_0, r"/todos/(?P<id>\d+)");
+
+// sentry-0.6.0: r"^(?:_<)?([a-zA-Z0-9_]+?)(?:\.\.|::)"
+consistent!(sentry_0, r"^(?:_<)?([a-zA-Z0-9_]+?)(?:\.\.|::)");
+
+// sentiment-0.1.1: r"[^a-zA-Z0 -]+"
+consistent!(sentiment_0, r"[^a-zA-Z0 -]+");
+
+// sentiment-0.1.1: r" {2,}"
+consistent!(sentiment_1, r" {2,}");
+
+// verilog-0.0.1: r"(?m)//.*"
+consistent!(verilog_0, r"(?m)//.*");
+
+// verex-0.2.2: "(?P<robot>C3PO)"
+consistent!(verex_0, "(?P<robot>C3PO)");
+
+// handlebars-0.32.4: ">|<|\"|&"
+consistent!(handlebars_0, ">|<|\"|&");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789]{4}$"
+consistent!(haikunator_0, r"^\w+-\w+-[0123456789]{4}$");
+
+// haikunator-0.1.2: r"^\w+@\w+@[0123456789]{4}$"
+consistent!(haikunator_1, r"^\w+@\w+@[0123456789]{4}$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789abcdef]{4}$"
+consistent!(haikunator_2, r"^\w+-\w+-[0123456789abcdef]{4}$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789忠犬ハチ公]{10}$"
+consistent!(haikunator_3, r"^\w+-\w+-[0123456789忠犬ハチ公]{10}$");
+
+// haikunator-0.1.2: r"^\w+-\w+$"
+consistent!(haikunator_4, r"^\w+-\w+$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[foo]{4}$"
+consistent!(haikunator_5, r"^\w+-\w+-[foo]{4}$");
+
+// haikunator-0.1.2: r"^\w+-\w+-[0123456789忠犬ハチ公]{5}$"
+consistent!(haikunator_6, r"^\w+-\w+-[0123456789忠犬ハチ公]{5}$");
+
+// bobbin-cli-0.8.3: r"(.*)"
+consistent!(bobbin_cli_0, r"(.*)");
+
+// bobbin-cli-0.8.3: r"rustc (.*)"
+consistent!(bobbin_cli_1, r"rustc (.*)");
+
+// bobbin-cli-0.8.3: r"cargo (.*)"
+consistent!(bobbin_cli_2, r"cargo (.*)");
+
+// bobbin-cli-0.8.3: r"xargo (.*)\n"
+consistent!(bobbin_cli_3, r"xargo (.*)\n");
+
+// bobbin-cli-0.8.3: r"Open On-Chip Debugger (.*)"
+consistent!(bobbin_cli_4, r"Open On-Chip Debugger (.*)");
+
+// bobbin-cli-0.8.3: r"arm-none-eabi-gcc \(GNU Tools for ARM Embedded Processors[^\)]*\) (.*)"
+consistent!(bobbin_cli_5, r"arm-none-eabi-gcc \(GNU Tools for ARM Embedded Processors[^\)]*\) (.*)");
+
+// bobbin-cli-0.8.3: r"(?m).*\nBasic Open Source SAM-BA Application \(BOSSA\) Version (.*)\n"
+consistent!(bobbin_cli_6, r"(?m).*\nBasic Open Source SAM-BA Application \(BOSSA\) Version (.*)\n");
+
+// bobbin-cli-0.8.3: r"(?m)SEGGER J-Link Commander (.*)\n"
+consistent!(bobbin_cli_7, r"(?m)SEGGER J-Link Commander (.*)\n");
+
+// bobbin-cli-0.8.3: r"(?m)Teensy Loader, Command Line, Version (.*)\n"
+consistent!(bobbin_cli_8, r"(?m)Teensy Loader, Command Line, Version (.*)\n");
+
+// bobbin-cli-0.8.3: r"dfu-util (.*)\n"
+consistent!(bobbin_cli_9, r"dfu-util (.*)\n");
+
+// borsholder-0.9.1: r"^/static/[\w.]+$"
+consistent!(borsholder_0, r"^/static/[\w.]+$");
+
+// borsholder-0.9.1: r"^/timeline/([0-9]+)$"
+consistent!(borsholder_1, r"^/timeline/([0-9]+)$");
+
+// fblog-1.0.1: "\u{001B}\\[[\\d;]*[^\\d;]"
+consistent!(fblog_0, "\u{001B}\\[[\\d;]*[^\\d;]");
+
+// fblog-1.0.1: "\u{001B}\\[[\\d;]*[^\\d;]"
+consistent!(fblog_1, "\u{001B}\\[[\\d;]*[^\\d;]");
+
+// toml-query-0.6.0: r"^\[\d+\]$"
+consistent!(toml_query_0, r"^\[\d+\]$");
+
+// todo-txt-1.1.0: r" (?P<key>[^\s]+):(?P<value>[^\s^/]+)"
+consistent!(todo_txt_0, r" (?P<key>[^\s]+):(?P<value>[^\s^/]+)");
+
+// findr-0.1.5: r"\band\b"
+consistent!(findr_0, r"\band\b");
+
+// findr-0.1.5: r"\bor\b"
+consistent!(findr_1, r"\bor\b");
+
+// findr-0.1.5: r"\bnot\b"
+consistent!(findr_2, r"\bnot\b");
+
+// file-sniffer-3.0.1: r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(file_sniffer_0, r".*?\.(a|la|lo|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// file-sniffer-3.0.1: r".*?\.(stats|conf|h|cache.*|dat|pc|info)$"
+consistent!(file_sniffer_1, r".*?\.(stats|conf|h|cache.*|dat|pc|info)$");
+
+// file-sniffer-3.0.1: r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$"
+consistent!(file_sniffer_2, r".*?\.(exe|a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|p_hi|p_o|prof|tix)$");
+
+// file-sniffer-3.0.1: r".*?\.(stats|conf|h|cache.*)$"
+consistent!(file_sniffer_3, r".*?\.(stats|conf|h|cache.*)$");
+
+// file-sniffer-3.0.1: r"(\.git|\.pijul|_darcs|\.hg)$"
+consistent!(file_sniffer_4, r"(\.git|\.pijul|_darcs|\.hg)$");
+
+// file_logger-0.1.0: "test"
+consistent!(file_logger_0, "test");
+
+// file_scanner-0.2.0: r"foo"
+consistent!(file_scanner_0, r"foo");
+
+// file_scanner-0.2.0: r"a+b"
+consistent!(file_scanner_1, r"a+b");
+
+// file_scanner-0.2.0: r"a[ab]*b"
+consistent!(file_scanner_2, r"a[ab]*b");
+
+// file_scanner-0.2.0: r"\s+"
+consistent!(file_scanner_3, r"\s+");
+
+// file_scanner-0.2.0: r"\s+"
+consistent!(file_scanner_4, r"\s+");
+
+// cellsplit-0.2.1: r"^\s*([^\s]+) %cellsplit<\d+>$"
+consistent!(cellsplit_0, r"^\s*([^\s]+) %cellsplit<\d+>$");
+
+// cellsplit-0.2.1: r"^\s*([^\s]+) %cellsplit<\d+>$"
+consistent!(cellsplit_1, r"^\s*([^\s]+) %cellsplit<\d+>$");
+
+// aterm-0.20.0: r"^[+\-]?[0-9]+"
+consistent!(aterm_0, r"^[+\-]?[0-9]+");
+
+// aterm-0.20.0: r"^[+\-]?[0-9]+\.[0-9]*([eE][+\-]?[0-9]+)?"
+consistent!(aterm_1, r"^[+\-]?[0-9]+\.[0-9]*([eE][+\-]?[0-9]+)?");
+
+// atarashii_imap-0.3.0: r"^[*] OK"
+consistent!(atarashii_imap_0, r"^[*] OK");
+
+// atarashii_imap-0.3.0: r"FLAGS\s\((.+)\)"
+consistent!(atarashii_imap_1, r"FLAGS\s\((.+)\)");
+
+// atarashii_imap-0.3.0: r"\[PERMANENTFLAGS\s\((.+)\)\]"
+consistent!(atarashii_imap_2, r"\[PERMANENTFLAGS\s\((.+)\)\]");
+
+// atarashii_imap-0.3.0: r"\[UIDVALIDITY\s(\d+)\]"
+consistent!(atarashii_imap_3, r"\[UIDVALIDITY\s(\d+)\]");
+
+// atarashii_imap-0.3.0: r"(\d+)\sEXISTS"
+consistent!(atarashii_imap_4, r"(\d+)\sEXISTS");
+
+// atarashii_imap-0.3.0: r"(\d+)\sRECENT"
+consistent!(atarashii_imap_5, r"(\d+)\sRECENT");
+
+// atarashii_imap-0.3.0: r"\[UNSEEN\s(\d+)\]"
+consistent!(atarashii_imap_6, r"\[UNSEEN\s(\d+)\]");
+
+// atarashii_imap-0.3.0: r"\[UIDNEXT\s(\d+)\]"
+consistent!(atarashii_imap_7, r"\[UIDNEXT\s(\d+)\]");
+
+// editorconfig-1.0.0: r"\\(\{|\})"
+consistent!(editorconfig_0, r"\\(\{|\})");
+
+// editorconfig-1.0.0: r"(^|[^\\])\\\|"
+consistent!(editorconfig_1, r"(^|[^\\])\\\|");
+
+// editorconfig-1.0.0: r"\[([^\]]*)$"
+consistent!(editorconfig_2, r"\[([^\]]*)$");
+
+// editorconfig-1.0.0: r"\[(.*/.*)\]"
+consistent!(editorconfig_3, r"\[(.*/.*)\]");
+
+// editorconfig-1.0.0: r"\{(-?\d+\\\.\\\.-?\d+)\}"
+consistent!(editorconfig_4, r"\{(-?\d+\\\.\\\.-?\d+)\}");
+
+// editorconfig-1.0.0: r"\{([^,]+)\}"
+consistent!(editorconfig_5, r"\{([^,]+)\}");
+
+// editorconfig-1.0.0: r"\{(([^\}].*)?(,|\|)(.*[^\\])?)\}"
+consistent!(editorconfig_6, r"\{(([^\}].*)?(,|\|)(.*[^\\])?)\}");
+
+// editorconfig-1.0.0: r"^/"
+consistent!(editorconfig_7, r"^/");
+
+// editorconfig-1.0.0: r"(^|[^\\])(\{|\})"
+consistent!(editorconfig_8, r"(^|[^\\])(\{|\})");
+
+// edmunge-1.0.0: "^#!.*\n"
+consistent!(edmunge_0, "^#!.*\n");
+
+// unicode_names2_macros-0.2.0: r"\\N\{(.*?)(?:\}|$)"
+consistent!(unicode_names2_macros_0, r"\\N\{(.*?)(?:\}|$)");
+
+// unidiff-0.2.1: r"^--- (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
+consistent!(unidiff_0, r"^--- (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?");
+
+// unidiff-0.2.1: r"^\+\+\+ (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?"
+consistent!(unidiff_1, r"^\+\+\+ (?P<filename>[^\t\n]+)(?:\t(?P<timestamp>[^\n]+))?");
+
+// unidiff-0.2.1: r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)"
+consistent!(unidiff_2, r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)");
+
+// unidiff-0.2.1: r"^(?P<line_type>[- \n\+\\]?)(?P<value>.*)"
+consistent!(unidiff_3, r"^(?P<line_type>[- \n\+\\]?)(?P<value>.*)");
+
+// slippy-map-tiles-0.13.1: "/?(?P<zoom>[0-9]?[0-9])/(?P<x>[0-9]{1,10})/(?P<y>[0-9]{1,10})(\\.[a-zA-Z]{3,4})?$"
+consistent!(slippy_map_tiles_0, "/?(?P<zoom>[0-9]?[0-9])/(?P<x>[0-9]{1,10})/(?P<y>[0-9]{1,10})(\\.[a-zA-Z]{3,4})?$");
+
+// slippy-map-tiles-0.13.1: r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$"
+consistent!(slippy_map_tiles_1, r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?) (?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$");
+
+// slippy-map-tiles-0.13.1: r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$"
+consistent!(slippy_map_tiles_2, r"^(?P<minlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<minlat>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlon>-?[0-9]{1,3}(\.[0-9]{1,10})?),(?P<maxlat>-?[0-9]{1,3}(\.[0-9]{1,10})?)$");
+
+// sonos-0.1.2: r"^https?://(.+?):1400/xml"
+consistent!(sonos_0, r"^https?://(.+?):1400/xml");
+
+// validator_derive-0.7.0: r"^[a-z]{2}$"
+consistent!(validator_derive_0, r"^[a-z]{2}$");
+
+// validator_derive-0.7.0: r"[a-z]{2}"
+consistent!(validator_derive_1, r"[a-z]{2}");
+
+// validator_derive-0.7.0: r"[a-z]{2}"
+consistent!(validator_derive_2, r"[a-z]{2}");
+
+// nginx-config-0.8.0: r"one of \d+ options"
+consistent!(nginx_config_0, r"one of \d+ options");
+
+// waltz-0.4.0: r"[\s,]"
+consistent!(waltz_0, r"[\s,]");
+
+// warheadhateus-0.2.1: r"^aws_access_key_id = (.*)"
+consistent!(warheadhateus_0, r"^aws_access_key_id = (.*)");
+
+// warheadhateus-0.2.1: r"^aws_secret_access_key = (.*)"
+consistent!(warheadhateus_1, r"^aws_secret_access_key = (.*)");
+
+// warheadhateus-0.2.1: r"^aws_access_key_id = (.*)"
+consistent!(warheadhateus_2, r"^aws_access_key_id = (.*)");
+
+// warheadhateus-0.2.1: r"^aws_secret_access_key = (.*)"
+consistent!(warheadhateus_3, r"^aws_secret_access_key = (.*)");
+
+// jieba-rs-0.2.2: r"([\u{4E00}-\u{9FD5}a-zA-Z0-9+#&\._%]+)"
+consistent!(jieba_rs_0, r"([\u{4E00}-\u{9FD5}a-zA-Z0-9+#&\._%]+)");
+
+// jieba-rs-0.2.2: r"(\r\n|\s)"
+consistent!(jieba_rs_1, r"(\r\n|\s)");
+
+// jieba-rs-0.2.2: "([\u{4E00}-\u{9FD5}]+)"
+consistent!(jieba_rs_2, "([\u{4E00}-\u{9FD5}]+)");
+
+// jieba-rs-0.2.2: r"[^a-zA-Z0-9+#\n]"
+consistent!(jieba_rs_3, r"[^a-zA-Z0-9+#\n]");
+
+// jieba-rs-0.2.2: r"([\u{4E00}-\u{9FD5}]+)"
+consistent!(jieba_rs_4, r"([\u{4E00}-\u{9FD5}]+)");
+
+// jieba-rs-0.2.2: r"([a-zA-Z0-9]+(?:.\d+)?%?)"
+consistent!(jieba_rs_5, r"([a-zA-Z0-9]+(?:.\d+)?%?)");
+
+// lalrpop-0.15.2: r"Span\([0-9 ,]*\)"
+consistent!(lalrpop_0, r"Span\([0-9 ,]*\)");
+
+// lalrpop-snap-0.15.2: r"Span\([0-9 ,]*\)"
+consistent!(lalrpop_snap_0, r"Span\([0-9 ,]*\)");
+
+// nlp-tokenize-0.1.0: r"[\S]+"
+consistent!(nlp_tokenize_0, r"[\S]+");
+
+// kbgpg-0.1.2: "[[:xdigit:]][70]"
+consistent!(kbgpg_0, "[[:xdigit:]][70]");
+
+// cdbd-0.1.1: r"^((?P<address>.*):)?(?P<port>\d+)$"
+consistent!(cdbd_0, r"^((?P<address>.*):)?(?P<port>\d+)$");
+
+// mbutiles-0.1.1: r"[\w\s=+-/]+\((\{(.|\n)*\})\);?"
+consistent!(mbutiles_0, r"[\w\s=+-/]+\((\{(.|\n)*\})\);?");
+
+// extrahop-0.2.5: r"^-\d+(?:ms|s|m|h|d|w|y)?$"
+consistent!(extrahop_0, r"^-\d+(?:ms|s|m|h|d|w|y)?$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$"
+consistent!(pippin_0, "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
+consistent!(pippin_1, "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$"
+consistent!(pippin_2, "^((?:.*)-)?ss(0|[1-9][0-9]*)\\.pip$");
+
+// pippin-0.1.0: "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$"
+consistent!(pippin_3, "^((?:.*)-)?ss(0|[1-9][0-9]*)-cl(0|[1-9][0-9]*)\\.piplog$");
+
+// pippin-0.1.0: "^.*pn(0|[1-9][0-9]*)(-ss(0|[1-9][0-9]*)(\\.pip|-cl(0|[1-9][0-9]*)\\.piplog))?$"
+consistent!(pippin_4, "^.*pn(0|[1-9][0-9]*)(-ss(0|[1-9][0-9]*)(\\.pip|-cl(0|[1-9][0-9]*)\\.piplog))?$");
+
+// pippin-0.1.0: "^(.*)-ss(?:0|[1-9][0-9]*)(?:\\.pip|-cl(?:0|[1-9][0-9]*)\\.piplog)$"
+consistent!(pippin_5, "^(.*)-ss(?:0|[1-9][0-9]*)(?:\\.pip|-cl(?:0|[1-9][0-9]*)\\.piplog)$");
+
+// pinyin-0.3.0: r"(?i)[āáǎàēéěèōóǒòīíǐìūúǔùüǘǚǜńň]"
+consistent!(pinyin_0, r"(?i)[āáǎàēéěèōóǒòīíǐìūúǔùüǘǚǜńň]");
+
+// pinyin-0.3.0: r"([aeoiuvnm])([0-4])$"
+consistent!(pinyin_1, r"([aeoiuvnm])([0-4])$");
+
+// duration-parser-0.2.0: r"(?P<value>\d+)(?P<units>[a-z])"
+consistent!(duration_parser_0, r"(?P<value>\d+)(?P<units>[a-z])");
+
+// dutree-0.2.7: r"^\d+\D?$"
+consistent!(dutree_0, r"^\d+\D?$");
+
+// djangohashers-0.3.0: r"^[A-Za-z0-9]*$"
+consistent!(djangohashers_0, r"^[A-Za-z0-9]*$");
+
+// rtag-0.3.5: r"^[A-Z][A-Z0-9]{2,}$"
+consistent!(rtag_0, r"^[A-Z][A-Z0-9]{2,}$");
+
+// rtag-0.3.5: r"^http://www\.emusic\.com"
+consistent!(rtag_1, r"^http://www\.emusic\.com");
+
+// rtag-0.3.5: r"^[A-Z][A-Z0-9]{2,}"
+consistent!(rtag_2, r"^[A-Z][A-Z0-9]{2,}");
+
+// rtag-0.3.5: r"(^[\x{0}|\x{feff}|\x{fffe}]*|[\x{0}|\x{feff}|\x{fffe}]*$)"
+consistent!(rtag_3, r"(^[\x{0}|\x{feff}|\x{fffe}]*|[\x{0}|\x{feff}|\x{fffe}]*$)");
+
+// rtow-0.1.0: r"(\d+)[xX](\d+)"
+consistent!(rtow_0, r"(\d+)[xX](\d+)");
+
+// pleingres-sql-plugin-0.1.0: r"\$([a-zA-Z0-9_]+)"
+consistent!(pleingres_sql_plugin_0, r"\$([a-zA-Z0-9_]+)");
+
+// dono-2.0.0: "[\\n]+"
+consistent!(dono_0, "[\\n]+");
+
+// dono-2.0.0: "(?m)^\\n"
+consistent!(dono_1, "(?m)^\\n");
+
+// dono-2.0.0: "(?m)^\\n"
+consistent!(dono_2, "(?m)^\\n");
+
+// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{43}=\.ed25519$"
+consistent!(ssb_common_0, r"^[0-9A-Za-z\+/]{43}=\.ed25519$");
+
+// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{86}==\.ed25519$"
+consistent!(ssb_common_1, r"^[0-9A-Za-z\+/]{86}==\.ed25519$");
+
+// ssb-common-0.3.0: r"^[0-9A-Za-z\+/]{43}=\.sha256$"
+consistent!(ssb_common_2, r"^[0-9A-Za-z\+/]{43}=\.sha256$");
+
+// mozversion-0.1.3: r"^(?P<major>\d+)\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?(?:(?P<pre0>[a-z]+)(?P<pre1>\d*))?$"
+consistent!(mozversion_0, r"^(?P<major>\d+)\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?(?:(?P<pre0>[a-z]+)(?P<pre1>\d*))?$");
+
+// monger-0.5.6: r"^(\d+)\.(\d+)$"
+consistent!(monger_0, r"^(\d+)\.(\d+)$");
+
+// mongo_rub-0.0.2: r"^[rv]2\.6"
+consistent!(mongo_rub_0, r"^[rv]2\.6");
+
+// flow-0.3.5: "body value"
+consistent!(flow_0, "body value");
+
+// flow-0.3.5: "start marker"
+consistent!(flow_1, "start marker");
+
+// flow-0.3.5: "end marker"
+consistent!(flow_2, "end marker");
+
+// flow-0.3.5: "body value"
+consistent!(flow_3, "body value");
+
+// vobsub-0.2.3: "^([A-Za-z/ ]+): (.*)"
+consistent!(vobsub_0, "^([A-Za-z/ ]+): (.*)");
+
+// voidmap-1.1.2: r"#([^\s=]+)*"
+consistent!(voidmap_0, r"#([^\s=]+)*");
+
+// voidmap-1.1.2: r"#(\S+)*"
+consistent!(voidmap_1, r"#(\S+)*");
+
+// voidmap-1.1.2: r"#prio=(\d+)"
+consistent!(voidmap_2, r"#prio=(\d+)");
+
+// voidmap-1.1.2: r"\[(\S+)\]"
+consistent!(voidmap_3, r"\[(\S+)\]");
+
+// voidmap-1.1.2: r"#limit=(\d+)"
+consistent!(voidmap_4, r"#limit=(\d+)");
+
+// voidmap-1.1.2: r"#tagged=(\S+)"
+consistent!(voidmap_5, r"#tagged=(\S+)");
+
+// voidmap-1.1.2: r"#rev\b"
+consistent!(voidmap_6, r"#rev\b");
+
+// voidmap-1.1.2: r"#done\b"
+consistent!(voidmap_7, r"#done\b");
+
+// voidmap-1.1.2: r"#open\b"
+consistent!(voidmap_8, r"#open\b");
+
+// voidmap-1.1.2: r"#since=(\S+)"
+consistent!(voidmap_9, r"#since=(\S+)");
+
+// voidmap-1.1.2: r"#until=(\S+)"
+consistent!(voidmap_10, r"#until=(\S+)");
+
+// voidmap-1.1.2: r"#plot=(\S+)"
+consistent!(voidmap_11, r"#plot=(\S+)");
+
+// voidmap-1.1.2: r"#n=(\d+)"
+consistent!(voidmap_12, r"#n=(\d+)");
+
+// voidmap-1.1.2: r"(\S+)"
+consistent!(voidmap_13, r"(\S+)");
+
+// voidmap-1.1.2: r"(?P<y>\d+)y"
+consistent!(voidmap_14, r"(?P<y>\d+)y");
+
+// voidmap-1.1.2: r"(?P<m>\d+)m"
+consistent!(voidmap_15, r"(?P<m>\d+)m");
+
+// voidmap-1.1.2: r"(?P<w>\d+)w"
+consistent!(voidmap_16, r"(?P<w>\d+)w");
+
+// voidmap-1.1.2: r"(?P<d>\d+)d"
+consistent!(voidmap_17, r"(?P<d>\d+)d");
+
+// voidmap-1.1.2: r"(?P<h>\d+)h"
+consistent!(voidmap_18, r"(?P<h>\d+)h");
+
+// voidmap-1.1.2: r"C-(.)"
+consistent!(voidmap_19, r"C-(.)");
+
+// qt_generator-0.2.0: r"^\.\./qt[^/]+/"
+consistent!(qt_generator_0, r"^\.\./qt[^/]+/");
+
+// qt_generator-0.2.0: "(href|src)=\"([^\"]*)\""
+consistent!(qt_generator_1, "(href|src)=\"([^\"]*)\"");
+
+// kryptos-0.6.1: r"[01]{5}"
+consistent!(kryptos_0, r"[01]{5}");
+
+// cifar_10_loader-0.2.0: "data_batch_[1-5].bin"
+consistent!(cifar_10_loader_0, "data_batch_[1-5].bin");
+
+// cifar_10_loader-0.2.0: "test_batch.bin"
+consistent!(cifar_10_loader_1, "test_batch.bin");
+
+// circadian-0.6.0: r"^\d+.\d+s$"
+consistent!(circadian_0, r"^\d+.\d+s$");
+
+// circadian-0.6.0: r"^\d+:\d+$"
+consistent!(circadian_1, r"^\d+:\d+$");
+
+// circadian-0.6.0: r"^\d+:\d+m$"
+consistent!(circadian_2, r"^\d+:\d+m$");
+
+// cicada-0.8.1: r"!!"
+consistent!(cicada_0, r"!!");
+
+// cicada-0.8.1: r"^([^`]*)`([^`]+)`(.*)$"
+consistent!(cicada_1, r"^([^`]*)`([^`]+)`(.*)$");
+
+// cicada-0.8.1: r"\*+"
+consistent!(cicada_2, r"\*+");
+
+// cicada-0.8.1: r"([^\$]*)\$\{?([A-Za-z0-9\?\$_]+)\}?(.*)"
+consistent!(cicada_3, r"([^\$]*)\$\{?([A-Za-z0-9\?\$_]+)\}?(.*)");
+
+// cicada-0.8.1: r"^ *alias +([a-zA-Z0-9_\.-]+)=(.*)$"
+consistent!(cicada_4, r"^ *alias +([a-zA-Z0-9_\.-]+)=(.*)$");
+
+// vterm-sys-0.1.0: r"hi"
+consistent!(vterm_sys_0, r"hi");
+
+// skim-0.5.0: r".*?\t"
+consistent!(skim_0, r".*?\t");
+
+// skim-0.5.0: r".*?[\t ]"
+consistent!(skim_1, r".*?[\t ]");
+
+// skim-0.5.0: r"(\{-?[0-9.,q]*?})"
+consistent!(skim_2, r"(\{-?[0-9.,q]*?})");
+
+// skim-0.5.0: r"[ \t\n]+"
+consistent!(skim_3, r"[ \t\n]+");
+
+// skim-0.5.0: r"[ \t\n]+"
+consistent!(skim_4, r"[ \t\n]+");
+
+// skim-0.5.0: r"([^ |]+( +\| +[^ |]*)+)|( +)"
+consistent!(skim_5, r"([^ |]+( +\| +[^ |]*)+)|( +)");
+
+// skim-0.5.0: r" +\| +"
+consistent!(skim_6, r" +\| +");
+
+// skim-0.5.0: r"^(?P<left>-?\d+)?(?P<sep>\.\.)?(?P<right>-?\d+)?$"
+consistent!(skim_7, r"^(?P<left>-?\d+)?(?P<sep>\.\.)?(?P<right>-?\d+)?$");
+
+// skim-0.5.0: ","
+consistent!(skim_8, ",");
+
+// skim-0.5.0: ".*?,"
+consistent!(skim_9, ".*?,");
+
+// skim-0.5.0: ".*?,"
+consistent!(skim_10, ".*?,");
+
+// skim-0.5.0: ","
+consistent!(skim_11, ",");
+
+// skim-0.5.0: r"\x1B\[(?:([0-9]+;[0-9]+[Hf])|([0-9]+[ABCD])|(s|u|2J|K)|([0-9;]*m)|(=[0-9]+[hI]))"
+consistent!(skim_12, r"\x1B\[(?:([0-9]+;[0-9]+[Hf])|([0-9]+[ABCD])|(s|u|2J|K)|([0-9;]*m)|(=[0-9]+[hI]))");
+
+// egg-mode-text-1.14.7: r"[-_./]\z"
+consistent!(egg_mode_text_0, r"[-_./]\z");
+
+// java-properties-1.1.1: "^[ \t\r\n\x0c]*[#!]"
+consistent!(java_properties_0, "^[ \t\r\n\x0c]*[#!]");
+
+// java-properties-1.1.1: r"^[ \t\x0c]*[#!][^\r\n]*$"
+consistent!(java_properties_1, r"^[ \t\x0c]*[#!][^\r\n]*$");
+
+// java-properties-1.1.1: r"^([ \t\x0c]*[:=][ \t\x0c]*|[ \t\x0c]+)$"
+consistent!(java_properties_2, r"^([ \t\x0c]*[:=][ \t\x0c]*|[ \t\x0c]+)$");
+
+// ipaddress-0.1.2: r":.+\."
+consistent!(ipaddress_0, r":.+\.");
+
+// ipaddress-0.1.2: r"\."
+consistent!(ipaddress_1, r"\.");
+
+// ipaddress-0.1.2: r":"
+consistent!(ipaddress_2, r":");
+
+// iptables-0.2.2: r"v(\d+)\.(\d+)\.(\d+)"
+consistent!(iptables_0, r"v(\d+)\.(\d+)\.(\d+)");
+
+// rsure-0.8.1: r"^([^-]+)-(.*)\.dat\.gz$"
+consistent!(rsure_0, r"^([^-]+)-(.*)\.dat\.gz$");
+
+// rs-jsonpath-0.1.0: "^(.*?)(<=|<|==|>=|>)(.*?)$"
+consistent!(rs_jsonpath_0, "^(.*?)(<=|<|==|>=|>)(.*?)$");
+
+// oatie-0.3.0: r"(\n|^)(\w+):([\n\w\W]+?)(\n(?:\w)|(\n\]))"
+consistent!(oatie_0, r"(\n|^)(\w+):([\n\w\W]+?)(\n(?:\w)|(\n\]))");
+
+// weld-0.2.0: "#.*$"
+consistent!(weld_0, "#.*$");
+
+// weld-0.2.0: r"^[A-Za-z$_][A-Za-z0-9$_]*$"
+consistent!(weld_1, r"^[A-Za-z$_][A-Za-z0-9$_]*$");
+
+// weld-0.2.0: r"^[0-9]+[cC]$"
+consistent!(weld_2, r"^[0-9]+[cC]$");
+
+// weld-0.2.0: r"^0b[0-1]+[cC]$"
+consistent!(weld_3, r"^0b[0-1]+[cC]$");
+
+// weld-0.2.0: r"^0x[0-9a-fA-F]+[cC]$"
+consistent!(weld_4, r"^0x[0-9a-fA-F]+[cC]$");
+
+// weld-0.2.0: r"^[0-9]+$"
+consistent!(weld_5, r"^[0-9]+$");
+
+// weld-0.2.0: r"^0b[0-1]+$"
+consistent!(weld_6, r"^0b[0-1]+$");
+
+// weld-0.2.0: r"^0x[0-9a-fA-F]+$"
+consistent!(weld_7, r"^0x[0-9a-fA-F]+$");
+
+// weld-0.2.0: r"^[0-9]+[lL]$"
+consistent!(weld_8, r"^[0-9]+[lL]$");
+
+// weld-0.2.0: r"^0b[0-1]+[lL]$"
+consistent!(weld_9, r"^0b[0-1]+[lL]$");
+
+// weld-0.2.0: r"^0x[0-9a-fA-F]+[lL]$"
+consistent!(weld_10, r"^0x[0-9a-fA-F]+[lL]$");
+
+// webgl_generator-0.1.0: "([(, ])enum\\b"
+consistent!(webgl_generator_0, "([(, ])enum\\b");
+
+// webgl_generator-0.1.0: "\\bAcquireResourcesCallback\\b"
+consistent!(webgl_generator_1, "\\bAcquireResourcesCallback\\b");
+
+// weave-0.2.0: r"^(\d+)(,(\d+))?([acd]).*$"
+consistent!(weave_0, r"^(\d+)(,(\d+))?([acd]).*$");
+
+// wemo-0.0.12: r"<BinaryState>(\d)(\|-?\d+)*</BinaryState>"
+consistent!(wemo_0, r"<BinaryState>(\d)(\|-?\d+)*</BinaryState>");
+
+// webscale-0.9.4: r"(http[s]?://[^\s]+)"
+consistent!(webscale_0, r"(http[s]?://[^\s]+)");
+
+// svgrep-1.1.0: r"^\d+.*$"
+consistent!(svgrep_0, r"^\d+.*$");
+
+// ignore-0.4.2: r"^[\pL\pN]+$"
+consistent!(ignore_0, r"^[\pL\pN]+$");
+
+// ommui_string_patterns-0.1.2: r"^([A-Za-z][0-9A-Za-z_]*)?$"
+consistent!(ommui_string_patterns_0, r"^([A-Za-z][0-9A-Za-z_]*)?$");
+
+// ommui_string_patterns-0.1.2: r"^(\S+(?:.*\S)?)?$"
+consistent!(ommui_string_patterns_1, r"^(\S+(?:.*\S)?)?$");
+
+// opcua-types-0.3.0: "^(?P<min>[0-9]{1,10})(:(?P<max>[0-9]{1,10}))?$"
+consistent!(opcua_types_0, "^(?P<min>[0-9]{1,10})(:(?P<max>[0-9]{1,10}))?$");
+
+// opcua-types-0.3.0: r"^(ns=(?P<ns>[0-9]+);)?(?P<t>[isgb])=(?P<v>.+)$"
+consistent!(opcua_types_1, r"^(ns=(?P<ns>[0-9]+);)?(?P<t>[isgb])=(?P<v>.+)$");
+
+// open_read_later-1.1.1: r"^(.+?)\s*:\s*(.+)$"
+consistent!(open_read_later_0, r"^(.+?)\s*:\s*(.+)$");
+
+// youtube-downloader-0.1.0: r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*"
+consistent!(youtube_downloader_0, r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*");
+
+// yobot-0.1.1: "."
+consistent!(yobot_0, ".");
+
+// yobot-0.1.1: r"."
+consistent!(yobot_1, r".");
+
+// yobot-0.1.1: r".+"
+consistent!(yobot_2, r".+");
+
+// yobot-0.1.1: r"."
+consistent!(yobot_3, r".");
+
+// ubiquity-0.1.5: r"foo"
+consistent!(ubiquity_0, r"foo");
+
+// ubiquity-0.1.5: r"/target/"
+consistent!(ubiquity_1, r"/target/");
+
+// ubiquity-0.1.5: r".DS_Store"
+consistent!(ubiquity_2, r".DS_Store");
+
+// qasm-1.0.0: r"//.*"
+consistent!(qasm_0, r"//.*");
+
+// drill-0.3.5: r"\{\{ *([a-z\._]+) *\}\}"
+consistent!(drill_0, r"\{\{ *([a-z\._]+) *\}\}");
+
+// queryst-2.0.0: r"^([^\]\[]+)"
+consistent!(queryst_0, r"^([^\]\[]+)");
+
+// queryst-2.0.0: r"(\[[^\]\[]*\])"
+consistent!(queryst_1, r"(\[[^\]\[]*\])");
+
+// qui-vive-0.1.0: r"^/(\w+)$"
+consistent!(qui_vive_0, r"^/(\w+)$");
+
+// qui-vive-0.1.0: r"^/key$"
+consistent!(qui_vive_1, r"^/key$");
+
+// qui-vive-0.1.0: r"^/key/(\w+)$"
+consistent!(qui_vive_2, r"^/key/(\w+)$");
+
+// qui-vive-0.1.0: r"^/url$"
+consistent!(qui_vive_3, r"^/url$");
+
+// qui-vive-0.1.0: r"^/url/(\w+)$"
+consistent!(qui_vive_4, r"^/url/(\w+)$");
+
+// qui-vive-0.1.0: r"^/inv$"
+consistent!(qui_vive_5, r"^/inv$");
+
+// qui-vive-0.1.0: r"^/inv/(\w+)$"
+consistent!(qui_vive_6, r"^/inv/(\w+)$");
+
+// subdiff-0.1.0: r"\b"
+// consistent!(subdiff_0, r"\b");
+
+// substudy-0.4.5: r"^(\d+)/(\d+)$"
+consistent!(substudy_0, r"^(\d+)/(\d+)$");
+
+// substudy-0.4.5: r"\s+"
+consistent!(substudy_1, r"\s+");
+
+// substudy-0.4.5: r"<[a-z/][^>]*>"
+consistent!(substudy_2, r"<[a-z/][^>]*>");
+
+// substudy-0.4.5: r"(\([^)]*\)|♪[^♪]*♪|[A-Z]{2,} ?:)"
+consistent!(substudy_3, r"(\([^)]*\)|♪[^♪]*♪|[A-Z]{2,} ?:)");
+
+// substudy-0.4.5: r"\s+"
+consistent!(substudy_4, r"\s+");
+
+// isbnid-0.1.3: r"^(\d(-| )?){9}(x|X|\d|(\d(-| )?){3}\d)$"
+consistent!(isbnid_0, r"^(\d(-| )?){9}(x|X|\d|(\d(-| )?){3}\d)$");
+
+// isbnid-0.1.3: r"[^0-9X]"
+consistent!(isbnid_1, r"[^0-9X]");
+
+// ispc-0.3.5: r"Intel\(r\) SPMD Program Compiler \(ispc\), (\d+\.\d+\.\d+)"
+consistent!(ispc_0, r"Intel\(r\) SPMD Program Compiler \(ispc\), (\d+\.\d+\.\d+)");
+
diff --git a/vendor/proptest/src/result.rs b/vendor/proptest/src/result.rs
new file mode 100644
index 000000000..bdb163b35
--- /dev/null
+++ b/vendor/proptest/src/result.rs
@@ -0,0 +1,326 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+//! Strategies for combining delegate strategies into `std::Result`s.
+//!
+//! That is, the strategies here are for producing `Ok` _and_ `Err` cases. To
+//! simply adapt a strategy producing `T` into `Result<T, something>` which is
+//! always `Ok`, you can do something like `base_strategy.prop_map(Ok)` to
+//! simply wrap the generated values.
+//!
+//! Note that there are two nearly identical APIs for doing this, termed "maybe
+//! ok" and "maybe err". The difference between the two is in how they shrink;
+//! "maybe ok" treats `Ok` as the special case and shrinks to `Err`;
+//! conversely, "maybe err" treats `Err` as the special case and shrinks to
+//! `Ok`. Which to use largely depends on the code being tested; if the code
+//! typically handles errors by immediately bailing out and doing nothing else,
+//! "maybe ok" is likely more suitable, as shrinking will cause the code to
+//! take simpler paths. On the other hand, functions that need to make a
+//! complicated or fragile "back out" process on error are better tested with
+//! "maybe err" since the success case results in an easier to understand code
+//! path.
+
+#![cfg_attr(feature = "cargo-clippy", allow(expl_impl_clone_on_copy))]
+
+use core::fmt;
+use core::marker::PhantomData;
+
+use crate::std_facade::Arc;
+use crate::strategy::*;
+use crate::test_runner::*;
+
+// Re-export the type for easier usage.
+pub use crate::option::{prob, Probability};
+
+struct WrapOk<T, E>(PhantomData<T>, PhantomData<E>);
+impl<T, E> Clone for WrapOk<T, E> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+impl<T, E> Copy for WrapOk<T, E> {}
+impl<T, E> fmt::Debug for WrapOk<T, E> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "WrapOk")
+ }
+}
+impl<T: fmt::Debug, E: fmt::Debug> statics::MapFn<T> for WrapOk<T, E> {
+ type Output = Result<T, E>;
+ fn apply(&self, t: T) -> Result<T, E> {
+ Ok(t)
+ }
+}
+struct WrapErr<T, E>(PhantomData<T>, PhantomData<E>);
+impl<T, E> Clone for WrapErr<T, E> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+impl<T, E> Copy for WrapErr<T, E> {}
+impl<T, E> fmt::Debug for WrapErr<T, E> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "WrapErr")
+ }
+}
+impl<T: fmt::Debug, E: fmt::Debug> statics::MapFn<E> for WrapErr<T, E> {
+ type Output = Result<T, E>;
+ fn apply(&self, e: E) -> Result<T, E> {
+ Err(e)
+ }
+}
+
+type MapErr<T, E> =
+ statics::Map<E, WrapErr<<T as Strategy>::Value, <E as Strategy>::Value>>;
+type MapOk<T, E> =
+ statics::Map<T, WrapOk<<T as Strategy>::Value, <E as Strategy>::Value>>;
+
+opaque_strategy_wrapper! {
+ /// Strategy which generates `Result`s using `Ok` and `Err` values from two
+ /// delegate strategies.
+ ///
+ /// Shrinks to `Err`.
+ #[derive(Clone)]
+ pub struct MaybeOk[<T, E>][where T : Strategy, E : Strategy]
+ (TupleUnion<(WA<MapErr<T, E>>, WA<MapOk<T, E>>)>)
+ -> MaybeOkValueTree<T, E>;
+ /// `ValueTree` type corresponding to `MaybeOk`.
+ pub struct MaybeOkValueTree[<T, E>][where T : Strategy, E : Strategy]
+ (TupleUnionValueTree<(
+ LazyValueTree<statics::Map<E, WrapErr<T::Value, E::Value>>>,
+ Option<LazyValueTree<statics::Map<T, WrapOk<T::Value, E::Value>>>>,
+ )>)
+ -> Result<T::Value, E::Value>;
+}
+
+opaque_strategy_wrapper! {
+ /// Strategy which generates `Result`s using `Ok` and `Err` values from two
+ /// delegate strategies.
+ ///
+ /// Shrinks to `Ok`.
+ #[derive(Clone)]
+ pub struct MaybeErr[<T, E>][where T : Strategy, E : Strategy]
+ (TupleUnion<(WA<MapOk<T, E>>, WA<MapErr<T, E>>)>)
+ -> MaybeErrValueTree<T, E>;
+ /// `ValueTree` type corresponding to `MaybeErr`.
+ pub struct MaybeErrValueTree[<T, E>][where T : Strategy, E : Strategy]
+ (TupleUnionValueTree<(
+ LazyValueTree<statics::Map<T, WrapOk<T::Value, E::Value>>>,
+ Option<LazyValueTree<statics::Map<E, WrapErr<T::Value, E::Value>>>>,
+ )>)
+ -> Result<T::Value, E::Value>;
+}
+
+// These need to exist for the same reason as the one on `OptionStrategy`
+impl<T: Strategy + fmt::Debug, E: Strategy + fmt::Debug> fmt::Debug
+ for MaybeOk<T, E>
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "MaybeOk({:?})", self.0)
+ }
+}
+impl<T: Strategy + fmt::Debug, E: Strategy + fmt::Debug> fmt::Debug
+ for MaybeErr<T, E>
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "MaybeErr({:?})", self.0)
+ }
+}
+
+impl<T: Strategy, E: Strategy> Clone for MaybeOkValueTree<T, E>
+where
+ T::Tree: Clone,
+ E::Tree: Clone,
+{
+ fn clone(&self) -> Self {
+ MaybeOkValueTree(self.0.clone())
+ }
+}
+
+impl<T: Strategy, E: Strategy> fmt::Debug for MaybeOkValueTree<T, E>
+where
+ T::Tree: fmt::Debug,
+ E::Tree: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "MaybeOkValueTree({:?})", self.0)
+ }
+}
+
+impl<T: Strategy, E: Strategy> Clone for MaybeErrValueTree<T, E>
+where
+ T::Tree: Clone,
+ E::Tree: Clone,
+{
+ fn clone(&self) -> Self {
+ MaybeErrValueTree(self.0.clone())
+ }
+}
+
+impl<T: Strategy, E: Strategy> fmt::Debug for MaybeErrValueTree<T, E>
+where
+ T::Tree: fmt::Debug,
+ E::Tree: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "MaybeErrValueTree({:?})", self.0)
+ }
+}
+
+/// Create a strategy for `Result`s where `Ok` values are taken from `t` and
+/// `Err` values are taken from `e`.
+///
+/// `Ok` and `Err` are chosen with equal probability.
+///
+/// Generated values shrink to `Err`.
+pub fn maybe_ok<T: Strategy, E: Strategy>(t: T, e: E) -> MaybeOk<T, E> {
+ maybe_ok_weighted(0.5, t, e)
+}
+
+/// Create a strategy for `Result`s where `Ok` values are taken from `t` and
+/// `Err` values are taken from `e`.
+///
+/// `probability_of_ok` is the probability (between 0.0 and 1.0, exclusive)
+/// that `Ok` is initially chosen.
+///
+/// Generated values shrink to `Err`.
+pub fn maybe_ok_weighted<T: Strategy, E: Strategy>(
+ probability_of_ok: impl Into<Probability>,
+ t: T,
+ e: E,
+) -> MaybeOk<T, E> {
+ let prob = probability_of_ok.into().into();
+ let (ok_weight, err_weight) = float_to_weight(prob);
+
+ MaybeOk(TupleUnion::new((
+ (
+ err_weight,
+ Arc::new(statics::Map::new(e, WrapErr(PhantomData, PhantomData))),
+ ),
+ (
+ ok_weight,
+ Arc::new(statics::Map::new(t, WrapOk(PhantomData, PhantomData))),
+ ),
+ )))
+}
+
+/// Create a strategy for `Result`s where `Ok` values are taken from `t` and
+/// `Err` values are taken from `e`.
+///
+/// `Ok` and `Err` are chosen with equal probability.
+///
+/// Generated values shrink to `Ok`.
+pub fn maybe_err<T: Strategy, E: Strategy>(t: T, e: E) -> MaybeErr<T, E> {
+ maybe_err_weighted(0.5, t, e)
+}
+
+/// Create a strategy for `Result`s where `Ok` values are taken from `t` and
+/// `Err` values are taken from `e`.
+///
+/// `probability_of_ok` is the probability (between 0.0 and 1.0, exclusive)
+/// that `Err` is initially chosen.
+///
+/// Generated values shrink to `Ok`.
+pub fn maybe_err_weighted<T: Strategy, E: Strategy>(
+ probability_of_err: impl Into<Probability>,
+ t: T,
+ e: E,
+) -> MaybeErr<T, E> {
+ let prob = probability_of_err.into().into();
+ let (err_weight, ok_weight) = float_to_weight(prob);
+
+ MaybeErr(TupleUnion::new((
+ (
+ ok_weight,
+ Arc::new(statics::Map::new(t, WrapOk(PhantomData, PhantomData))),
+ ),
+ (
+ err_weight,
+ Arc::new(statics::Map::new(e, WrapErr(PhantomData, PhantomData))),
+ ),
+ )))
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ fn count_ok_of_1000(s: impl Strategy<Value = Result<(), ()>>) -> u32 {
+ let mut runner = TestRunner::deterministic();
+ let mut count = 0;
+ for _ in 0..1000 {
+ count += s.new_tree(&mut runner).unwrap().current().is_ok() as u32;
+ }
+
+ count
+ }
+
+ #[test]
+ fn probability_defaults_to_0p5() {
+ let count = count_ok_of_1000(maybe_err(Just(()), Just(())));
+ assert!(count > 400 && count < 600);
+ let count = count_ok_of_1000(maybe_ok(Just(()), Just(())));
+ assert!(count > 400 && count < 600);
+ }
+
+ #[test]
+ fn probability_handled_correctly() {
+ let count =
+ count_ok_of_1000(maybe_err_weighted(0.1, Just(()), Just(())));
+ assert!(count > 800 && count < 950);
+
+ let count =
+ count_ok_of_1000(maybe_err_weighted(0.9, Just(()), Just(())));
+ assert!(count > 50 && count < 150);
+
+ let count =
+ count_ok_of_1000(maybe_ok_weighted(0.9, Just(()), Just(())));
+ assert!(count > 800 && count < 950);
+
+ let count =
+ count_ok_of_1000(maybe_ok_weighted(0.1, Just(()), Just(())));
+ assert!(count > 50 && count < 150);
+ }
+
+ #[test]
+ fn shrink_to_correct_case() {
+ let mut runner = TestRunner::default();
+ {
+ let input = maybe_err(Just(()), Just(()));
+ for _ in 0..64 {
+ let mut val = input.new_tree(&mut runner).unwrap();
+ if val.current().is_ok() {
+ assert!(!val.simplify());
+ assert!(val.current().is_ok());
+ } else {
+ assert!(val.simplify());
+ assert!(val.current().is_ok());
+ }
+ }
+ }
+ {
+ let input = maybe_ok(Just(()), Just(()));
+ for _ in 0..64 {
+ let mut val = input.new_tree(&mut runner).unwrap();
+ if val.current().is_err() {
+ assert!(!val.simplify());
+ assert!(val.current().is_err());
+ } else {
+ assert!(val.simplify());
+ assert!(val.current().is_err());
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_sanity() {
+ check_strategy_sanity(maybe_ok(0i32..100i32, 0i32..100i32), None);
+ check_strategy_sanity(maybe_err(0i32..100i32, 0i32..100i32), None);
+ }
+}
diff --git a/vendor/proptest/src/sample.rs b/vendor/proptest/src/sample.rs
new file mode 100644
index 000000000..9c464f132
--- /dev/null
+++ b/vendor/proptest/src/sample.rs
@@ -0,0 +1,566 @@
+//-
+// Copyright 2017, 2018 Jason Lingle
+//
+// 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.
+
+//! Strategies for generating values by taking samples of collections.
+//!
+//! Note that the strategies in this module are not native combinators; that
+//! is, the input collection is not itself a strategy, but is rather fixed when
+//! the strategy is created.
+
+use crate::std_facade::{Arc, Cow, Vec};
+use core::fmt;
+use core::mem;
+use core::ops::Range;
+use core::u64;
+
+use rand::Rng;
+
+use crate::bits::{self, BitSetValueTree, SampledBitSetStrategy, VarBitSet};
+use crate::num;
+use crate::strategy::*;
+use crate::test_runner::*;
+
+/// Re-exported to make usage more ergonomic.
+pub use crate::collection::{size_range, SizeRange};
+
+/// Sample subsequences whose size are within `size` from the given collection
+/// `values`.
+///
+/// A subsequence is a subset of the elements in a collection in the order they
+/// occur in that collection. The elements are not chosen to be contiguous.
+///
+/// This is roughly analogous to `rand::sample`, except that it guarantees that
+/// the order is preserved.
+///
+/// `values` may be a static slice or a `Vec`.
+///
+/// ## Panics
+///
+/// Panics if the maximum size implied by `size` is larger than the size of
+/// `values`.
+///
+/// Panics if `size` is a zero-length range.
+pub fn subsequence<T: Clone + 'static>(
+ values: impl Into<Cow<'static, [T]>>,
+ size: impl Into<SizeRange>,
+) -> Subsequence<T> {
+ let values = values.into();
+ let len = values.len();
+ let size = size.into();
+
+ size.assert_nonempty();
+ assert!(
+ size.end_incl() <= len,
+ "Maximum size of subsequence {} exceeds length of input {}",
+ size.end_incl(),
+ len
+ );
+ Subsequence {
+ values: Arc::new(values),
+ bit_strategy: bits::varsize::sampled(size, 0..len),
+ }
+}
+
+/// Strategy to generate `Vec`s by sampling a subsequence from another
+/// collection.
+///
+/// This is created by the `subsequence` function in the same module.
+#[derive(Debug, Clone)]
+#[must_use = "strategies do nothing unless used"]
+pub struct Subsequence<T: Clone + 'static> {
+ values: Arc<Cow<'static, [T]>>,
+ bit_strategy: SampledBitSetStrategy<VarBitSet>,
+}
+
+impl<T: fmt::Debug + Clone + 'static> Strategy for Subsequence<T> {
+ type Tree = SubsequenceValueTree<T>;
+ type Value = Vec<T>;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(SubsequenceValueTree {
+ values: Arc::clone(&self.values),
+ inner: self.bit_strategy.new_tree(runner)?,
+ })
+ }
+}
+
+/// `ValueTree` type for `Subsequence`.
+#[derive(Debug, Clone)]
+pub struct SubsequenceValueTree<T: Clone + 'static> {
+ values: Arc<Cow<'static, [T]>>,
+ inner: BitSetValueTree<VarBitSet>,
+}
+
+impl<T: fmt::Debug + Clone + 'static> ValueTree for SubsequenceValueTree<T> {
+ type Value = Vec<T>;
+
+ fn current(&self) -> Self::Value {
+ let inner = self.inner.current();
+ let ret = inner.iter().map(|ix| self.values[ix].clone()).collect();
+ ret
+ }
+
+ fn simplify(&mut self) -> bool {
+ self.inner.simplify()
+ }
+
+ fn complicate(&mut self) -> bool {
+ self.inner.complicate()
+ }
+}
+
+#[derive(Debug, Clone)]
+struct SelectMapFn<T: Clone + 'static>(Arc<Cow<'static, [T]>>);
+
+impl<T: fmt::Debug + Clone + 'static> statics::MapFn<usize> for SelectMapFn<T> {
+ type Output = T;
+
+ fn apply(&self, ix: usize) -> T {
+ self.0[ix].clone()
+ }
+}
+
+opaque_strategy_wrapper! {
+ /// Strategy to produce one value from a fixed collection of options.
+ ///
+ /// Created by the `select()` in the same module.
+ #[derive(Clone, Debug)]
+ pub struct Select[<T>][where T : Clone + fmt::Debug + 'static](
+ statics::Map<Range<usize>, SelectMapFn<T>>)
+ -> SelectValueTree<T>;
+ /// `ValueTree` corresponding to `Select`.
+ #[derive(Clone, Debug)]
+ pub struct SelectValueTree[<T>][where T : Clone + fmt::Debug + 'static](
+ statics::Map<num::usize::BinarySearch, SelectMapFn<T>>)
+ -> T;
+}
+
+/// Create a strategy which uniformly selects one value from `values`.
+///
+/// `values` should be a `&'static [T]` or a `Vec<T>`, or potentially another
+/// type that can be coerced to `Cow<'static,[T]>`.
+///
+/// This is largely equivalent to making a `Union` of a bunch of `Just`
+/// strategies, but is substantially more efficient and shrinks by binary
+/// search.
+///
+/// If `values` is also to be generated by a strategy, see
+/// [`Index`](struct.Index.html) for a more efficient way to select values than
+/// using `prop_flat_map()`.
+pub fn select<T: Clone + fmt::Debug + 'static>(
+ values: impl Into<Cow<'static, [T]>>,
+) -> Select<T> {
+ let cow = values.into();
+
+ Select(statics::Map::new(0..cow.len(), SelectMapFn(Arc::new(cow))))
+}
+
+/// A stand-in for an index into a slice or similar collection or conceptually
+/// similar things.
+///
+/// At the lowest level, `Index` is a mechanism for generating `usize` values
+/// in the range [0..N), for some N whose value is not known until it is
+/// needed. (Contrast with using `0..N` itself as a strategy, where you need to
+/// know N when you define the strategy.)
+///
+/// For any upper bound, the actual index produced by an `Index` is the same no
+/// matter how many times it is used. Different upper bounds will produce
+/// different but not independent values.
+///
+/// Shrinking will cause the index to binary search through the underlying
+/// collection(s) it is used to sample.
+///
+/// Note that `Index` _cannot_ currently be used as a slice index (e.g.,
+/// `slice[index]`) due to the trait coherence rules.
+///
+/// ## Example
+///
+/// If the collection itself being indexed is itself generated by a strategy,
+/// you can make separately define that strategy and a strategy generating one
+/// or more `Index`es and then join the two after input generation, avoiding a
+/// call to `prop_flat_map()`.
+///
+/// ```
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// # /*
+/// #[test]
+/// # */
+/// fn my_test(
+/// names in prop::collection::vec("[a-z]+", 10..20),
+/// indices in prop::collection::vec(any::<prop::sample::Index>(), 5..10)
+/// ) {
+/// // We now have Vec<String> of ten to twenty names, and a Vec<Index>
+/// // of five to ten indices and can combine them however we like.
+/// for index in &indices {
+/// println!("Accessing item by index: {}", names[index.index(names.len())]);
+/// println!("Accessing item by convenience method: {}", index.get(&names));
+/// }
+/// // Test stuff...
+/// }
+/// }
+/// #
+/// # fn main() { my_test(); }
+/// ```
+#[derive(Clone, Copy, Debug)]
+pub struct Index(usize);
+
+impl Index {
+ /// Return the real index that would be used to index a collection of size `size`.
+ ///
+ /// ## Panics
+ ///
+ /// Panics if `size == 0`.
+ pub fn index(&self, size: usize) -> usize {
+ assert!(size > 0, "Attempt to use `Index` with 0-size collection");
+
+ // No platforms currently have `usize` wider than 64 bits, so `u128` is
+ // sufficient to hold the result of a full multiply, letting us do a
+ // simple fixed-point multiply.
+ ((size as u128) * (self.0 as u128) >> (mem::size_of::<usize>() * 8))
+ as usize
+ }
+
+ /// Return a reference to the element in `slice` that this `Index` refers to.
+ ///
+ /// A shortcut for `&slice[index.index(slice.len())]`.
+ pub fn get<'a, T>(&self, slice: &'a [T]) -> &'a T {
+ &slice[self.index(slice.len())]
+ }
+
+ /// Return a mutable reference to the element in `slice` that this `Index`
+ /// refers to.
+ ///
+ /// A shortcut for `&mut slice[index.index(slice.len())]`.
+ pub fn get_mut<'a, T>(&self, slice: &'a mut [T]) -> &'a mut T {
+ let ix = self.index(slice.len());
+ &mut slice[ix]
+ }
+}
+
+mapfn! {
+ [] fn UsizeToIndex[](raw: usize) -> Index {
+ Index(raw)
+ }
+}
+
+opaque_strategy_wrapper! {
+ /// Strategy to create `Index`es.
+ ///
+ /// Created via `any::<Index>()`.
+ #[derive(Clone, Debug)]
+ pub struct IndexStrategy[][](
+ statics::Map<num::usize::Any, UsizeToIndex>)
+ -> IndexValueTree;
+ /// `ValueTree` corresponding to `IndexStrategy`.
+ #[derive(Clone, Debug)]
+ pub struct IndexValueTree[][](
+ statics::Map<num::usize::BinarySearch,UsizeToIndex>)
+ -> Index;
+}
+
+impl IndexStrategy {
+ pub(crate) fn new() -> Self {
+ IndexStrategy(statics::Map::new(num::usize::ANY, UsizeToIndex))
+ }
+}
+
+/// A value for picking random values out of iterators.
+///
+/// This is, in a sense, a more flexible variant of
+/// [`Index`](struct.Index.html) in that it can operate on arbitrary
+/// `IntoIterator` values.
+///
+/// Initially, the selection is roughly uniform, with a very slight bias
+/// towards items earlier in the iterator.
+///
+/// Shrinking causes the selection to move toward items earlier in the
+/// iterator, ultimately settling on the very first, but this currently happens
+/// in a very haphazard way that may fail to find the earliest failing input.
+///
+/// ## Example
+///
+/// Generate a non-indexable collection and a value to pick out of it.
+///
+/// ```
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// # /*
+/// #[test]
+/// # */
+/// fn my_test(
+/// names in prop::collection::hash_set("[a-z]+", 10..20),
+/// selector in any::<prop::sample::Selector>()
+/// ) {
+/// println!("Selected name: {}", selector.select(&names));
+/// // Test stuff...
+/// }
+/// }
+/// #
+/// # fn main() { my_test(); }
+/// ```
+#[derive(Clone, Debug)]
+pub struct Selector {
+ rng: TestRng,
+ bias_increment: u64,
+}
+
+/// Strategy to create `Selector`s.
+///
+/// Created via `any::<Selector>()`.
+#[derive(Debug)]
+pub struct SelectorStrategy {
+ _nonexhaustive: (),
+}
+
+/// `ValueTree` corresponding to `SelectorStrategy`.
+#[derive(Debug)]
+pub struct SelectorValueTree {
+ rng: TestRng,
+ reverse_bias_increment: num::u64::BinarySearch,
+}
+
+impl SelectorStrategy {
+ pub(crate) fn new() -> Self {
+ SelectorStrategy { _nonexhaustive: () }
+ }
+}
+
+impl Strategy for SelectorStrategy {
+ type Tree = SelectorValueTree;
+ type Value = Selector;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(SelectorValueTree {
+ rng: runner.new_rng(),
+ reverse_bias_increment: num::u64::BinarySearch::new(u64::MAX),
+ })
+ }
+}
+
+impl ValueTree for SelectorValueTree {
+ type Value = Selector;
+
+ fn current(&self) -> Selector {
+ Selector {
+ rng: self.rng.clone(),
+ bias_increment: u64::MAX - self.reverse_bias_increment.current(),
+ }
+ }
+
+ fn simplify(&mut self) -> bool {
+ self.reverse_bias_increment.simplify()
+ }
+
+ fn complicate(&mut self) -> bool {
+ self.reverse_bias_increment.complicate()
+ }
+}
+
+impl Selector {
+ /// Pick a random element from iterable `it`.
+ ///
+ /// The selection is unaffected by the elements themselves, and is
+ /// dependent only on the actual length of `it`.
+ ///
+ /// `it` is always iterated completely.
+ ///
+ /// ## Panics
+ ///
+ /// Panics if `it` has no elements.
+ pub fn select<T: IntoIterator>(&self, it: T) -> T::Item {
+ self.try_select(it).expect("select from empty iterator")
+ }
+
+ /// Pick a random element from iterable `it`.
+ ///
+ /// Returns `None` if `it` is empty.
+ ///
+ /// The selection is unaffected by the elements themselves, and is
+ /// dependent only on the actual length of `it`.
+ ///
+ /// `it` is always iterated completely.
+ pub fn try_select<T: IntoIterator>(&self, it: T) -> Option<T::Item> {
+ let mut bias = 0u64;
+ let mut min_score = 0;
+ let mut best = None;
+ let mut rng = self.rng.clone();
+
+ for item in it {
+ let score = bias.saturating_add(rng.gen());
+ if best.is_none() || score < min_score {
+ best = Some(item);
+ min_score = score;
+ }
+
+ bias = bias.saturating_add(self.bias_increment);
+ }
+
+ best
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use crate::std_facade::BTreeSet;
+
+ use super::*;
+ use crate::arbitrary::any;
+
+ #[test]
+ fn sample_slice() {
+ static VALUES: &[usize] = &[0, 1, 2, 3, 4, 5, 6, 7];
+ let mut size_counts = [0; 8];
+ let mut value_counts = [0; 8];
+
+ let mut runner = TestRunner::deterministic();
+ let input = subsequence(VALUES, 3..7);
+
+ for _ in 0..2048 {
+ let value = input.new_tree(&mut runner).unwrap().current();
+ // Generated the correct number of items
+ assert!(value.len() >= 3 && value.len() < 7);
+ // Chose distinct items
+ assert_eq!(
+ value.len(),
+ value.iter().cloned().collect::<BTreeSet<_>>().len()
+ );
+ // Values are in correct order
+ let mut sorted = value.clone();
+ sorted.sort();
+ assert_eq!(sorted, value);
+
+ size_counts[value.len()] += 1;
+
+ for value in value {
+ value_counts[value] += 1;
+ }
+ }
+
+ for i in 3..7 {
+ assert!(
+ size_counts[i] >= 256 && size_counts[i] < 1024,
+ "size {} was chosen {} times",
+ i,
+ size_counts[i]
+ );
+ }
+
+ for (ix, &v) in value_counts.iter().enumerate() {
+ assert!(
+ v >= 1024 && v < 1500,
+ "Value {} was chosen {} times",
+ ix,
+ v
+ );
+ }
+ }
+
+ #[test]
+ fn sample_vec() {
+ // Just test that the types work out
+ let values = vec![0, 1, 2, 3, 4];
+
+ let mut runner = TestRunner::deterministic();
+ let input = subsequence(values, 1..3);
+
+ let _ = input.new_tree(&mut runner).unwrap().current();
+ }
+
+ #[test]
+ fn test_select() {
+ let values = vec![0, 1, 2, 3, 4, 5, 6, 7];
+ let mut counts = [0; 8];
+
+ let mut runner = TestRunner::deterministic();
+ let input = select(values);
+
+ for _ in 0..1024 {
+ counts[input.new_tree(&mut runner).unwrap().current()] += 1;
+ }
+
+ for (ix, &count) in counts.iter().enumerate() {
+ assert!(
+ count >= 64 && count < 256,
+ "Generated value {} {} times",
+ ix,
+ count
+ );
+ }
+ }
+
+ #[test]
+ fn test_sample_sanity() {
+ check_strategy_sanity(subsequence(vec![0, 1, 2, 3, 4], 1..3), None);
+ }
+
+ #[test]
+ fn test_select_sanity() {
+ check_strategy_sanity(select(vec![0, 1, 2, 3, 4]), None);
+ }
+
+ #[test]
+ fn subseq_empty_vec_works() {
+ let mut runner = TestRunner::deterministic();
+ let input = subsequence(Vec::<()>::new(), 0..1);
+ assert_eq!(
+ Vec::<()>::new(),
+ input.new_tree(&mut runner).unwrap().current()
+ );
+ }
+
+ #[test]
+ fn subseq_full_vec_works() {
+ let v = vec![1u32, 2u32, 3u32];
+ let mut runner = TestRunner::deterministic();
+ let input = subsequence(v.clone(), 3);
+ assert_eq!(v, input.new_tree(&mut runner).unwrap().current());
+ }
+
+ #[test]
+ fn index_works() {
+ let mut runner = TestRunner::deterministic();
+ let input = any::<Index>();
+ let col = vec!["foo", "bar", "baz"];
+ let mut seen = BTreeSet::new();
+
+ for _ in 0..16 {
+ let mut tree = input.new_tree(&mut runner).unwrap();
+ seen.insert(*tree.current().get(&col));
+
+ while tree.simplify() {}
+
+ assert_eq!("foo", *tree.current().get(&col));
+ }
+
+ assert_eq!(col.into_iter().collect::<BTreeSet<_>>(), seen);
+ }
+
+ #[test]
+ fn selector_works() {
+ let mut runner = TestRunner::deterministic();
+ let input = any::<Selector>();
+ let col: BTreeSet<&str> =
+ vec!["foo", "bar", "baz"].into_iter().collect();
+ let mut seen = BTreeSet::new();
+
+ for _ in 0..16 {
+ let mut tree = input.new_tree(&mut runner).unwrap();
+ seen.insert(*tree.current().select(&col));
+
+ while tree.simplify() {}
+
+ assert_eq!("bar", *tree.current().select(&col));
+ }
+
+ assert_eq!(col, seen);
+ }
+}
diff --git a/vendor/proptest/src/std_facade.rs b/vendor/proptest/src/std_facade.rs
new file mode 100644
index 000000000..2ccbe1550
--- /dev/null
+++ b/vendor/proptest/src/std_facade.rs
@@ -0,0 +1,74 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! This module provides #[cfg(..)]ed type aliases over features.
+
+macro_rules! multiplex_alloc {
+ ($($alloc: path, $std: path),*) => {
+ $(
+ #[cfg(all(feature = "alloc", not(feature = "std")))]
+ pub use $alloc;
+ #[cfg(feature = "std")]
+ pub use $std;
+ )*
+ };
+}
+
+macro_rules! multiplex_core {
+ ($($core: path, $std: path),*) => {
+ $(
+ #[cfg(not(feature = "std"))]
+ pub use $core;
+ #[cfg(feature = "std")]
+ pub use $std;
+ )*
+ };
+}
+
+multiplex_alloc! {
+ alloc::borrow::Cow, ::std::borrow::Cow,
+ alloc::borrow::ToOwned, ::std::borrow::ToOwned,
+ alloc::boxed::Box, ::std::boxed::Box,
+ alloc::string::String, ::std::string::String,
+ alloc::string, ::std::string,
+ alloc::sync::Arc, ::std::sync::Arc,
+ alloc::rc::Rc, ::std::rc::Rc,
+ alloc::vec::Vec, ::std::vec::Vec,
+ alloc::vec, ::std::vec,
+ alloc::collections::VecDeque, std::collections::VecDeque,
+ alloc::collections::vec_deque, std::collections::vec_deque,
+ alloc::collections::BinaryHeap, ::std::collections::BinaryHeap,
+ alloc::collections::binary_heap, ::std::collections::binary_heap,
+ alloc::collections::LinkedList, ::std::collections::LinkedList,
+ alloc::collections::linked_list, ::std::collections::linked_list,
+ alloc::collections::BTreeSet, ::std::collections::BTreeSet,
+ alloc::collections::BTreeMap, ::std::collections::BTreeMap,
+ alloc::collections::btree_map, ::std::collections::btree_map,
+ alloc::collections::btree_set, ::std::collections::btree_set
+}
+
+#[cfg(feature = "std")]
+multiplex_alloc! {
+ hashmap_core::HashMap, ::std::collections::HashMap,
+ hashmap_core::HashSet, ::std::collections::HashSet
+}
+
+//#[cfg(not(feature = "std"))]
+//pub(crate) use hashmap_core::map as hash_map;
+#[cfg(feature = "std")]
+pub use ::std::collections::hash_map;
+//#[cfg(not(feature = "std"))]
+//pub(crate) use hashmap_core::set as hash_set;
+#[cfg(feature = "std")]
+pub use ::std::collections::hash_set;
+
+multiplex_core! {
+ core::fmt, ::std::fmt,
+ core::cell::Cell, ::std::cell::Cell
+}
diff --git a/vendor/proptest/src/strategy/filter.rs b/vendor/proptest/src/strategy/filter.rs
new file mode 100644
index 000000000..029dbcebc
--- /dev/null
+++ b/vendor/proptest/src/strategy/filter.rs
@@ -0,0 +1,147 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+use crate::std_facade::{fmt, Arc};
+
+use crate::strategy::traits::*;
+use crate::test_runner::*;
+
+/// `Strategy` and `ValueTree` filter adaptor.
+///
+/// See `Strategy::prop_filter()`.
+#[must_use = "strategies do nothing unless used"]
+pub struct Filter<S, F> {
+ pub(super) source: S,
+ pub(super) whence: Reason,
+ pub(super) fun: Arc<F>,
+}
+
+impl<S, F> Filter<S, F> {
+ pub(super) fn new(source: S, whence: Reason, fun: F) -> Self {
+ Self {
+ source,
+ whence,
+ fun: Arc::new(fun),
+ }
+ }
+}
+
+impl<S: fmt::Debug, F> fmt::Debug for Filter<S, F> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Filter")
+ .field("source", &self.source)
+ .field("whence", &self.whence)
+ .field("fun", &"<function>")
+ .finish()
+ }
+}
+
+impl<S: Clone, F> Clone for Filter<S, F> {
+ fn clone(&self) -> Self {
+ Filter {
+ source: self.source.clone(),
+ whence: "unused".into(),
+ fun: Arc::clone(&self.fun),
+ }
+ }
+}
+
+impl<S: Strategy, F: Fn(&S::Value) -> bool> Strategy for Filter<S, F> {
+ type Tree = Filter<S::Tree, F>;
+ type Value = S::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ loop {
+ let val = self.source.new_tree(runner)?;
+ if !(self.fun)(&val.current()) {
+ runner.reject_local(self.whence.clone())?;
+ } else {
+ return Ok(Filter {
+ source: val,
+ whence: self.whence.clone(),
+ fun: Arc::clone(&self.fun),
+ });
+ }
+ }
+ }
+}
+
+impl<S: ValueTree, F: Fn(&S::Value) -> bool> Filter<S, F> {
+ fn ensure_acceptable(&mut self) {
+ while !(self.fun)(&self.source.current()) {
+ if !self.source.complicate() {
+ panic!(
+ "Unable to complicate filtered strategy \
+ back into acceptable value"
+ );
+ }
+ }
+ }
+}
+
+impl<S: ValueTree, F: Fn(&S::Value) -> bool> ValueTree for Filter<S, F> {
+ type Value = S::Value;
+
+ fn current(&self) -> S::Value {
+ self.source.current()
+ }
+
+ fn simplify(&mut self) -> bool {
+ if self.source.simplify() {
+ self.ensure_acceptable();
+ true
+ } else {
+ false
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ if self.source.complicate() {
+ self.ensure_acceptable();
+ true
+ } else {
+ false
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_filter() {
+ let input = (0..256).prop_filter("%3", |&v| 0 == v % 3);
+
+ for _ in 0..256 {
+ let mut runner = TestRunner::default();
+ let mut case = input.new_tree(&mut runner).unwrap();
+
+ assert!(0 == case.current() % 3);
+
+ while case.simplify() {
+ assert!(0 == case.current() % 3);
+ }
+ assert!(0 == case.current() % 3);
+ }
+ }
+
+ #[test]
+ fn test_filter_sanity() {
+ check_strategy_sanity(
+ (0..256).prop_filter("!%5", |&v| 0 != v % 5),
+ Some(CheckStrategySanityOptions {
+ // Due to internal rejection sampling, `simplify()` can
+ // converge back to what `complicate()` would do.
+ strict_complicate_after_simplify: false,
+ ..CheckStrategySanityOptions::default()
+ }),
+ );
+ }
+}
diff --git a/vendor/proptest/src/strategy/filter_map.rs b/vendor/proptest/src/strategy/filter_map.rs
new file mode 100644
index 000000000..52f901276
--- /dev/null
+++ b/vendor/proptest/src/strategy/filter_map.rs
@@ -0,0 +1,209 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+use crate::std_facade::{fmt, Arc, Cell};
+
+use crate::strategy::traits::*;
+use crate::test_runner::*;
+
+/// `Strategy` and `ValueTree` filter_map adaptor.
+///
+/// See `Strategy::prop_filter_map()`.
+#[must_use = "strategies do nothing unless used"]
+pub struct FilterMap<S, F> {
+ pub(super) source: S,
+ pub(super) whence: Reason,
+ pub(super) fun: Arc<F>,
+}
+
+impl<S, F> FilterMap<S, F> {
+ pub(super) fn new(source: S, whence: Reason, fun: F) -> Self {
+ Self {
+ source,
+ whence,
+ fun: Arc::new(fun),
+ }
+ }
+}
+
+impl<S: fmt::Debug, F> fmt::Debug for FilterMap<S, F> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("FilterMap")
+ .field("source", &self.source)
+ .field("whence", &self.whence)
+ .field("fun", &"<function>")
+ .finish()
+ }
+}
+
+impl<S: Clone, F> Clone for FilterMap<S, F> {
+ fn clone(&self) -> Self {
+ Self {
+ source: self.source.clone(),
+ whence: self.whence.clone(),
+ fun: Arc::clone(&self.fun),
+ }
+ }
+}
+
+impl<S: Strategy, F: Fn(S::Value) -> Option<O>, O: fmt::Debug> Strategy
+ for FilterMap<S, F>
+{
+ type Tree = FilterMapValueTree<S::Tree, F, O>;
+ type Value = O;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ loop {
+ let val = self.source.new_tree(runner)?;
+ if let Some(current) = (self.fun)(val.current()) {
+ return Ok(FilterMapValueTree::new(val, &self.fun, current));
+ } else {
+ runner.reject_local(self.whence.clone())?;
+ }
+ }
+ }
+}
+
+/// `ValueTree` corresponding to `FilterMap`.
+pub struct FilterMapValueTree<V, F, O> {
+ source: V,
+ current: Cell<Option<O>>,
+ fun: Arc<F>,
+}
+
+impl<V: Clone + ValueTree, F: Fn(V::Value) -> Option<O>, O> Clone
+ for FilterMapValueTree<V, F, O>
+{
+ fn clone(&self) -> Self {
+ Self::new(self.source.clone(), &self.fun, self.fresh_current())
+ }
+}
+
+impl<V: fmt::Debug, F, O> fmt::Debug for FilterMapValueTree<V, F, O> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("FilterMapValueTree")
+ .field("source", &self.source)
+ .field("current", &"<current>")
+ .field("fun", &"<function>")
+ .finish()
+ }
+}
+
+impl<V: ValueTree, F: Fn(V::Value) -> Option<O>, O>
+ FilterMapValueTree<V, F, O>
+{
+ fn new(source: V, fun: &Arc<F>, current: O) -> Self {
+ Self {
+ source,
+ current: Cell::new(Some(current)),
+ fun: Arc::clone(fun),
+ }
+ }
+
+ fn fresh_current(&self) -> O {
+ (self.fun)(self.source.current())
+ .expect("internal logic error; this is a bug!")
+ }
+
+ fn ensure_acceptable(&mut self) {
+ loop {
+ if let Some(current) = (self.fun)(self.source.current()) {
+ // Found an acceptable element!
+ self.current = Cell::new(Some(current));
+ break;
+ } else if !self.source.complicate() {
+ panic!(
+ "Unable to complicate filtered strategy \
+ back into acceptable value"
+ );
+ }
+ }
+ }
+}
+
+impl<V: ValueTree, F: Fn(V::Value) -> Option<O>, O: fmt::Debug> ValueTree
+ for FilterMapValueTree<V, F, O>
+{
+ type Value = O;
+
+ fn current(&self) -> O {
+ // Optimization: we avoid the else branch in most success cases
+ // thereby avoiding to call the closure and the source tree.
+ if let Some(current) = self.current.replace(None) {
+ current
+ } else {
+ self.fresh_current()
+ }
+ }
+
+ fn simplify(&mut self) -> bool {
+ if self.source.simplify() {
+ self.ensure_acceptable();
+ true
+ } else {
+ false
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ if self.source.complicate() {
+ self.ensure_acceptable();
+ true
+ } else {
+ false
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_filter_map() {
+ let input = (0..256).prop_filter_map("%3 + 1", |v| {
+ if 0 == v % 3 {
+ Some(v + 1)
+ } else {
+ None
+ }
+ });
+
+ for _ in 0..256 {
+ let mut runner = TestRunner::default();
+ let mut case = input.new_tree(&mut runner).unwrap();
+
+ assert_eq!(0, (case.current() - 1) % 3);
+
+ while case.simplify() {
+ assert_eq!(0, (case.current() - 1) % 3);
+ }
+ assert_eq!(0, (case.current() - 1) % 3);
+ }
+ }
+
+ #[test]
+ fn test_filter_map_sanity() {
+ check_strategy_sanity(
+ (0..256).prop_filter_map("!%5 * 2", |v| {
+ if 0 != v % 5 {
+ Some(v * 2)
+ } else {
+ None
+ }
+ }),
+ Some(CheckStrategySanityOptions {
+ // Due to internal rejection sampling, `simplify()` can
+ // converge back to what `complicate()` would do.
+ strict_complicate_after_simplify: false,
+ ..CheckStrategySanityOptions::default()
+ }),
+ );
+ }
+}
diff --git a/vendor/proptest/src/strategy/flatten.rs b/vendor/proptest/src/strategy/flatten.rs
new file mode 100644
index 000000000..63ac41604
--- /dev/null
+++ b/vendor/proptest/src/strategy/flatten.rs
@@ -0,0 +1,359 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+use crate::std_facade::{fmt, Arc};
+use core::mem;
+
+use crate::strategy::fuse::Fuse;
+use crate::strategy::traits::*;
+use crate::test_runner::*;
+
+/// Adaptor that flattens a `Strategy` which produces other `Strategy`s into a
+/// `Strategy` that picks one of those strategies and then picks values from
+/// it.
+#[derive(Debug, Clone, Copy)]
+#[must_use = "strategies do nothing unless used"]
+pub struct Flatten<S> {
+ source: S,
+}
+
+impl<S: Strategy> Flatten<S> {
+ /// Wrap `source` to flatten it.
+ pub fn new(source: S) -> Self {
+ Flatten { source }
+ }
+}
+
+impl<S: Strategy> Strategy for Flatten<S>
+where
+ S::Value: Strategy,
+{
+ type Tree = FlattenValueTree<S::Tree>;
+ type Value = <S::Value as Strategy>::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let meta = self.source.new_tree(runner)?;
+ FlattenValueTree::new(runner, meta)
+ }
+}
+
+/// The `ValueTree` produced by `Flatten`.
+pub struct FlattenValueTree<S: ValueTree>
+where
+ S::Value: Strategy,
+{
+ meta: Fuse<S>,
+ current: Fuse<<S::Value as Strategy>::Tree>,
+ // The final value to produce after successive calls to complicate() on the
+ // underlying objects return false.
+ final_complication: Option<Fuse<<S::Value as Strategy>::Tree>>,
+ // When `simplify()` or `complicate()` causes a new `Strategy` to be
+ // chosen, we need to find a new failing input for that case. To do this,
+ // we implement `complicate()` by regenerating values up to a number of
+ // times corresponding to the maximum number of test cases. A `simplify()`
+ // which does not cause a new strategy to be chosen always resets
+ // `complicate_regen_remaining` to 0.
+ //
+ // This does unfortunately depart from the direct interpretation of
+ // simplify/complicate as binary search, but is still easier to think about
+ // than other implementations of higher-order strategies.
+ runner: TestRunner,
+ complicate_regen_remaining: u32,
+}
+
+impl<S: ValueTree> Clone for FlattenValueTree<S>
+where
+ S::Value: Strategy + Clone,
+ S: Clone,
+ <S::Value as Strategy>::Tree: Clone,
+{
+ fn clone(&self) -> Self {
+ FlattenValueTree {
+ meta: self.meta.clone(),
+ current: self.current.clone(),
+ final_complication: self.final_complication.clone(),
+ runner: self.runner.clone(),
+ complicate_regen_remaining: self.complicate_regen_remaining,
+ }
+ }
+}
+
+impl<S: ValueTree> fmt::Debug for FlattenValueTree<S>
+where
+ S::Value: Strategy,
+ S: fmt::Debug,
+ <S::Value as Strategy>::Tree: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("FlattenValueTree")
+ .field("meta", &self.meta)
+ .field("current", &self.current)
+ .field("final_complication", &self.final_complication)
+ .field(
+ "complicate_regen_remaining",
+ &self.complicate_regen_remaining,
+ )
+ .finish()
+ }
+}
+
+impl<S: ValueTree> FlattenValueTree<S>
+where
+ S::Value: Strategy,
+{
+ fn new(runner: &mut TestRunner, meta: S) -> Result<Self, Reason> {
+ let current = meta.current().new_tree(runner)?;
+ Ok(FlattenValueTree {
+ meta: Fuse::new(meta),
+ current: Fuse::new(current),
+ final_complication: None,
+ runner: runner.partial_clone(),
+ complicate_regen_remaining: 0,
+ })
+ }
+}
+
+impl<S: ValueTree> ValueTree for FlattenValueTree<S>
+where
+ S::Value: Strategy,
+{
+ type Value = <S::Value as Strategy>::Value;
+
+ fn current(&self) -> Self::Value {
+ self.current.current()
+ }
+
+ fn simplify(&mut self) -> bool {
+ self.complicate_regen_remaining = 0;
+
+ if self.current.simplify() {
+ // Now that we've simplified the derivative value, we can't
+ // re-complicate the meta value unless it gets simplified again.
+ // We also mustn't complicate back to whatever's in
+ // `final_complication` since the new state of `self.current` is
+ // the most complicated state.
+ self.meta.disallow_complicate();
+ self.final_complication = None;
+ true
+ } else if !self.meta.simplify() {
+ false
+ } else if let Ok(v) = self.meta.current().new_tree(&mut self.runner) {
+ // Shift current into final_complication and `v` into
+ // `current`. We also need to prevent that value from
+ // complicating beyond the current point in the future
+ // since we're going to return `true` from `simplify()`
+ // ourselves.
+ self.current.disallow_complicate();
+ self.final_complication = Some(Fuse::new(v));
+ mem::swap(
+ self.final_complication.as_mut().unwrap(),
+ &mut self.current,
+ );
+ // Initially complicate by regenerating the chosen value.
+ self.complicate_regen_remaining = self.runner.config().cases;
+ true
+ } else {
+ false
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ if self.complicate_regen_remaining > 0 {
+ if self.runner.flat_map_regen() {
+ self.complicate_regen_remaining -= 1;
+
+ if let Ok(v) = self.meta.current().new_tree(&mut self.runner) {
+ self.current = Fuse::new(v);
+ return true;
+ }
+ } else {
+ self.complicate_regen_remaining = 0;
+ }
+ }
+
+ if self.current.complicate() {
+ return true;
+ } else if self.meta.complicate() {
+ if let Ok(v) = self.meta.current().new_tree(&mut self.runner) {
+ self.complicate_regen_remaining = self.runner.config().cases;
+ self.current = Fuse::new(v);
+ return true;
+ }
+ }
+
+ if let Some(v) = self.final_complication.take() {
+ self.current = v;
+ true
+ } else {
+ false
+ }
+ }
+}
+
+/// Similar to `Flatten`, but does not shrink the input strategy.
+///
+/// See `Strategy::prop_ind_flat_map()` fore more details.
+#[derive(Clone, Copy, Debug)]
+pub struct IndFlatten<S>(pub(super) S);
+
+impl<S: Strategy> Strategy for IndFlatten<S>
+where
+ S::Value: Strategy,
+{
+ type Tree = <S::Value as Strategy>::Tree;
+ type Value = <S::Value as Strategy>::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let inner = self.0.new_tree(runner)?;
+ inner.current().new_tree(runner)
+ }
+}
+
+/// Similar to `Map` plus `Flatten`, but does not shrink the input strategy and
+/// passes the original input through.
+///
+/// See `Strategy::prop_ind_flat_map2()` for more details.
+pub struct IndFlattenMap<S, F> {
+ pub(super) source: S,
+ pub(super) fun: Arc<F>,
+}
+
+impl<S: fmt::Debug, F> fmt::Debug for IndFlattenMap<S, F> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("IndFlattenMap")
+ .field("source", &self.source)
+ .field("fun", &"<function>")
+ .finish()
+ }
+}
+
+impl<S: Clone, F> Clone for IndFlattenMap<S, F> {
+ fn clone(&self) -> Self {
+ IndFlattenMap {
+ source: self.source.clone(),
+ fun: Arc::clone(&self.fun),
+ }
+ }
+}
+
+impl<S: Strategy, R: Strategy, F: Fn(S::Value) -> R> Strategy
+ for IndFlattenMap<S, F>
+{
+ type Tree = crate::tuple::TupleValueTree<(S::Tree, R::Tree)>;
+ type Value = (S::Value, R::Value);
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let left = self.source.new_tree(runner)?;
+ let right_source = (self.fun)(left.current());
+ let right = right_source.new_tree(runner)?;
+
+ Ok(crate::tuple::TupleValueTree::new((left, right)))
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ use std::u32;
+
+ use crate::strategy::just::Just;
+ use crate::test_runner::Config;
+
+ #[test]
+ fn test_flat_map() {
+ // Pick random integer A, then random integer B which is ±5 of A and
+ // assert that B <= A if A > 10000. Shrinking should always converge to
+ // A=10001, B=10002.
+ let input = (0..65536).prop_flat_map(|a| (Just(a), (a - 5..a + 5)));
+
+ let mut failures = 0;
+ let mut runner = TestRunner::new_with_rng(
+ Config {
+ max_shrink_iters: u32::MAX - 1,
+ ..Config::default()
+ },
+ TestRng::deterministic_rng(RngAlgorithm::default()),
+ );
+ for _ in 0..1000 {
+ let case = input.new_tree(&mut runner).unwrap();
+ let result = runner.run_one(case, |(a, b)| {
+ if a <= 10000 || b <= a {
+ Ok(())
+ } else {
+ Err(TestCaseError::fail("fail"))
+ }
+ });
+
+ match result {
+ Ok(_) => {}
+ Err(TestError::Fail(_, v)) => {
+ failures += 1;
+ assert_eq!((10001, 10002), v);
+ }
+ result => panic!("Unexpected result: {:?}", result),
+ }
+ }
+
+ assert!(failures > 250);
+ }
+
+ #[test]
+ fn test_flat_map_sanity() {
+ check_strategy_sanity(
+ (0..65536).prop_flat_map(|a| (Just(a), (a - 5..a + 5))),
+ None,
+ );
+ }
+
+ #[test]
+ fn flat_map_respects_regen_limit() {
+ use std::sync::atomic::{AtomicBool, Ordering};
+
+ let input = (0..65536)
+ .prop_flat_map(|_| 0..65536)
+ .prop_flat_map(|_| 0..65536)
+ .prop_flat_map(|_| 0..65536)
+ .prop_flat_map(|_| 0..65536)
+ .prop_flat_map(|_| 0..65536);
+
+ // Arteficially make the first case fail and all others pass, so that
+ // the regeneration logic futilely searches for another failing
+ // example and eventually gives up. Unfortunately, the test is sort of
+ // semi-decidable; if the limit *doesn't* work, the test just runs
+ // almost forever.
+ let pass = AtomicBool::new(false);
+ let mut runner = TestRunner::new(Config {
+ max_flat_map_regens: 1000,
+ ..Config::default()
+ });
+ let case = input.new_tree(&mut runner).unwrap();
+ let _ = runner.run_one(case, |_| {
+ // Only the first run fails, all others succeed
+ prop_assert!(pass.fetch_or(true, Ordering::SeqCst));
+ Ok(())
+ });
+ }
+
+ #[test]
+ fn test_ind_flat_map_sanity() {
+ check_strategy_sanity(
+ (0..65536).prop_ind_flat_map(|a| (Just(a), (a - 5..a + 5))),
+ None,
+ );
+ }
+
+ #[test]
+ fn test_ind_flat_map2_sanity() {
+ check_strategy_sanity(
+ (0..65536).prop_ind_flat_map2(|a| a - 5..a + 5),
+ None,
+ );
+ }
+}
diff --git a/vendor/proptest/src/strategy/fuse.rs b/vendor/proptest/src/strategy/fuse.rs
new file mode 100644
index 000000000..5c0f9a374
--- /dev/null
+++ b/vendor/proptest/src/strategy/fuse.rs
@@ -0,0 +1,228 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+use crate::strategy::*;
+use crate::test_runner::*;
+
+/// Adaptor for `Strategy` and `ValueTree` which guards `simplify()` and
+/// `complicate()` to avoid contract violations.
+///
+/// This can be used as an intermediate when the caller would otherwise need
+/// its own separate state tracking, or as a workaround for a broken
+/// `ValueTree` implementation.
+///
+/// This wrapper specifically has the following effects:
+///
+/// - Calling `complicate()` before `simplify()` was ever called does nothing
+/// and returns `false`.
+///
+/// - Calling `simplify()` after it has returned `false` and no calls to
+/// `complicate()` returned `true` does nothing and returns `false`.
+///
+/// - Calling `complicate()` after it has returned `false` and no calls to
+/// `simplify()` returned `true` does nothing and returns `false`.
+///
+/// There is also limited functionality to alter the internal state to assist
+/// in its usage as a state tracker.
+///
+/// Wrapping a `Strategy` in `Fuse` simply causes its `ValueTree` to also be
+/// wrapped in `Fuse`.
+///
+/// While this is similar to `std::iter::Fuse`, it is not exposed as a method
+/// on `Strategy` since the vast majority of proptest should never need this
+/// functionality; it mainly concerns implementors of strategies.
+#[derive(Debug, Clone, Copy)]
+#[must_use = "strategies do nothing unless used"]
+pub struct Fuse<T> {
+ inner: T,
+ may_simplify: bool,
+ may_complicate: bool,
+}
+
+impl<T> Fuse<T> {
+ /// Wrap the given `T` in `Fuse`.
+ pub fn new(inner: T) -> Self {
+ Fuse {
+ inner,
+ may_simplify: true,
+ may_complicate: false,
+ }
+ }
+}
+
+impl<T: Strategy> Strategy for Fuse<T> {
+ type Tree = Fuse<T::Tree>;
+ type Value = T::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ self.inner.new_tree(runner).map(Fuse::new)
+ }
+}
+
+impl<T: ValueTree> Fuse<T> {
+ /// Return whether a call to `simplify()` may be productive.
+ ///
+ /// Formally, this is true if one of the following holds:
+ ///
+ /// - `simplify()` has never been called.
+ /// - The most recent call to `simplify()` returned `true`.
+ /// - `complicate()` has been called more recently than `simplify()` and
+ /// the last call returned `true`.
+ pub fn may_simplify(&self) -> bool {
+ self.may_simplify
+ }
+
+ /// Disallow any further calls to `simplify()` until a call to
+ /// `complicate()` returns `true`.
+ pub fn disallow_simplify(&mut self) {
+ self.may_simplify = false;
+ }
+
+ /// Return whether a call to `complicate()` may be productive.
+ ///
+ /// Formally, this is true if one of the following holds:
+ ///
+ /// - The most recent call to `complicate()` returned `true`.
+ /// - `simplify()` has been called more recently than `complicate()` and
+ /// the last call returned `true`.
+ pub fn may_complicate(&self) -> bool {
+ self.may_complicate
+ }
+
+ /// Disallow any further calls to `complicate()` until a call to
+ /// `simplify()` returns `true`.
+ pub fn disallow_complicate(&mut self) {
+ self.may_complicate = false;
+ }
+
+ /// Prevent any further shrinking operations from occurring.
+ pub fn freeze(&mut self) {
+ self.disallow_simplify();
+ self.disallow_complicate();
+ }
+}
+
+impl<T: ValueTree> ValueTree for Fuse<T> {
+ type Value = T::Value;
+
+ fn current(&self) -> T::Value {
+ self.inner.current()
+ }
+
+ fn simplify(&mut self) -> bool {
+ if self.may_simplify {
+ if self.inner.simplify() {
+ self.may_complicate = true;
+ true
+ } else {
+ self.may_simplify = false;
+ false
+ }
+ } else {
+ false
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ if self.may_complicate {
+ if self.inner.complicate() {
+ self.may_simplify = true;
+ true
+ } else {
+ self.may_complicate = false;
+ false
+ }
+ } else {
+ false
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ struct StrictValueTree {
+ min: u32,
+ curr: u32,
+ max: u32,
+ ready: bool,
+ }
+
+ impl StrictValueTree {
+ fn new(start: u32) -> Self {
+ StrictValueTree {
+ min: 0,
+ curr: start,
+ max: start,
+ ready: false,
+ }
+ }
+ }
+
+ impl ValueTree for StrictValueTree {
+ type Value = u32;
+
+ fn current(&self) -> u32 {
+ self.curr
+ }
+
+ fn simplify(&mut self) -> bool {
+ assert!(self.min <= self.curr);
+ if self.curr > self.min {
+ self.max = self.curr;
+ self.curr -= 1;
+ self.ready = true;
+ true
+ } else {
+ self.min += 1;
+ false
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ assert!(self.max >= self.curr);
+ assert!(self.ready);
+ if self.curr < self.max {
+ self.curr += 1;
+ true
+ } else {
+ self.max -= 1;
+ false
+ }
+ }
+ }
+
+ #[test]
+ fn test_sanity() {
+ check_strategy_sanity(Fuse::new(0i32..100i32), None);
+ }
+
+ #[test]
+ fn guards_bad_transitions() {
+ let mut vt = Fuse::new(StrictValueTree::new(5));
+ assert!(!vt.complicate());
+ assert_eq!(5, vt.current());
+
+ assert!(vt.simplify()); // 0, 4, 5
+ assert!(vt.simplify()); // 0, 3, 4
+ assert!(vt.simplify()); // 0, 2, 3
+ assert!(vt.simplify()); // 0, 1, 2
+ assert!(vt.simplify()); // 0, 0, 1
+ assert_eq!(0, vt.current());
+ assert!(!vt.simplify()); // 1, 0, 1
+ assert!(!vt.simplify()); // 1, 0, 1
+ assert_eq!(0, vt.current());
+ assert!(vt.complicate()); // 1, 1, 1
+ assert_eq!(1, vt.current());
+ assert!(!vt.complicate()); // 1, 1, 0
+ assert!(!vt.complicate()); // 1, 1, 0
+ assert_eq!(1, vt.current());
+ }
+}
diff --git a/vendor/proptest/src/strategy/just.rs b/vendor/proptest/src/strategy/just.rs
new file mode 100644
index 000000000..a141f8a17
--- /dev/null
+++ b/vendor/proptest/src/strategy/just.rs
@@ -0,0 +1,145 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+use crate::std_facade::fmt;
+
+use crate::strategy::{NewTree, Strategy, ValueTree};
+use crate::test_runner::TestRunner;
+
+macro_rules! noshrink {
+ () => {
+ fn simplify(&mut self) -> bool {
+ false
+ }
+ fn complicate(&mut self) -> bool {
+ false
+ }
+ };
+}
+
+//==============================================================================
+// Just
+//==============================================================================
+
+/// A `Strategy` which always produces a single value value and never
+/// simplifies.
+#[derive(Clone, Copy, Debug)]
+#[must_use = "strategies do nothing unless used"]
+pub struct Just<T: Clone + fmt::Debug>(
+ /// The value produced by this strategy.
+ pub T,
+);
+
+impl<T: Clone + fmt::Debug> Strategy for Just<T> {
+ type Tree = Self;
+ type Value = T;
+
+ fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
+ Ok(self.clone())
+ }
+}
+
+impl<T: Clone + fmt::Debug> ValueTree for Just<T> {
+ type Value = T;
+ noshrink!();
+ fn current(&self) -> T {
+ self.0.clone()
+ }
+}
+
+//==============================================================================
+// LazyJust
+//==============================================================================
+
+/// A `Strategy` which always produces a single value value and never
+/// simplifies. If `T` is `Clone`, you should use `Just` instead.
+///
+/// This is a generalization of `Just` and works by calling
+/// the provided `Fn () -> T` in `.current()` every time. This is not a
+/// very interesting strategy, but is required in cases where `T` is
+/// not `Clone`. It is also used in `proptest_derive` where we can't
+/// assume that your type is `Clone`.
+///
+/// **It is important that the function used be pure.**
+#[must_use = "strategies do nothing unless used"]
+pub struct LazyJust<T, F: Fn() -> T> {
+ /// The function executed in `.current()`.
+ function: F,
+}
+
+/// Shorthand for `LazyJust<T, fn () -> T>`.
+pub type LazyJustFn<V> = LazyJust<V, fn() -> V>;
+
+impl<T, F: Fn() -> T> LazyJust<T, F> {
+ /// Constructs a `LazyJust` strategy given the function/closure
+ /// that produces the value.
+ ///
+ /// **It is important that the function used be pure.**
+ pub fn new(function: F) -> Self {
+ Self { function }
+ }
+}
+
+impl<T: fmt::Debug, F: Clone + Fn() -> T> Strategy for LazyJust<T, F> {
+ type Tree = Self;
+ type Value = T;
+
+ fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
+ Ok(self.clone())
+ }
+}
+
+impl<T: fmt::Debug, F: Fn() -> T> ValueTree for LazyJust<T, F> {
+ type Value = T;
+ noshrink!();
+ fn current(&self) -> Self::Value {
+ (self.function)()
+ }
+}
+
+impl<T, F: Copy + Fn() -> T> Copy for LazyJust<T, F> {}
+
+impl<T, F: Clone + Fn() -> T> Clone for LazyJust<T, F> {
+ fn clone(&self) -> Self {
+ Self {
+ function: self.function.clone(),
+ }
+ }
+}
+
+impl<T, F: Fn() -> T> fmt::Debug for LazyJust<T, F> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("LazyJust")
+ .field("function", &"<function>")
+ .finish()
+ }
+}
+
+//==============================================================================
+// Any `fn () -> T` is a Strategy
+//==============================================================================
+
+// TODO: try 'F: Fn () -> T' instead when we've got specialization.
+
+impl<T: fmt::Debug> Strategy for fn() -> T {
+ type Tree = Self;
+ type Value = T;
+
+ fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> {
+ Ok(*self)
+ }
+}
+
+impl<T: fmt::Debug> ValueTree for fn() -> T {
+ type Value = T;
+ noshrink!();
+ fn current(&self) -> Self::Value {
+ self()
+ }
+}
diff --git a/vendor/proptest/src/strategy/lazy.rs b/vendor/proptest/src/strategy/lazy.rs
new file mode 100644
index 000000000..cb95a7492
--- /dev/null
+++ b/vendor/proptest/src/strategy/lazy.rs
@@ -0,0 +1,175 @@
+//-
+// Copyright 2019 The proptest 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.
+
+use crate::std_facade::{fmt, Arc};
+use core::mem;
+
+use crate::strategy::traits::*;
+use crate::test_runner::*;
+
+/// Represents a value tree that is initialized on the first call to any
+/// methods.
+///
+/// This is used to defer potentially expensive generation to shrinking time. It
+/// is public only to allow APIs to expose it as an intermediate value.
+pub struct LazyValueTree<S: Strategy> {
+ state: LazyValueTreeState<S>,
+}
+
+enum LazyValueTreeState<S: Strategy> {
+ Initialized(S::Tree),
+ Uninitialized {
+ strategy: Arc<S>,
+ runner: TestRunner,
+ },
+ Failed,
+}
+
+impl<S: Strategy> LazyValueTree<S> {
+ /// Create a new value tree where initial generation is deferred until
+ /// `maybe_init` is called.
+ pub(crate) fn new(strategy: Arc<S>, runner: &mut TestRunner) -> Self {
+ let runner = runner.partial_clone();
+ Self {
+ state: LazyValueTreeState::Uninitialized { strategy, runner },
+ }
+ }
+
+ /// Create a new value tree that has already been initialized.
+ pub(crate) fn new_initialized(value_tree: S::Tree) -> Self {
+ Self {
+ state: LazyValueTreeState::Initialized(value_tree),
+ }
+ }
+
+ /// Returns a reference to the inner value tree if initialized.
+ pub(crate) fn as_inner(&self) -> Option<&S::Tree> {
+ match &self.state {
+ LazyValueTreeState::Initialized(v) => Some(v),
+ LazyValueTreeState::Uninitialized { .. }
+ | LazyValueTreeState::Failed => None,
+ }
+ }
+
+ /// Returns a mutable reference to the inner value tree if uninitialized.
+ pub(crate) fn as_inner_mut(&mut self) -> Option<&mut S::Tree> {
+ match &mut self.state {
+ LazyValueTreeState::Initialized(v) => Some(v),
+ LazyValueTreeState::Uninitialized { .. }
+ | LazyValueTreeState::Failed => None,
+ }
+ }
+
+ /// Try initializing the value tree.
+ pub(crate) fn maybe_init(&mut self) {
+ if !self.is_uninitialized() {
+ return;
+ }
+
+ let state = mem::replace(&mut self.state, LazyValueTreeState::Failed);
+ match state {
+ LazyValueTreeState::Uninitialized {
+ strategy,
+ mut runner,
+ } => {
+ match strategy.new_tree(&mut runner) {
+ Ok(v) => {
+ let _ = mem::replace(
+ &mut self.state,
+ LazyValueTreeState::Initialized(v),
+ );
+ }
+ Err(_) => {
+ // self.state is set to Failed above. Keep it that way.
+ }
+ }
+ }
+ LazyValueTreeState::Initialized(_) | LazyValueTreeState::Failed => {
+ unreachable!("can only reach here if uninitialized")
+ }
+ }
+ }
+
+ /// Whether this value tree still needs to be initialized.
+ pub(crate) fn is_uninitialized(&self) -> bool {
+ match &self.state {
+ LazyValueTreeState::Uninitialized { .. } => true,
+ LazyValueTreeState::Initialized(_) | LazyValueTreeState::Failed => {
+ false
+ }
+ }
+ }
+
+ /// Whether the value tree was successfully initialized.
+ pub(crate) fn is_initialized(&self) -> bool {
+ match &self.state {
+ LazyValueTreeState::Initialized(_) => true,
+ LazyValueTreeState::Uninitialized { .. }
+ | LazyValueTreeState::Failed => false,
+ }
+ }
+}
+
+impl<S: Strategy> Clone for LazyValueTree<S>
+where
+ S::Tree: Clone,
+{
+ fn clone(&self) -> Self {
+ Self {
+ state: self.state.clone(),
+ }
+ }
+}
+
+impl<S: Strategy> fmt::Debug for LazyValueTree<S>
+where
+ S::Tree: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("LazyValueTree")
+ .field("state", &self.state)
+ .finish()
+ }
+}
+
+impl<S: Strategy> Clone for LazyValueTreeState<S>
+where
+ S::Tree: Clone,
+{
+ fn clone(&self) -> Self {
+ use LazyValueTreeState::*;
+
+ match self {
+ Initialized(v) => Initialized(v.clone()),
+ Uninitialized { strategy, runner } => Uninitialized {
+ strategy: Arc::clone(strategy),
+ runner: runner.clone(),
+ },
+ Failed => Failed,
+ }
+ }
+}
+
+impl<S: Strategy> fmt::Debug for LazyValueTreeState<S>
+where
+ S::Tree: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ LazyValueTreeState::Initialized(value_tree) => {
+ f.debug_tuple("Initialized").field(value_tree).finish()
+ }
+ LazyValueTreeState::Uninitialized { strategy, .. } => f
+ .debug_struct("Uninitialized")
+ .field("strategy", strategy)
+ .finish(),
+ LazyValueTreeState::Failed => write!(f, "Failed"),
+ }
+ }
+}
diff --git a/vendor/proptest/src/strategy/map.rs b/vendor/proptest/src/strategy/map.rs
new file mode 100644
index 000000000..464b99819
--- /dev/null
+++ b/vendor/proptest/src/strategy/map.rs
@@ -0,0 +1,301 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+use crate::std_facade::Arc;
+use core::fmt;
+use core::marker::PhantomData;
+
+use crate::strategy::traits::*;
+use crate::test_runner::*;
+
+//==============================================================================
+// Map
+//==============================================================================
+
+/// `Strategy` and `ValueTree` map adaptor.
+///
+/// See `Strategy::prop_map()`.
+#[must_use = "strategies do nothing unless used"]
+pub struct Map<S, F> {
+ pub(super) source: S,
+ pub(super) fun: Arc<F>,
+}
+
+impl<S: fmt::Debug, F> fmt::Debug for Map<S, F> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Map")
+ .field("source", &self.source)
+ .field("fun", &"<function>")
+ .finish()
+ }
+}
+
+impl<S: Clone, F> Clone for Map<S, F> {
+ fn clone(&self) -> Self {
+ Map {
+ source: self.source.clone(),
+ fun: Arc::clone(&self.fun),
+ }
+ }
+}
+
+impl<S: Strategy, O: fmt::Debug, F: Fn(S::Value) -> O> Strategy for Map<S, F> {
+ type Tree = Map<S::Tree, F>;
+ type Value = O;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ self.source.new_tree(runner).map(|v| Map {
+ source: v,
+ fun: Arc::clone(&self.fun),
+ })
+ }
+}
+
+impl<S: ValueTree, O: fmt::Debug, F: Fn(S::Value) -> O> ValueTree
+ for Map<S, F>
+{
+ type Value = O;
+
+ fn current(&self) -> O {
+ (self.fun)(self.source.current())
+ }
+
+ fn simplify(&mut self) -> bool {
+ self.source.simplify()
+ }
+
+ fn complicate(&mut self) -> bool {
+ self.source.complicate()
+ }
+}
+
+//==============================================================================
+// MapInto
+//==============================================================================
+
+// NOTE: Since this is external stable API,
+// we avoid relying on the Map in `statics`.
+
+/// `Strategy` and `ValueTree` map into adaptor.
+///
+/// See `Strategy::prop_map_into()`.
+#[must_use = "strategies do nothing unless used"]
+pub struct MapInto<S, O> {
+ pub(super) source: S,
+ pub(super) output: PhantomData<O>,
+}
+
+impl<S, O> MapInto<S, O> {
+ /// Construct a `MapInto` mapper from an `S` strategy into a strategy
+ /// producing `O`s.
+ pub(super) fn new(source: S) -> Self {
+ Self {
+ source,
+ output: PhantomData,
+ }
+ }
+}
+
+impl<S: fmt::Debug, O> fmt::Debug for MapInto<S, O> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("MapInto")
+ .field("source", &self.source)
+ .finish()
+ }
+}
+
+impl<S: Clone, O> Clone for MapInto<S, O> {
+ fn clone(&self) -> Self {
+ Self::new(self.source.clone())
+ }
+}
+
+impl<S: Strategy, O: fmt::Debug> Strategy for MapInto<S, O>
+where
+ S::Value: Into<O>,
+{
+ type Tree = MapInto<S::Tree, O>;
+ type Value = O;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ self.source.new_tree(runner).map(MapInto::new)
+ }
+}
+
+impl<S: ValueTree, O: fmt::Debug> ValueTree for MapInto<S, O>
+where
+ S::Value: Into<O>,
+{
+ type Value = O;
+
+ fn current(&self) -> O {
+ self.source.current().into()
+ }
+
+ fn simplify(&mut self) -> bool {
+ self.source.simplify()
+ }
+
+ fn complicate(&mut self) -> bool {
+ self.source.complicate()
+ }
+}
+
+//==============================================================================
+// Perturb
+//==============================================================================
+
+/// `Strategy` perturbation adaptor.
+///
+/// See `Strategy::prop_perturb()`.
+#[must_use = "strategies do nothing unless used"]
+pub struct Perturb<S, F> {
+ pub(super) source: S,
+ pub(super) fun: Arc<F>,
+}
+
+impl<S: fmt::Debug, F> fmt::Debug for Perturb<S, F> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Perturb")
+ .field("source", &self.source)
+ .field("fun", &"<function>")
+ .finish()
+ }
+}
+
+impl<S: Clone, F> Clone for Perturb<S, F> {
+ fn clone(&self) -> Self {
+ Perturb {
+ source: self.source.clone(),
+ fun: Arc::clone(&self.fun),
+ }
+ }
+}
+
+impl<S: Strategy, O: fmt::Debug, F: Fn(S::Value, TestRng) -> O> Strategy
+ for Perturb<S, F>
+{
+ type Tree = PerturbValueTree<S::Tree, F>;
+ type Value = O;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let rng = runner.new_rng();
+
+ self.source.new_tree(runner).map(|source| PerturbValueTree {
+ source,
+ rng,
+ fun: Arc::clone(&self.fun),
+ })
+ }
+}
+
+/// `ValueTree` perturbation adaptor.
+///
+/// See `Strategy::prop_perturb()`.
+pub struct PerturbValueTree<S, F> {
+ source: S,
+ fun: Arc<F>,
+ rng: TestRng,
+}
+
+impl<S: fmt::Debug, F> fmt::Debug for PerturbValueTree<S, F> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("PerturbValueTree")
+ .field("source", &self.source)
+ .field("fun", &"<function>")
+ .field("rng", &self.rng)
+ .finish()
+ }
+}
+
+impl<S: Clone, F> Clone for PerturbValueTree<S, F> {
+ fn clone(&self) -> Self {
+ PerturbValueTree {
+ source: self.source.clone(),
+ fun: Arc::clone(&self.fun),
+ rng: self.rng.clone(),
+ }
+ }
+}
+
+impl<S: ValueTree, O: fmt::Debug, F: Fn(S::Value, TestRng) -> O> ValueTree
+ for PerturbValueTree<S, F>
+{
+ type Value = O;
+
+ fn current(&self) -> O {
+ (self.fun)(self.source.current(), self.rng.clone())
+ }
+
+ fn simplify(&mut self) -> bool {
+ self.source.simplify()
+ }
+
+ fn complicate(&mut self) -> bool {
+ self.source.complicate()
+ }
+}
+
+//==============================================================================
+// Tests
+//==============================================================================
+
+#[cfg(test)]
+mod test {
+ use std::collections::HashSet;
+
+ use rand::RngCore;
+
+ use super::*;
+ use crate::strategy::just::Just;
+
+ #[test]
+ fn test_map() {
+ TestRunner::default()
+ .run(&(0..10).prop_map(|v| v * 2), |v| {
+ assert!(0 == v % 2);
+ Ok(())
+ })
+ .unwrap();
+ }
+
+ #[test]
+ fn test_map_into() {
+ TestRunner::default()
+ .run(&(0..10u8).prop_map_into::<usize>(), |v| {
+ assert!(v < 10);
+ Ok(())
+ })
+ .unwrap();
+ }
+
+ #[test]
+ fn perturb_uses_same_rng_every_time() {
+ let mut runner = TestRunner::default();
+ let input = Just(1).prop_perturb(|v, mut rng| v + rng.next_u32());
+
+ for _ in 0..16 {
+ let value = input.new_tree(&mut runner).unwrap();
+ assert_eq!(value.current(), value.current());
+ }
+ }
+
+ #[test]
+ fn perturb_uses_varying_random_seeds() {
+ let mut runner = TestRunner::default();
+ let input = Just(1).prop_perturb(|v, mut rng| v + rng.next_u32());
+
+ let mut seen = HashSet::new();
+ for _ in 0..64 {
+ seen.insert(input.new_tree(&mut runner).unwrap().current());
+ }
+
+ assert_eq!(64, seen.len());
+ }
+}
diff --git a/vendor/proptest/src/strategy/mod.rs b/vendor/proptest/src/strategy/mod.rs
new file mode 100644
index 000000000..6427fc103
--- /dev/null
+++ b/vendor/proptest/src/strategy/mod.rs
@@ -0,0 +1,37 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! Defines the core traits used by Proptest.
+
+mod filter;
+mod filter_map;
+mod flatten;
+mod fuse;
+mod just;
+mod lazy;
+mod map;
+mod recursive;
+mod shuffle;
+mod traits;
+mod unions;
+
+pub use self::filter::*;
+pub use self::filter_map::*;
+pub use self::flatten::*;
+pub use self::fuse::*;
+pub use self::just::*;
+pub use self::lazy::*;
+pub use self::lazy::*;
+pub use self::map::*;
+pub use self::recursive::*;
+pub use self::shuffle::*;
+pub use self::traits::*;
+pub use self::unions::*;
+
+pub mod statics;
diff --git a/vendor/proptest/src/strategy/recursive.rs b/vendor/proptest/src/strategy/recursive.rs
new file mode 100644
index 000000000..6407be7c7
--- /dev/null
+++ b/vendor/proptest/src/strategy/recursive.rs
@@ -0,0 +1,209 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+use crate::std_facade::{fmt, Arc, Box, Vec};
+
+use crate::strategy::traits::*;
+use crate::strategy::unions::float_to_weight;
+use crate::test_runner::*;
+
+/// Return type from `Strategy::prop_recursive()`.
+#[must_use = "strategies do nothing unless used"]
+pub struct Recursive<T, F> {
+ base: BoxedStrategy<T>,
+ recurse: Arc<F>,
+ depth: u32,
+ desired_size: u32,
+ expected_branch_size: u32,
+}
+
+impl<T: fmt::Debug, F> fmt::Debug for Recursive<T, F> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Recursive")
+ .field("base", &self.base)
+ .field("recurse", &"<function>")
+ .field("depth", &self.depth)
+ .field("desired_size", &self.desired_size)
+ .field("expected_branch_size", &self.expected_branch_size)
+ .finish()
+ }
+}
+
+impl<T, F> Clone for Recursive<T, F> {
+ fn clone(&self) -> Self {
+ Recursive {
+ base: self.base.clone(),
+ recurse: Arc::clone(&self.recurse),
+ depth: self.depth,
+ desired_size: self.desired_size,
+ expected_branch_size: self.expected_branch_size,
+ }
+ }
+}
+
+impl<
+ T: fmt::Debug + 'static,
+ R: Strategy<Value = T> + 'static,
+ F: Fn(BoxedStrategy<T>) -> R,
+ > Recursive<T, F>
+{
+ pub(super) fn new(
+ base: impl Strategy<Value = T> + 'static,
+ depth: u32,
+ desired_size: u32,
+ expected_branch_size: u32,
+ recurse: F,
+ ) -> Self {
+ Self {
+ base: base.boxed(),
+ recurse: Arc::new(recurse),
+ depth,
+ desired_size,
+ expected_branch_size,
+ }
+ }
+}
+
+impl<
+ T: fmt::Debug + 'static,
+ R: Strategy<Value = T> + 'static,
+ F: Fn(BoxedStrategy<T>) -> R,
+ > Strategy for Recursive<T, F>
+{
+ type Tree = Box<dyn ValueTree<Value = T>>;
+ type Value = T;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ // Since the generator is stateless, we can't implement any "absolutely
+ // X many items" rule. We _can_, however, with extremely high
+ // probability, obtain a value near what we want by using decaying
+ // probabilities of branching as we go down the tree.
+ //
+ // We are given a target size S and a branch size K (branch size =
+ // expected number of items immediately below each branch). We select
+ // some probability P for each level.
+ //
+ // A single level l is thus expected to hold PlK branches. Each of
+ // those will have P(l+1)K child branches of their own, so there are
+ // PlP(l+1)K² second-level branches. The total branches in the tree is
+ // thus (Σ PlK^l) for l from 0 to infinity. Each level is expected to
+ // hold K items, so the total number of items is simply K times the
+ // number of branches, or (K Σ PlK^l). So we want to find a P sequence
+ // such that (lim (K Σ PlK^l) = S), or more simply,
+ // (lim Σ PlK^l = S/K).
+ //
+ // Let Q be a second probability sequence such that Pl = Ql/K^l. This
+ // changes the formulation to (lim Σ Ql = S/K). The series Σ0.5^(l+1)
+ // converges on 1.0, so we can let Ql = S/K * 0.5^(l+1), and so
+ // Pl = S/K^(l+1) * 0.5^(l+1) = S / (2K) ^ (l+1)
+ //
+ // We don't actually have infinite levels here since we _can_ easily
+ // cap to a fixed max depth, so this will be a minor underestimate. We
+ // also clamp all probabilities to 0.9 to ensure that we can't end up
+ // with levels which are always pure branches, which further
+ // underestimates size.
+
+ let mut branch_probabilities = Vec::new();
+ let mut k2 = u64::from(self.expected_branch_size) * 2;
+ for _ in 0..self.depth {
+ branch_probabilities.push(f64::from(self.desired_size) / k2 as f64);
+ k2 = k2.saturating_mul(u64::from(self.expected_branch_size) * 2);
+ }
+
+ let mut strat = self.base.clone();
+ while let Some(branch_probability) = branch_probabilities.pop() {
+ let recursed = (self.recurse)(strat.clone());
+ let recursive_choice = recursed.boxed();
+ let non_recursive_choice = strat;
+ // Clamp the maximum branch probability to 0.9 to ensure we can
+ // generate non-recursive cases reasonably often.
+ let branch_probability = branch_probability.min(0.9);
+ let (weight_branch, weight_leaf) =
+ float_to_weight(branch_probability);
+ let branch = prop_oneof![
+ weight_leaf => non_recursive_choice,
+ weight_branch => recursive_choice,
+ ];
+ strat = branch.boxed();
+ }
+
+ strat.new_tree(runner)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use std::cmp::max;
+
+ use super::*;
+ use crate::strategy::just::Just;
+
+ #[derive(Clone, Debug, PartialEq)]
+ enum Tree {
+ Leaf,
+ Branch(Vec<Tree>),
+ }
+
+ impl Tree {
+ fn stats(&self) -> (u32, u32) {
+ match *self {
+ Tree::Leaf => (0, 1),
+ Tree::Branch(ref children) => {
+ let mut depth = 0;
+ let mut count = 0;
+ for child in children {
+ let (d, c) = child.stats();
+ depth = max(d, depth);
+ count += c;
+ }
+
+ (depth + 1, count + 1)
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_recursive() {
+ let mut max_depth = 0;
+ let mut max_count = 0;
+
+ let strat = Just(Tree::Leaf).prop_recursive(4, 64, 16, |element| {
+ crate::collection::vec(element, 8..16).prop_map(Tree::Branch)
+ });
+
+ let mut runner = TestRunner::deterministic();
+ for _ in 0..65536 {
+ let tree = strat.new_tree(&mut runner).unwrap().current();
+ let (depth, count) = tree.stats();
+ assert!(depth <= 4, "Got depth {}", depth);
+ assert!(count <= 128, "Got count {}", count);
+ max_depth = max(depth, max_depth);
+ max_count = max(count, max_count);
+ }
+
+ assert!(max_depth >= 3, "Only got max depth {}", max_depth);
+ assert!(max_count > 48, "Only got max count {}", max_count);
+ }
+
+ #[test]
+ fn simplifies_to_non_recursive() {
+ let strat = Just(Tree::Leaf).prop_recursive(4, 64, 16, |element| {
+ crate::collection::vec(element, 8..16).prop_map(Tree::Branch)
+ });
+
+ let mut runner = TestRunner::deterministic();
+ for _ in 0..256 {
+ let mut value = strat.new_tree(&mut runner).unwrap();
+ while value.simplify() {}
+
+ assert_eq!(Tree::Leaf, value.current());
+ }
+ }
+}
diff --git a/vendor/proptest/src/strategy/shuffle.rs b/vendor/proptest/src/strategy/shuffle.rs
new file mode 100644
index 000000000..b94a73c3b
--- /dev/null
+++ b/vendor/proptest/src/strategy/shuffle.rs
@@ -0,0 +1,287 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+use crate::std_facade::{Cell, Vec, VecDeque};
+
+use rand::Rng;
+
+use crate::num;
+use crate::strategy::traits::*;
+use crate::test_runner::*;
+
+/// `Strategy` shuffle adaptor.
+///
+/// See `Strategy::prop_shuffle()`.
+#[derive(Clone, Debug)]
+#[must_use = "strategies do nothing unless used"]
+pub struct Shuffle<S>(pub(super) S);
+
+/// A value which can be used with the `prop_shuffle` combinator.
+///
+/// This is not a general-purpose trait. Its methods are prefixed with
+/// `shuffle_` to avoid the compiler suggesting them or this trait as
+/// corrections in errors.
+pub trait Shuffleable {
+ /// Return the length of this collection.
+ fn shuffle_len(&self) -> usize;
+ /// Swap the elements at the given indices.
+ fn shuffle_swap(&mut self, a: usize, b: usize);
+}
+
+macro_rules! shuffleable {
+ ($($t:tt)*) => {
+ impl<T> Shuffleable for $($t)* {
+ fn shuffle_len(&self) -> usize {
+ self.len()
+ }
+
+ fn shuffle_swap(&mut self, a: usize, b: usize) {
+ self.swap(a, b);
+ }
+ }
+ }
+}
+
+shuffleable!([T]);
+shuffleable!(Vec<T>);
+shuffleable!(VecDeque<T>);
+// Zero- and 1-length arrays aren't usefully shuffleable, but are included to
+// simplify external macros that may try to use them anyway.
+shuffleable!([T; 0]);
+shuffleable!([T; 1]);
+shuffleable!([T; 2]);
+shuffleable!([T; 3]);
+shuffleable!([T; 4]);
+shuffleable!([T; 5]);
+shuffleable!([T; 6]);
+shuffleable!([T; 7]);
+shuffleable!([T; 8]);
+shuffleable!([T; 9]);
+shuffleable!([T; 10]);
+shuffleable!([T; 11]);
+shuffleable!([T; 12]);
+shuffleable!([T; 13]);
+shuffleable!([T; 14]);
+shuffleable!([T; 15]);
+shuffleable!([T; 16]);
+shuffleable!([T; 17]);
+shuffleable!([T; 18]);
+shuffleable!([T; 19]);
+shuffleable!([T; 20]);
+shuffleable!([T; 21]);
+shuffleable!([T; 22]);
+shuffleable!([T; 23]);
+shuffleable!([T; 24]);
+shuffleable!([T; 25]);
+shuffleable!([T; 26]);
+shuffleable!([T; 27]);
+shuffleable!([T; 28]);
+shuffleable!([T; 29]);
+shuffleable!([T; 30]);
+shuffleable!([T; 31]);
+shuffleable!([T; 32]);
+
+impl<S: Strategy> Strategy for Shuffle<S>
+where
+ S::Value: Shuffleable,
+{
+ type Tree = ShuffleValueTree<S::Tree>;
+ type Value = S::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let rng = runner.new_rng();
+
+ self.0.new_tree(runner).map(|inner| ShuffleValueTree {
+ inner,
+ rng,
+ dist: Cell::new(None),
+ simplifying_inner: false,
+ })
+ }
+}
+
+/// `ValueTree` shuffling adaptor.
+///
+/// See `Strategy::prop_shuffle()`.
+#[derive(Clone, Debug)]
+pub struct ShuffleValueTree<V> {
+ inner: V,
+ rng: TestRng,
+ /// The maximum amount to move any one element during shuffling.
+ ///
+ /// This is `Cell` since we can't determine the bounds of the value until
+ /// the first call to `current()`. (We technically _could_ by generating a
+ /// value in `new_tree` and checking its length, but that would be a 100%
+ /// slowdown.)
+ dist: Cell<Option<num::usize::BinarySearch>>,
+ /// Whether we've started simplifying `inner`. After this point, we can no
+ /// longer simplify or complicate `dist`.
+ simplifying_inner: bool,
+}
+
+impl<V: ValueTree> ShuffleValueTree<V>
+where
+ V::Value: Shuffleable,
+{
+ fn init_dist(&self, dflt: usize) -> usize {
+ if self.dist.get().is_none() {
+ self.dist.set(Some(num::usize::BinarySearch::new(dflt)));
+ }
+
+ self.dist.get().unwrap().current()
+ }
+
+ fn force_init_dist(&self) {
+ if self.dist.get().is_none() {
+ self.init_dist(self.current().shuffle_len());
+ }
+ }
+}
+
+impl<V: ValueTree> ValueTree for ShuffleValueTree<V>
+where
+ V::Value: Shuffleable,
+{
+ type Value = V::Value;
+
+ fn current(&self) -> V::Value {
+ let mut value = self.inner.current();
+ let len = value.shuffle_len();
+ // The maximum distance to swap elements. This could be larger than
+ // `value` if `value` has reduced size during shrinking; that's OK,
+ // since we only use this to filter swaps.
+ let max_swap = self.init_dist(len);
+
+ // If empty collection or all swaps will be filtered out, there's
+ // nothing to shuffle.
+ if 0 == len || 0 == max_swap {
+ return value;
+ }
+
+ let mut rng = self.rng.clone();
+
+ for start_index in 0..len - 1 {
+ // Determine the other index to be swapped, then skip the swap if
+ // it is too far. This ordering is critical, as it ensures that we
+ // generate the same sequence of random numbers every time.
+ let end_index = rng.gen_range(start_index..len);
+ if end_index - start_index <= max_swap {
+ value.shuffle_swap(start_index, end_index);
+ }
+ }
+
+ value
+ }
+
+ fn simplify(&mut self) -> bool {
+ if self.simplifying_inner {
+ self.inner.simplify()
+ } else {
+ // Ensure that we've initialised `dist` to *something* to give
+ // consistent non-panicking behaviour even if called in an
+ // unexpected sequence.
+ self.force_init_dist();
+ if self.dist.get_mut().as_mut().unwrap().simplify() {
+ true
+ } else {
+ self.simplifying_inner = true;
+ self.inner.simplify()
+ }
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ if self.simplifying_inner {
+ self.inner.complicate()
+ } else {
+ self.force_init_dist();
+ self.dist.get_mut().as_mut().unwrap().complicate()
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use std::borrow::ToOwned;
+ use std::collections::HashSet;
+ use std::i32;
+
+ use super::*;
+ use crate::collection;
+ use crate::strategy::just::Just;
+
+ static VALUES: &'static [i32] = &[
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ ];
+
+ #[test]
+ fn generates_different_permutations() {
+ let mut runner = TestRunner::default();
+ let mut seen = HashSet::<Vec<i32>>::new();
+
+ let input = Just(VALUES.to_owned()).prop_shuffle();
+
+ for _ in 0..1024 {
+ let mut value = input.new_tree(&mut runner).unwrap().current();
+
+ assert!(
+ seen.insert(value.clone()),
+ "Value {:?} generated more than once",
+ value
+ );
+
+ value.sort();
+ assert_eq!(VALUES, &value[..]);
+ }
+ }
+
+ #[test]
+ fn simplify_reduces_shuffle_amount() {
+ let mut runner = TestRunner::default();
+
+ let input = Just(VALUES.to_owned()).prop_shuffle();
+ for _ in 0..1024 {
+ let mut value = input.new_tree(&mut runner).unwrap();
+
+ let mut prev_dist = i32::MAX;
+ loop {
+ let v = value.current();
+ // Compute the "shuffle distance" by summing the absolute
+ // distance of each element's displacement.
+ let mut dist = 0;
+ for (ix, &nominal) in v.iter().enumerate() {
+ dist += (nominal - ix as i32).abs();
+ }
+
+ assert!(
+ dist <= prev_dist,
+ "dist = {}, prev_dist = {}",
+ dist,
+ prev_dist
+ );
+
+ prev_dist = dist;
+ if !value.simplify() {
+ break;
+ }
+ }
+
+ // When fully simplified, the result is in the original order.
+ assert_eq!(0, prev_dist);
+ }
+ }
+
+ #[test]
+ fn simplify_complicate_contract_upheld() {
+ check_strategy_sanity(
+ collection::vec(0i32..1000, 5..10).prop_shuffle(),
+ None,
+ );
+ }
+}
diff --git a/vendor/proptest/src/strategy/statics.rs b/vendor/proptest/src/strategy/statics.rs
new file mode 100644
index 000000000..978dc13b9
--- /dev/null
+++ b/vendor/proptest/src/strategy/statics.rs
@@ -0,0 +1,266 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+//! Modified versions of the normal strategy combinators which take specialised
+//! traits instead of normal functions.
+//!
+//! This entire module is strictly a workaround until
+//! <https://github.com/rust-lang/rfcs/pull/1522> and
+//! <https://github.com/rust-lang/rfcs/pull/2071> are available in stable. It
+//! allows naming types built on the combinators without resorting to dynamic
+//! dispatch or causing `Arc` to allocate space for a function pointer.
+//!
+//! External code is discouraged from using this module directly. It is
+//! deliberately not exposed in a convenient way (i.e., via the `Strategy`
+//! trait itself), but is nonetheless exposed since external trait implementors
+//! may face the same issues.
+//!
+//! **This module is subject to removal at some point after the language
+//! features linked above become stable.**
+
+use crate::std_facade::fmt;
+
+use crate::strategy::traits::*;
+use crate::test_runner::*;
+
+//==============================================================================
+// Filter
+//==============================================================================
+
+/// Essentially `Fn (&T) -> bool`.
+pub trait FilterFn<T> {
+ /// Test whether `t` passes the filter.
+ fn apply(&self, t: &T) -> bool;
+}
+
+/// Static version of `strategy::Filter`.
+#[derive(Clone)]
+#[must_use = "strategies do nothing unless used"]
+pub struct Filter<S, F> {
+ source: S,
+ whence: Reason,
+ fun: F,
+}
+
+impl<S, F> Filter<S, F> {
+ /// Adapt strategy `source` to reject values which do not pass `filter`,
+ /// using `whence` as the reported reason/location.
+ pub fn new(source: S, whence: Reason, filter: F) -> Self {
+ // NOTE: We don't use universal quantification R: Into<Reason>
+ // since the module is not conveniently exposed.
+ Filter {
+ source,
+ whence,
+ fun: filter,
+ }
+ }
+}
+
+impl<S: fmt::Debug, F> fmt::Debug for Filter<S, F> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Filter")
+ .field("source", &self.source)
+ .field("whence", &self.whence)
+ .field("fun", &"<function>")
+ .finish()
+ }
+}
+
+impl<S: Strategy, F: FilterFn<S::Value> + Clone> Strategy for Filter<S, F> {
+ type Tree = Filter<S::Tree, F>;
+ type Value = S::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ loop {
+ let val = self.source.new_tree(runner)?;
+ if !self.fun.apply(&val.current()) {
+ runner.reject_local(self.whence.clone())?;
+ } else {
+ return Ok(Filter {
+ source: val,
+ whence: "unused".into(),
+ fun: self.fun.clone(),
+ });
+ }
+ }
+ }
+}
+
+impl<S: ValueTree, F: FilterFn<S::Value>> Filter<S, F> {
+ fn ensure_acceptable(&mut self) {
+ while !self.fun.apply(&self.source.current()) {
+ if !self.source.complicate() {
+ panic!(
+ "Unable to complicate filtered strategy \
+ back into acceptable value"
+ );
+ }
+ }
+ }
+}
+
+impl<S: ValueTree, F: FilterFn<S::Value>> ValueTree for Filter<S, F> {
+ type Value = S::Value;
+
+ fn current(&self) -> S::Value {
+ self.source.current()
+ }
+
+ fn simplify(&mut self) -> bool {
+ if self.source.simplify() {
+ self.ensure_acceptable();
+ true
+ } else {
+ false
+ }
+ }
+
+ fn complicate(&mut self) -> bool {
+ if self.source.complicate() {
+ self.ensure_acceptable();
+ true
+ } else {
+ false
+ }
+ }
+}
+
+//==============================================================================
+// Map
+//==============================================================================
+
+/// Essentially `Fn (T) -> Output`.
+pub trait MapFn<T> {
+ #[allow(missing_docs)]
+ type Output: fmt::Debug;
+
+ /// Map `T` to `Output`.
+ fn apply(&self, t: T) -> Self::Output;
+}
+
+/// Static version of `strategy::Map`.
+#[derive(Clone)]
+#[must_use = "strategies do nothing unless used"]
+pub struct Map<S, F> {
+ source: S,
+ fun: F,
+}
+
+impl<S, F> Map<S, F> {
+ /// Adapt strategy `source` by applying `fun` to values it produces.
+ pub fn new(source: S, fun: F) -> Self {
+ Map { source, fun }
+ }
+}
+
+impl<S: fmt::Debug, F> fmt::Debug for Map<S, F> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Map")
+ .field("source", &self.source)
+ .field("fun", &"<function>")
+ .finish()
+ }
+}
+
+impl<S: Strategy, F: Clone + MapFn<S::Value>> Strategy for Map<S, F> {
+ type Tree = Map<S::Tree, F>;
+ type Value = F::Output;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ self.source.new_tree(runner).map(|v| Map {
+ source: v,
+ fun: self.fun.clone(),
+ })
+ }
+}
+
+impl<S: ValueTree, F: MapFn<S::Value>> ValueTree for Map<S, F> {
+ type Value = F::Output;
+
+ fn current(&self) -> F::Output {
+ self.fun.apply(self.source.current())
+ }
+
+ fn simplify(&mut self) -> bool {
+ self.source.simplify()
+ }
+
+ fn complicate(&mut self) -> bool {
+ self.source.complicate()
+ }
+}
+
+impl<I, O: fmt::Debug> MapFn<I> for fn(I) -> O {
+ type Output = O;
+ fn apply(&self, x: I) -> Self::Output {
+ self(x)
+ }
+}
+
+pub(crate) fn static_map<S: Strategy, O: fmt::Debug>(
+ strat: S,
+ fun: fn(S::Value) -> O,
+) -> Map<S, fn(S::Value) -> O> {
+ Map::new(strat, fun)
+}
+
+//==============================================================================
+// Tests
+//==============================================================================
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_static_filter() {
+ #[derive(Clone, Copy, Debug)]
+ struct MyFilter;
+ impl FilterFn<i32> for MyFilter {
+ fn apply(&self, &v: &i32) -> bool {
+ 0 == v % 3
+ }
+ }
+
+ let input = Filter::new(0..256, "%3".into(), MyFilter);
+
+ for _ in 0..256 {
+ let mut runner = TestRunner::default();
+ let mut case = input.new_tree(&mut runner).unwrap();
+
+ assert!(0 == case.current() % 3);
+
+ while case.simplify() {
+ assert!(0 == case.current() % 3);
+ }
+ assert!(0 == case.current() % 3);
+ }
+ }
+
+ #[test]
+ fn test_static_map() {
+ #[derive(Clone, Copy, Debug)]
+ struct MyMap;
+ impl MapFn<i32> for MyMap {
+ type Output = i32;
+ fn apply(&self, v: i32) -> i32 {
+ v * 2
+ }
+ }
+
+ let input = Map::new(0..10, MyMap);
+
+ TestRunner::default()
+ .run(&input, |v| {
+ assert!(0 == v % 2);
+ Ok(())
+ })
+ .unwrap();
+ }
+}
diff --git a/vendor/proptest/src/strategy/traits.rs b/vendor/proptest/src/strategy/traits.rs
new file mode 100644
index 000000000..bcad20a1e
--- /dev/null
+++ b/vendor/proptest/src/strategy/traits.rs
@@ -0,0 +1,1054 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+use crate::std_facade::{fmt, Arc, Box, Rc};
+use core::cmp;
+
+use crate::strategy::*;
+use crate::test_runner::*;
+
+//==============================================================================
+// Traits
+//==============================================================================
+
+/// A new [`ValueTree`] from a [`Strategy`] when [`Ok`] or otherwise [`Err`]
+/// when a new value-tree can not be produced for some reason such as
+/// in the case of filtering with a predicate which always returns false.
+/// You should pass in your strategy as the type parameter.
+///
+/// [`Strategy`]: trait.Strategy.html
+/// [`ValueTree`]: trait.ValueTree.html
+/// [`Ok`]: https://doc.rust-lang.org/nightly/std/result/enum.Result.html#variant.Ok
+/// [`Err`]: https://doc.rust-lang.org/nightly/std/result/enum.Result.html#variant.Err
+pub type NewTree<S> = Result<<S as Strategy>::Tree, Reason>;
+
+/// A strategy for producing arbitrary values of a given type.
+///
+/// `fmt::Debug` is a hard requirement for all strategies currently due to
+/// `prop_flat_map()`. This constraint will be removed when specialisation
+/// becomes stable.
+#[must_use = "strategies do nothing unless used"]
+pub trait Strategy: fmt::Debug {
+ /// The value tree generated by this `Strategy`.
+ type Tree: ValueTree<Value = Self::Value>;
+
+ /// The type of value used by functions under test generated by this Strategy.
+ ///
+ /// This corresponds to the same type as the associated type `Value`
+ /// in `Self::Tree`. It is provided here to simplify usage particularly
+ /// in conjunction with `-> impl Strategy<Value = MyType>`.
+ type Value: fmt::Debug;
+
+ /// Generate a new value tree from the given runner.
+ ///
+ /// This may fail if there are constraints on the generated value and the
+ /// generator is unable to produce anything that satisfies them. Any
+ /// failure is wrapped in `TestError::Abort`.
+ ///
+ /// This method is generally expected to be deterministic. That is, given a
+ /// `TestRunner` with its RNG in a particular state, this should produce an
+ /// identical `ValueTree` every time. Non-deterministic strategies do not
+ /// cause problems during normal operation, but they do break failure
+ /// persistence since it is implemented by simply saving the seed used to
+ /// generate the test case.
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self>;
+
+ /// Returns a strategy which produces values transformed by the function
+ /// `fun`.
+ ///
+ /// There is no need (or possibility, for that matter) to define how the
+ /// output is to be shrunken. Shrinking continues to take place in terms of
+ /// the source value.
+ ///
+ /// `fun` should be a deterministic function. That is, for a given input
+ /// value, it should produce an equivalent output value on every call.
+ /// Proptest assumes that it can call the function as many times as needed
+ /// to generate as many identical values as needed. For this reason, `F` is
+ /// `Fn` rather than `FnMut`.
+ fn prop_map<O: fmt::Debug, F: Fn(Self::Value) -> O>(
+ self,
+ fun: F,
+ ) -> Map<Self, F>
+ where
+ Self: Sized,
+ {
+ Map {
+ source: self,
+ fun: Arc::new(fun),
+ }
+ }
+
+ /// Returns a strategy which produces values of type `O` by transforming
+ /// `Self` with `Into<O>`.
+ ///
+ /// You should always prefer this operation instead of `prop_map` when
+ /// you can as it is both clearer and also currently more efficient.
+ ///
+ /// There is no need (or possibility, for that matter) to define how the
+ /// output is to be shrunken. Shrinking continues to take place in terms of
+ /// the source value.
+ fn prop_map_into<O: fmt::Debug>(self) -> MapInto<Self, O>
+ where
+ Self: Sized,
+ Self::Value: Into<O>,
+ {
+ MapInto::new(self)
+ }
+
+ /// Returns a strategy which produces values transformed by the function
+ /// `fun`, which is additionally given a random number generator.
+ ///
+ /// This is exactly like `prop_map()` except for the addition of the second
+ /// argument to the function. This allows introducing chaotic variations to
+ /// generated values that are not easily expressed otherwise while allowing
+ /// shrinking to proceed reasonably.
+ ///
+ /// During shrinking, `fun` is always called with an identical random
+ /// number generator, so if it is a pure function it will always perform
+ /// the same perturbation.
+ ///
+ /// ## Example
+ ///
+ /// ```
+ /// // The prelude also gets us the `Rng` trait.
+ /// use proptest::prelude::*;
+ ///
+ /// proptest! {
+ /// #[test]
+ /// fn test_something(a in (0i32..10).prop_perturb(
+ /// // Perturb the integer `a` (range 0..10) to a pair of that
+ /// // integer and another that's ± 10 of it.
+ /// // Note that this particular case would be better implemented as
+ /// // `(0i32..10, -10i32..10).prop_map(|(a, b)| (a, a + b))`
+ /// // but is shown here for simplicity.
+ /// |centre, rng| (centre, centre + rng.gen_range(-10, 10))))
+ /// {
+ /// // Test stuff
+ /// }
+ /// }
+ /// # fn main() { }
+ /// ```
+ fn prop_perturb<O: fmt::Debug, F: Fn(Self::Value, TestRng) -> O>(
+ self,
+ fun: F,
+ ) -> Perturb<Self, F>
+ where
+ Self: Sized,
+ {
+ Perturb {
+ source: self,
+ fun: Arc::new(fun),
+ }
+ }
+
+ /// Maps values produced by this strategy into new strategies and picks
+ /// values from those strategies.
+ ///
+ /// `fun` is used to transform the values produced by this strategy into
+ /// other strategies. Values are then chosen from the derived strategies.
+ /// Shrinking proceeds by shrinking individual values as well as shrinking
+ /// the input used to generate the internal strategies.
+ ///
+ /// ## Shrinking
+ ///
+ /// In the case of test failure, shrinking will not only shrink the output
+ /// from the combinator itself, but also the input, i.e., the strategy used
+ /// to generate the output itself. Doing this requires searching the new
+ /// derived strategy for a new failing input. The combinator will generate
+ /// up to `Config::cases` values for this search.
+ ///
+ /// As a result, nested `prop_flat_map`/`Flatten` combinators risk
+ /// exponential run time on this search for new failing values. To ensure
+ /// that test failures occur within a reasonable amount of time, all of
+ /// these combinators share a single "flat map regen" counter, and will
+ /// stop generating new values if it exceeds `Config::max_flat_map_regens`.
+ ///
+ /// ## Example
+ ///
+ /// Generate two integers, where the second is always less than the first,
+ /// without using filtering:
+ ///
+ /// ```
+ /// use proptest::prelude::*;
+ ///
+ /// proptest! {
+ /// # /*
+ /// #[test]
+ /// # */
+ /// fn test_two(
+ /// // Pick integers in the 1..65536 range, and derive a strategy
+ /// // which emits a tuple of that integer and another one which is
+ /// // some value less than it.
+ /// (a, b) in (1..65536).prop_flat_map(|a| (Just(a), 0..a))
+ /// ) {
+ /// prop_assert!(b < a);
+ /// }
+ /// }
+ /// #
+ /// # fn main() { test_two(); }
+ /// ```
+ ///
+ /// ## Choosing the right flat-map
+ ///
+ /// `Strategy` has three "flat-map" combinators. They look very similar at
+ /// first, and can be used to produce superficially identical test results.
+ /// For example, the following three expressions all produce inputs which
+ /// are 2-tuples `(a,b)` where the `b` component is less than `a`.
+ ///
+ /// ```no_run
+ /// # #![allow(unused_variables)]
+ /// use proptest::prelude::*;
+ ///
+ /// let flat_map = (1..10).prop_flat_map(|a| (Just(a), 0..a));
+ /// let ind_flat_map = (1..10).prop_ind_flat_map(|a| (Just(a), 0..a));
+ /// let ind_flat_map2 = (1..10).prop_ind_flat_map2(|a| 0..a);
+ /// ```
+ ///
+ /// The three do differ however in terms of how they shrink.
+ ///
+ /// For `flat_map`, both `a` and `b` will shrink, and the invariant that
+ /// `b < a` is maintained. This is a "dependent" or "higher-order" strategy
+ /// in that it remembers that the strategy for choosing `b` is dependent on
+ /// the value chosen for `a`.
+ ///
+ /// For `ind_flat_map`, the invariant `b < a` is maintained, but only
+ /// because `a` does not shrink. This is due to the fact that the
+ /// dependency between the strategies is not tracked; `a` is simply seen as
+ /// a constant.
+ ///
+ /// Finally, for `ind_flat_map2`, the invariant `b < a` is _not_
+ /// maintained, because `a` can shrink independently of `b`, again because
+ /// the dependency between the two variables is not tracked, but in this
+ /// case the derivation of `a` is still exposed to the shrinking system.
+ ///
+ /// The use-cases for the independent flat-map variants is pretty narrow.
+ /// For the majority of cases where invariants need to be maintained and
+ /// you want all components to shrink, `prop_flat_map` is the way to go.
+ /// `prop_ind_flat_map` makes the most sense when the input to the map
+ /// function is not exposed in the output and shrinking across strategies
+ /// is not expected to be useful. `prop_ind_flat_map2` is useful for using
+ /// related values as starting points while not constraining them to that
+ /// relation.
+ fn prop_flat_map<S: Strategy, F: Fn(Self::Value) -> S>(
+ self,
+ fun: F,
+ ) -> Flatten<Map<Self, F>>
+ where
+ Self: Sized,
+ {
+ Flatten::new(Map {
+ source: self,
+ fun: Arc::new(fun),
+ })
+ }
+
+ /// Maps values produced by this strategy into new strategies and picks
+ /// values from those strategies while considering the new strategies to be
+ /// independent.
+ ///
+ /// This is very similar to `prop_flat_map()`, but shrinking will *not*
+ /// attempt to shrink the input that produces the derived strategies. This
+ /// is appropriate for when the derived strategies already fully shrink in
+ /// the desired way.
+ ///
+ /// In most cases, you want `prop_flat_map()`.
+ ///
+ /// See `prop_flat_map()` for a more detailed explanation on how the
+ /// three flat-map combinators differ.
+ fn prop_ind_flat_map<S: Strategy, F: Fn(Self::Value) -> S>(
+ self,
+ fun: F,
+ ) -> IndFlatten<Map<Self, F>>
+ where
+ Self: Sized,
+ {
+ IndFlatten(Map {
+ source: self,
+ fun: Arc::new(fun),
+ })
+ }
+
+ /// Similar to `prop_ind_flat_map()`, but produces 2-tuples with the input
+ /// generated from `self` in slot 0 and the derived strategy in slot 1.
+ ///
+ /// See `prop_flat_map()` for a more detailed explanation on how the
+ /// three flat-map combinators differ.
+ fn prop_ind_flat_map2<S: Strategy, F: Fn(Self::Value) -> S>(
+ self,
+ fun: F,
+ ) -> IndFlattenMap<Self, F>
+ where
+ Self: Sized,
+ {
+ IndFlattenMap {
+ source: self,
+ fun: Arc::new(fun),
+ }
+ }
+
+ /// Returns a strategy which only produces values accepted by `fun`.
+ ///
+ /// This results in a very naïve form of rejection sampling and should only
+ /// be used if (a) relatively few values will actually be rejected; (b) it
+ /// isn't easy to express what you want by using another strategy and/or
+ /// `map()`.
+ ///
+ /// There are a lot of downsides to this form of filtering. It slows
+ /// testing down, since values must be generated but then discarded.
+ /// Proptest only allows a limited number of rejects this way (across the
+ /// entire `TestRunner`). Rejection can interfere with shrinking;
+ /// particularly, complex filters may largely or entirely prevent shrinking
+ /// from substantially altering the original value.
+ ///
+ /// Local rejection sampling is still preferable to rejecting the entire
+ /// input to a test (via `TestCaseError::Reject`), however, and the default
+ /// number of local rejections allowed is much higher than the number of
+ /// whole-input rejections.
+ ///
+ /// `whence` is used to record where and why the rejection occurred.
+ fn prop_filter<R: Into<Reason>, F: Fn(&Self::Value) -> bool>(
+ self,
+ whence: R,
+ fun: F,
+ ) -> Filter<Self, F>
+ where
+ Self: Sized,
+ {
+ Filter::new(self, whence.into(), fun)
+ }
+
+ /// Returns a strategy which only produces transformed values where `fun`
+ /// returns `Some(value)` and rejects those where `fun` returns `None`.
+ ///
+ /// Using this method is preferable to using `.prop_map(..).prop_filter(..)`.
+ ///
+ /// This results in a very naïve form of rejection sampling and should only
+ /// be used if (a) relatively few values will actually be rejected; (b) it
+ /// isn't easy to express what you want by using another strategy and/or
+ /// `map()`.
+ ///
+ /// There are a lot of downsides to this form of filtering. It slows
+ /// testing down, since values must be generated but then discarded.
+ /// Proptest only allows a limited number of rejects this way (across the
+ /// entire `TestRunner`). Rejection can interfere with shrinking;
+ /// particularly, complex filters may largely or entirely prevent shrinking
+ /// from substantially altering the original value.
+ ///
+ /// Local rejection sampling is still preferable to rejecting the entire
+ /// input to a test (via `TestCaseError::Reject`), however, and the default
+ /// number of local rejections allowed is much higher than the number of
+ /// whole-input rejections.
+ ///
+ /// `whence` is used to record where and why the rejection occurred.
+ fn prop_filter_map<F: Fn(Self::Value) -> Option<O>, O: fmt::Debug>(
+ self,
+ whence: impl Into<Reason>,
+ fun: F,
+ ) -> FilterMap<Self, F>
+ where
+ Self: Sized,
+ {
+ FilterMap::new(self, whence.into(), fun)
+ }
+
+ /// Returns a strategy which picks uniformly from `self` and `other`.
+ ///
+ /// When shrinking, if a value from `other` was originally chosen but that
+ /// value can be shrunken no further, it switches to a value from `self`
+ /// and starts shrinking that.
+ ///
+ /// Be aware that chaining `prop_union` calls will result in a very
+ /// right-skewed distribution. If this is not what you want, you can call
+ /// the `.or()` method on the `Union` to add more values to the same union,
+ /// or directly call `Union::new()`.
+ ///
+ /// Both `self` and `other` must be of the same type. To combine
+ /// heterogeneous strategies, call the `boxed()` method on both `self` and
+ /// `other` to erase the type differences before calling `prop_union()`.
+ fn prop_union(self, other: Self) -> Union<Self>
+ where
+ Self: Sized,
+ {
+ Union::new(vec![self, other])
+ }
+
+ /// Generate a recursive structure with `self` items as leaves.
+ ///
+ /// `recurse` is applied to various strategies that produce the same type
+ /// as `self` with nesting depth _n_ to create a strategy that produces the
+ /// same type with nesting depth _n+1_. Generated structures will have a
+ /// depth between 0 and `depth` and will usually have up to `desired_size`
+ /// total elements, though they may have more. `expected_branch_size` gives
+ /// the expected maximum size for any collection which may contain
+ /// recursive elements and is used to control branch probability to achieve
+ /// the desired size. Passing a too small value can result in trees vastly
+ /// larger than desired.
+ ///
+ /// Note that `depth` only counts branches; i.e., `depth = 0` is a single
+ /// leaf, and `depth = 1` is a leaf or a branch containing only leaves.
+ ///
+ /// In practise, generated values usually have a lower depth than `depth`
+ /// (but `depth` is a hard limit) and almost always under
+ /// `expected_branch_size` (though it is not a hard limit) since the
+ /// underlying code underestimates probabilities.
+ ///
+ /// Shrinking shrinks both the inner values and attempts switching from
+ /// recursive to non-recursive cases.
+ ///
+ /// ## Example
+ ///
+ /// ```rust,no_run
+ /// # #![allow(unused_variables)]
+ /// use std::collections::HashMap;
+ ///
+ /// use proptest::prelude::*;
+ ///
+ /// /// Define our own JSON AST type
+ /// #[derive(Debug, Clone)]
+ /// enum JsonNode {
+ /// Null,
+ /// Bool(bool),
+ /// Number(f64),
+ /// String(String),
+ /// Array(Vec<JsonNode>),
+ /// Map(HashMap<String, JsonNode>),
+ /// }
+ ///
+ /// # fn main() {
+ /// #
+ /// // Define a strategy for generating leaf nodes of the AST
+ /// let json_leaf = prop_oneof![
+ /// Just(JsonNode::Null),
+ /// prop::bool::ANY.prop_map(JsonNode::Bool),
+ /// prop::num::f64::ANY.prop_map(JsonNode::Number),
+ /// ".*".prop_map(JsonNode::String),
+ /// ];
+ ///
+ /// // Now define a strategy for a whole tree
+ /// let json_tree = json_leaf.prop_recursive(
+ /// 4, // No more than 4 branch levels deep
+ /// 64, // Target around 64 total elements
+ /// 16, // Each collection is up to 16 elements long
+ /// |element| prop_oneof![
+ /// // NB `element` is an `Arc` and we'll need to reference it twice,
+ /// // so we clone it the first time.
+ /// prop::collection::vec(element.clone(), 0..16)
+ /// .prop_map(JsonNode::Array),
+ /// prop::collection::hash_map(".*", element, 0..16)
+ /// .prop_map(JsonNode::Map)
+ /// ]);
+ /// # }
+ /// ```
+ fn prop_recursive<
+ R: Strategy<Value = Self::Value> + 'static,
+ F: Fn(BoxedStrategy<Self::Value>) -> R,
+ >(
+ self,
+ depth: u32,
+ desired_size: u32,
+ expected_branch_size: u32,
+ recurse: F,
+ ) -> Recursive<Self::Value, F>
+ where
+ Self: Sized + 'static,
+ {
+ Recursive::new(self, depth, desired_size, expected_branch_size, recurse)
+ }
+
+ /// Shuffle the contents of the values produced by this strategy.
+ ///
+ /// That is, this modifies a strategy producing a `Vec`, slice, etc, to
+ /// shuffle the contents of that `Vec`/slice/etc.
+ ///
+ /// Initially, the value is fully shuffled. During shrinking, the input
+ /// value will initially be unchanged while the result will gradually be
+ /// restored to its original order. Once de-shuffling either completes or
+ /// is cancelled by calls to `complicate()` pinning it to a particular
+ /// permutation, the inner value will be simplified.
+ ///
+ /// ## Example
+ ///
+ /// ```
+ /// use proptest::prelude::*;
+ ///
+ /// static VALUES: &'static [u32] = &[0, 1, 2, 3, 4];
+ ///
+ /// fn is_permutation(orig: &[u32], mut actual: Vec<u32>) -> bool {
+ /// actual.sort();
+ /// orig == &actual[..]
+ /// }
+ ///
+ /// proptest! {
+ /// # /*
+ /// #[test]
+ /// # */
+ /// fn test_is_permutation(
+ /// ref perm in Just(VALUES.to_owned()).prop_shuffle()
+ /// ) {
+ /// assert!(is_permutation(VALUES, perm.clone()));
+ /// }
+ /// }
+ /// #
+ /// # fn main() { test_is_permutation(); }
+ /// ```
+ fn prop_shuffle(self) -> Shuffle<Self>
+ where
+ Self: Sized,
+ Self::Value: Shuffleable,
+ {
+ Shuffle(self)
+ }
+
+ /// Erases the type of this `Strategy` so it can be passed around as a
+ /// simple trait object.
+ ///
+ /// See also `sboxed()` if this `Strategy` is `Send` and `Sync` and you
+ /// want to preserve that information.
+ ///
+ /// Strategies of this type afford cheap shallow cloning via reference
+ /// counting by using an `Arc` internally.
+ fn boxed(self) -> BoxedStrategy<Self::Value>
+ where
+ Self: Sized + 'static,
+ {
+ BoxedStrategy(Arc::new(BoxedStrategyWrapper(self)))
+ }
+
+ /// Erases the type of this `Strategy` so it can be passed around as a
+ /// simple trait object.
+ ///
+ /// Unlike `boxed()`, this conversion retains the `Send` and `Sync` traits
+ /// on the output.
+ ///
+ /// Strategies of this type afford cheap shallow cloning via reference
+ /// counting by using an `Arc` internally.
+ fn sboxed(self) -> SBoxedStrategy<Self::Value>
+ where
+ Self: Sized + Send + Sync + 'static,
+ {
+ SBoxedStrategy(Arc::new(BoxedStrategyWrapper(self)))
+ }
+
+ /// Wraps this strategy to prevent values from being subject to shrinking.
+ ///
+ /// Suppressing shrinking is useful when testing things like linear
+ /// approximation functions. Ordinarily, proptest will tend to shrink the
+ /// input to the function until the result is just barely outside the
+ /// acceptable range whereas the original input may have produced a result
+ /// far outside of it. Since this makes it harder to see what the actual
+ /// problem is, making the input `NoShrink` allows learning about inputs
+ /// that produce more incorrect results.
+ fn no_shrink(self) -> NoShrink<Self>
+ where
+ Self: Sized,
+ {
+ NoShrink(self)
+ }
+}
+
+/// A generated value and its associated shrinker.
+///
+/// Conceptually, a `ValueTree` represents a spectrum between a "minimally
+/// complex" value and a starting, randomly-chosen value. For values such as
+/// numbers, this can be thought of as a simple binary search, and this is how
+/// the `ValueTree` state machine is defined.
+///
+/// The `ValueTree` state machine notionally has three fields: low, current,
+/// and high. Initially, low is the "minimally complex" value for the type, and
+/// high and current are both the initially chosen value. It can be queried for
+/// its current state. When shrinking, the controlling code tries simplifying
+/// the value one step. If the test failure still happens with the simplified
+/// value, further simplification occurs. Otherwise, the code steps back up
+/// towards the prior complexity.
+///
+/// The main invariants here are that the "high" value always corresponds to a
+/// failing test case, and that repeated calls to `complicate()` will return
+/// `false` only once the "current" value has returned to what it was before
+/// the last call to `simplify()`.
+///
+/// While it would be possible for default do-nothing implementations of
+/// `simplify()` and `complicate()` to be provided, this was not done
+/// deliberately since the majority of strategies will want to define their own
+/// shrinking anyway, and the minority that do not must call it out explicitly
+/// by their own implementation.
+pub trait ValueTree {
+ /// The type of the value produced by this `ValueTree`.
+ type Value: fmt::Debug;
+
+ /// Returns the current value.
+ fn current(&self) -> Self::Value;
+ /// Attempts to simplify the current value. Notionally, this sets the
+ /// "high" value to the current value, and the current value to a "halfway
+ /// point" between high and low, rounding towards low.
+ ///
+ /// Returns whether any state changed as a result of this call. This does
+ /// not necessarily imply that the value of `current()` has changed, since
+ /// in the most general case, it is not possible for an implementation to
+ /// determine this.
+ ///
+ /// This call needs to correctly handle being called even immediately after
+ /// it had been called previously and returned `false`.
+ fn simplify(&mut self) -> bool;
+ /// Attempts to partially undo the last simplification. Notionally, this
+ /// sets the "low" value to one plus the current value, and the current
+ /// value to a "halfway point" between high and the new low, rounding
+ /// towards low.
+ ///
+ /// Returns whether any state changed as a result of this call. This does
+ /// not necessarily imply that the value of `current()` has changed, since
+ /// in the most general case, it is not possible for an implementation to
+ /// determine this.
+ ///
+ /// It is usually expected that, immediately after a call to `simplify()`
+ /// which returns true, this call will itself return true. However, this is
+ /// not always the case; in some strategies, particularly those that use
+ /// some form of rejection sampling, the act of trying to simplify may
+ /// change the state such that `simplify()` returns true, yet ultimately
+ /// left the resulting value unchanged, in which case there is nothing left
+ /// to complicate.
+ ///
+ /// This call does not need to gracefully handle being called before
+ /// `simplify()` was ever called, but does need to correctly handle being
+ /// called even immediately after it had been called previously and
+ /// returned `false`.
+ fn complicate(&mut self) -> bool;
+}
+
+//==============================================================================
+// NoShrink
+//==============================================================================
+
+/// Wraps a `Strategy` or `ValueTree` to suppress shrinking of generated
+/// values.
+///
+/// See `Strategy::no_shrink()` for more details.
+#[derive(Clone, Copy, Debug)]
+#[must_use = "strategies do nothing unless used"]
+pub struct NoShrink<T>(T);
+
+impl<T: Strategy> Strategy for NoShrink<T> {
+ type Tree = NoShrink<T::Tree>;
+ type Value = T::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ self.0.new_tree(runner).map(NoShrink)
+ }
+}
+
+impl<T: ValueTree> ValueTree for NoShrink<T> {
+ type Value = T::Value;
+
+ fn current(&self) -> T::Value {
+ self.0.current()
+ }
+
+ fn simplify(&mut self) -> bool {
+ false
+ }
+ fn complicate(&mut self) -> bool {
+ false
+ }
+}
+
+//==============================================================================
+// Trait objects
+//==============================================================================
+
+macro_rules! proxy_strategy {
+ ($typ:ty $(, $lt:tt)*) => {
+ impl<$($lt,)* S : Strategy + ?Sized> Strategy for $typ {
+ type Tree = S::Tree;
+ type Value = S::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ (**self).new_tree(runner)
+ }
+ }
+ };
+}
+proxy_strategy!(Box<S>);
+proxy_strategy!(&'a S, 'a);
+proxy_strategy!(&'a mut S, 'a);
+proxy_strategy!(Rc<S>);
+proxy_strategy!(Arc<S>);
+
+impl<T: ValueTree + ?Sized> ValueTree for Box<T> {
+ type Value = T::Value;
+ fn current(&self) -> Self::Value {
+ (**self).current()
+ }
+ fn simplify(&mut self) -> bool {
+ (**self).simplify()
+ }
+ fn complicate(&mut self) -> bool {
+ (**self).complicate()
+ }
+}
+
+/// A boxed `ValueTree`.
+type BoxedVT<T> = Box<dyn ValueTree<Value = T>>;
+
+/// A boxed `Strategy` trait object as produced by `Strategy::boxed()`.
+///
+/// Strategies of this type afford cheap shallow cloning via reference
+/// counting by using an `Arc` internally.
+#[derive(Debug)]
+#[must_use = "strategies do nothing unless used"]
+pub struct BoxedStrategy<T>(Arc<dyn Strategy<Value = T, Tree = BoxedVT<T>>>);
+
+/// A boxed `Strategy` trait object which is also `Sync` and
+/// `Send`, as produced by `Strategy::sboxed()`.
+///
+/// Strategies of this type afford cheap shallow cloning via reference
+/// counting by using an `Arc` internally.
+#[derive(Debug)]
+#[must_use = "strategies do nothing unless used"]
+pub struct SBoxedStrategy<T>(
+ Arc<dyn Strategy<Value = T, Tree = BoxedVT<T>> + Sync + Send>,
+);
+
+impl<T> Clone for BoxedStrategy<T> {
+ fn clone(&self) -> Self {
+ BoxedStrategy(Arc::clone(&self.0))
+ }
+}
+
+impl<T> Clone for SBoxedStrategy<T> {
+ fn clone(&self) -> Self {
+ SBoxedStrategy(Arc::clone(&self.0))
+ }
+}
+
+impl<T: fmt::Debug> Strategy for BoxedStrategy<T> {
+ type Tree = BoxedVT<T>;
+ type Value = T;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ self.0.new_tree(runner)
+ }
+
+ // Optimization: Don't rebox the strategy.
+
+ fn boxed(self) -> BoxedStrategy<Self::Value>
+ where
+ Self: Sized + 'static,
+ {
+ self
+ }
+}
+
+impl<T: fmt::Debug> Strategy for SBoxedStrategy<T> {
+ type Tree = BoxedVT<T>;
+ type Value = T;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ self.0.new_tree(runner)
+ }
+
+ // Optimization: Don't rebox the strategy.
+
+ fn sboxed(self) -> SBoxedStrategy<Self::Value>
+ where
+ Self: Sized + Send + Sync + 'static,
+ {
+ self
+ }
+
+ fn boxed(self) -> BoxedStrategy<Self::Value>
+ where
+ Self: Sized + 'static,
+ {
+ BoxedStrategy(self.0)
+ }
+}
+
+#[derive(Debug)]
+struct BoxedStrategyWrapper<T>(T);
+impl<T: Strategy> Strategy for BoxedStrategyWrapper<T>
+where
+ T::Tree: 'static,
+{
+ type Tree = Box<dyn ValueTree<Value = T::Value>>;
+ type Value = T::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ Ok(Box::new(self.0.new_tree(runner)?))
+ }
+}
+
+//==============================================================================
+// Sanity checking
+//==============================================================================
+
+/// Options passed to `check_strategy_sanity()`.
+#[derive(Clone, Copy, Debug)]
+pub struct CheckStrategySanityOptions {
+ /// If true (the default), require that `complicate()` return `true` at
+ /// least once after any call to `simplify()` which itself returns once.
+ ///
+ /// This property is not required by contract, but many strategies are
+ /// designed in a way that this is expected to hold.
+ pub strict_complicate_after_simplify: bool,
+
+ /// If true, cause local rejects to return an error instead of retrying.
+ /// Defaults to false. Useful for testing behaviors around error handling.
+ pub error_on_local_rejects: bool,
+
+ // Needs to be public for FRU syntax.
+ #[allow(missing_docs)]
+ #[doc(hidden)]
+ pub _non_exhaustive: (),
+}
+
+impl Default for CheckStrategySanityOptions {
+ fn default() -> Self {
+ CheckStrategySanityOptions {
+ strict_complicate_after_simplify: true,
+ error_on_local_rejects: false,
+ _non_exhaustive: (),
+ }
+ }
+}
+
+/// Run some tests on the given `Strategy` to ensure that it upholds the
+/// simplify/complicate contracts.
+///
+/// This is used to internally test proptest, but is made generally available
+/// for external implementations to use as well.
+///
+/// `options` can be passed to configure the test; if `None`, the defaults are
+/// used. Note that the defaults check for certain properties which are **not**
+/// actually required by the `Strategy` and `ValueTree` contracts; if you think
+/// your code is right but it fails the test, consider whether a non-default
+/// configuration is necessary.
+///
+/// This can work with fallible strategies, but limits how many times it will
+/// retry failures.
+pub fn check_strategy_sanity<S: Strategy>(
+ strategy: S,
+ options: Option<CheckStrategySanityOptions>,
+) where
+ S::Tree: Clone + fmt::Debug,
+ S::Value: cmp::PartialEq,
+{
+ // Like assert_eq!, but also pass if both values do not equal themselves.
+ // This allows the test to work correctly with things like NaN.
+ macro_rules! assert_same {
+ ($a:expr, $b:expr, $($stuff:tt)*) => { {
+ let a = $a;
+ let b = $b;
+ if a == a || b == b {
+ assert_eq!(a, b, $($stuff)*);
+ }
+ } }
+ }
+
+ let options = options.unwrap_or_else(CheckStrategySanityOptions::default);
+ let mut config = Config::default();
+ if options.error_on_local_rejects {
+ config.max_local_rejects = 0;
+ }
+ let mut runner = TestRunner::new(config);
+
+ for _ in 0..1024 {
+ let mut gen_tries = 0;
+ let mut state;
+ loop {
+ let err = match strategy.new_tree(&mut runner) {
+ Ok(s) => {
+ state = s;
+ break;
+ }
+ Err(e) => e,
+ };
+
+ gen_tries += 1;
+ if gen_tries > 100 {
+ panic!(
+ "Strategy passed to check_strategy_sanity failed \
+ to generate a value over 100 times in a row; \
+ last failure reason: {}",
+ err
+ );
+ }
+ }
+
+ {
+ let mut state = state.clone();
+ let mut count = 0;
+ while state.simplify() || state.complicate() {
+ count += 1;
+ if count > 65536 {
+ panic!(
+ "Failed to converge on any value. State:\n{:#?}",
+ state
+ );
+ }
+ }
+ }
+
+ let mut num_simplifies = 0;
+ let mut before_simplified;
+ loop {
+ before_simplified = state.clone();
+ if !state.simplify() {
+ break;
+ }
+
+ let mut complicated = state.clone();
+ let before_complicated = state.clone();
+ if options.strict_complicate_after_simplify {
+ assert!(
+ complicated.complicate(),
+ "complicate() returned false immediately after \
+ simplify() returned true. internal state after \
+ {} calls to simplify():\n\
+ {:#?}\n\
+ simplified to:\n\
+ {:#?}\n\
+ complicated to:\n\
+ {:#?}",
+ num_simplifies,
+ before_simplified,
+ state,
+ complicated
+ );
+ }
+
+ let mut prev_complicated = complicated.clone();
+ let mut num_complications = 0;
+ loop {
+ if !complicated.complicate() {
+ break;
+ }
+ prev_complicated = complicated.clone();
+ num_complications += 1;
+
+ if num_complications > 65_536 {
+ panic!(
+ "complicate() returned true over 65536 times in a \
+ row; aborting due to possible infinite loop. \
+ If this is not an infinite loop, it may be \
+ necessary to reconsider how shrinking is \
+ implemented or use a simpler test strategy. \
+ Internal state:\n{:#?}",
+ state
+ );
+ }
+ }
+
+ assert_same!(
+ before_simplified.current(),
+ complicated.current(),
+ "Calling simplify(), then complicate() until it \
+ returned false, did not return to the value before \
+ simplify. Expected:\n\
+ {:#?}\n\
+ Actual:\n\
+ {:#?}\n\
+ Internal state after {} calls to simplify():\n\
+ {:#?}\n\
+ Internal state after another call to simplify():\n\
+ {:#?}\n\
+ Internal state after {} subsequent calls to \
+ complicate():\n\
+ {:#?}",
+ before_simplified.current(),
+ complicated.current(),
+ num_simplifies,
+ before_simplified,
+ before_complicated,
+ num_complications + 1,
+ complicated
+ );
+
+ for iter in 1..16 {
+ assert_same!(
+ prev_complicated.current(),
+ complicated.current(),
+ "complicate() returned false but changed the output \
+ value anyway.\n\
+ Old value:\n\
+ {:#?}\n\
+ New value:\n\
+ {:#?}\n\
+ Old internal state:\n\
+ {:#?}\n\
+ New internal state after {} calls to complicate()\
+ including the :\n\
+ {:#?}",
+ prev_complicated.current(),
+ complicated.current(),
+ prev_complicated,
+ iter,
+ complicated
+ );
+
+ assert!(
+ !complicated.complicate(),
+ "complicate() returned true after having returned \
+ false;\n\
+ Internal state before:\n{:#?}\n\
+ Internal state after calling complicate() {} times:\n\
+ {:#?}",
+ prev_complicated,
+ iter + 1,
+ complicated
+ );
+ }
+
+ num_simplifies += 1;
+ if num_simplifies > 65_536 {
+ panic!(
+ "simplify() returned true over 65536 times in a row, \
+ aborting due to possible infinite loop. If this is not \
+ an infinite loop, it may be necessary to reconsider \
+ how shrinking is implemented or use a simpler test \
+ strategy. Internal state:\n{:#?}",
+ state
+ );
+ }
+ }
+
+ for iter in 0..16 {
+ assert_same!(
+ before_simplified.current(),
+ state.current(),
+ "simplify() returned false but changed the output \
+ value anyway.\n\
+ Old value:\n\
+ {:#?}\n\
+ New value:\n\
+ {:#?}\n\
+ Previous internal state:\n\
+ {:#?}\n\
+ New internal state after calling simplify() {} times:\n\
+ {:#?}",
+ before_simplified.current(),
+ state.current(),
+ before_simplified,
+ iter,
+ state
+ );
+
+ if state.simplify() {
+ panic!(
+ "simplify() returned true after having returned false. \
+ Previous internal state:\n\
+ {:#?}\n\
+ New internal state after calling simplify() {} times:\n\
+ {:#?}",
+ before_simplified,
+ iter + 1,
+ state
+ );
+ }
+ }
+ }
+}
diff --git a/vendor/proptest/src/strategy/unions.rs b/vendor/proptest/src/strategy/unions.rs
new file mode 100644
index 000000000..fb5806297
--- /dev/null
+++ b/vendor/proptest/src/strategy/unions.rs
@@ -0,0 +1,697 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+use crate::std_facade::{fmt, Arc, Vec};
+use core::cmp::{max, min};
+use core::u32;
+
+#[cfg(not(feature = "std"))]
+use num_traits::float::FloatCore;
+
+use crate::num::sample_uniform;
+use crate::strategy::{lazy::LazyValueTree, traits::*};
+use crate::test_runner::*;
+
+/// A **relative** `weight` of a particular `Strategy` corresponding to `T`
+/// coupled with `T` itself. The weight is currently given in `u32`.
+pub type W<T> = (u32, T);
+
+/// A **relative** `weight` of a particular `Strategy` corresponding to `T`
+/// coupled with `Arc<T>`. The weight is currently given in `u32`.
+pub type WA<T> = (u32, Arc<T>);
+
+/// A `Strategy` which picks from one of several delegate `Stragegy`s.
+///
+/// See `Strategy::prop_union()`.
+#[derive(Clone, Debug)]
+#[must_use = "strategies do nothing unless used"]
+pub struct Union<T: Strategy> {
+ // In principle T could be any `Strategy + Clone`, but that isn't possible
+ // for BC reasons with the 0.9 series.
+ options: Vec<WA<T>>,
+}
+
+impl<T: Strategy> Union<T> {
+ /// Create a strategy which selects uniformly from the given delegate
+ /// strategies.
+ ///
+ /// When shrinking, after maximal simplification of the chosen element, the
+ /// strategy will move to earlier options and continue simplification with
+ /// those.
+ ///
+ /// ## Panics
+ ///
+ /// Panics if `options` is empty.
+ pub fn new(options: impl IntoIterator<Item = T>) -> Self {
+ let options: Vec<WA<T>> =
+ options.into_iter().map(|v| (1, Arc::new(v))).collect();
+ assert!(!options.is_empty());
+ Self { options }
+ }
+
+ pub(crate) fn try_new<E>(
+ it: impl Iterator<Item = Result<T, E>>,
+ ) -> Result<Self, E> {
+ let options: Vec<WA<T>> = it
+ .map(|r| r.map(|v| (1, Arc::new(v))))
+ .collect::<Result<_, _>>()?;
+
+ assert!(!options.is_empty());
+ Ok(Self { options })
+ }
+
+ /// Create a strategy which selects from the given delegate strategies.
+ ///
+ /// Each strategy is assigned a non-zero weight which determines how
+ /// frequently that strategy is chosen. For example, a strategy with a
+ /// weight of 2 will be chosen twice as frequently as one with a weight of
+ /// 1\.
+ ///
+ /// ## Panics
+ ///
+ /// Panics if `options` is empty or any element has a weight of 0.
+ ///
+ /// Panics if the sum of the weights overflows a `u32`.
+ pub fn new_weighted(options: Vec<W<T>>) -> Self {
+ assert!(!options.is_empty());
+ assert!(
+ !options.iter().any(|&(w, _)| 0 == w),
+ "Union option has a weight of 0"
+ );
+ assert!(
+ options.iter().map(|&(w, _)| u64::from(w)).sum::<u64>()
+ <= u64::from(u32::MAX),
+ "Union weights overflow u32"
+ );
+ let options =
+ options.into_iter().map(|(w, v)| (w, Arc::new(v))).collect();
+ Self { options }
+ }
+
+ /// Add `other` as an additional alternate strategy with weight 1.
+ pub fn or(mut self, other: T) -> Self {
+ self.options.push((1, Arc::new(other)));
+ self
+ }
+}
+
+fn pick_weighted<I: Iterator<Item = u32>>(
+ runner: &mut TestRunner,
+ weights1: I,
+ weights2: I,
+) -> usize {
+ let sum = weights1.map(u64::from).sum();
+ let weighted_pick = sample_uniform(runner, 0, sum);
+ weights2
+ .scan(0u64, |state, w| {
+ *state += u64::from(w);
+ Some(*state)
+ })
+ .filter(|&v| v <= weighted_pick)
+ .count()
+}
+
+impl<T: Strategy> Strategy for Union<T> {
+ type Tree = UnionValueTree<T>;
+ type Value = T::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ fn extract_weight<V>(&(w, _): &WA<V>) -> u32 {
+ w
+ }
+
+ let pick = pick_weighted(
+ runner,
+ self.options.iter().map(extract_weight::<T>),
+ self.options.iter().map(extract_weight::<T>),
+ );
+
+ let mut options = Vec::with_capacity(pick);
+
+ // Delay initialization for all options less than pick.
+ for option in &self.options[0..pick] {
+ options.push(LazyValueTree::new(Arc::clone(&option.1), runner));
+ }
+
+ // Initialize the tree at pick so at least one value is available. Note
+ // that if generation for the value at pick fails, the entire strategy
+ // will fail. This seems like the right call.
+ options.push(LazyValueTree::new_initialized(
+ self.options[pick].1.new_tree(runner)?,
+ ));
+
+ Ok(UnionValueTree {
+ options,
+ pick,
+ min_pick: 0,
+ prev_pick: None,
+ })
+ }
+}
+
+macro_rules! access_vec {
+ ([$($muta:tt)*] $dst:ident = $this:expr, $ix:expr, $body:block) => {{
+ let $dst = &$($muta)* $this.options[$ix];
+ $body
+ }}
+}
+
+/// `ValueTree` corresponding to `Union`.
+pub struct UnionValueTree<T: Strategy> {
+ options: Vec<LazyValueTree<T>>,
+ // This struct maintains the invariant that between function calls,
+ // `pick` and `prev_pick` (if Some) always point to initialized
+ // trees.
+ pick: usize,
+ min_pick: usize,
+ prev_pick: Option<usize>,
+}
+
+macro_rules! lazy_union_value_tree_body {
+ ($typ:ty, $access:ident) => {
+ type Value = $typ;
+
+ fn current(&self) -> Self::Value {
+ $access!([] opt = self, self.pick, {
+ opt.as_inner().unwrap_or_else(||
+ panic!(
+ "value tree at self.pick = {} must be initialized",
+ self.pick,
+ )
+ ).current()
+ })
+ }
+
+ fn simplify(&mut self) -> bool {
+ let orig_pick = self.pick;
+ if $access!([mut] opt = self, orig_pick, {
+ opt.as_inner_mut().unwrap_or_else(||
+ panic!(
+ "value tree at self.pick = {} must be initialized",
+ orig_pick,
+ )
+ ).simplify()
+ }) {
+ self.prev_pick = None;
+ return true;
+ }
+
+ assert!(
+ self.pick >= self.min_pick,
+ "self.pick = {} should never go below self.min_pick = {}",
+ self.pick,
+ self.min_pick,
+ );
+ if self.pick == self.min_pick {
+ // No more simplification to be done.
+ return false;
+ }
+
+ // self.prev_pick is always a valid pick.
+ self.prev_pick = Some(self.pick);
+
+ let mut next_pick = self.pick;
+ while next_pick > self.min_pick {
+ next_pick -= 1;
+ let initialized = $access!([mut] opt = self, next_pick, {
+ opt.maybe_init();
+ opt.is_initialized()
+ });
+ if initialized {
+ // next_pick was correctly initialized above.
+ self.pick = next_pick;
+ return true;
+ }
+ }
+
+ false
+ }
+
+ fn complicate(&mut self) -> bool {
+ if let Some(pick) = self.prev_pick {
+ // simplify() ensures that the previous pick was initialized.
+ self.pick = pick;
+ self.min_pick = pick;
+ self.prev_pick = None;
+ true
+ } else {
+ let pick = self.pick;
+ $access!([mut] opt = self, pick, {
+ opt.as_inner_mut().unwrap_or_else(||
+ panic!(
+ "value tree at self.pick = {} must be initialized",
+ pick,
+ )
+ ).complicate()
+ })
+ }
+ }
+ }
+}
+
+impl<T: Strategy> ValueTree for UnionValueTree<T> {
+ lazy_union_value_tree_body!(T::Value, access_vec);
+}
+
+impl<T: Strategy> Clone for UnionValueTree<T>
+where
+ T::Tree: Clone,
+{
+ fn clone(&self) -> Self {
+ Self {
+ options: self.options.clone(),
+ pick: self.pick,
+ min_pick: self.min_pick,
+ prev_pick: self.prev_pick,
+ }
+ }
+}
+
+impl<T: Strategy> fmt::Debug for UnionValueTree<T>
+where
+ T::Tree: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("UnionValueTree")
+ .field("options", &self.options)
+ .field("pick", &self.pick)
+ .field("min_pick", &self.min_pick)
+ .field("prev_pick", &self.prev_pick)
+ .finish()
+ }
+}
+
+macro_rules! def_access_tuple {
+ ($b:tt $name:ident, $($n:tt)*) => {
+ macro_rules! $name {
+ ([$b($b muta:tt)*] $b dst:ident = $b this:expr,
+ $b ix:expr, $b body:block) => {
+ match $b ix {
+ 0 => {
+ let $b dst = &$b($b muta)* $b this.options.0;
+ $b body
+ },
+ $(
+ $n => {
+ if let Some(ref $b($b muta)* $b dst) =
+ $b this.options.$n
+ {
+ $b body
+ } else {
+ panic!("TupleUnion tried to access \
+ uninitialised slot {}", $n)
+ }
+ },
+ )*
+ _ => panic!("TupleUnion tried to access out-of-range \
+ slot {}", $b ix),
+ }
+ }
+ }
+ }
+}
+
+def_access_tuple!($ access_tuple2, 1);
+def_access_tuple!($ access_tuple3, 1 2);
+def_access_tuple!($ access_tuple4, 1 2 3);
+def_access_tuple!($ access_tuple5, 1 2 3 4);
+def_access_tuple!($ access_tuple6, 1 2 3 4 5);
+def_access_tuple!($ access_tuple7, 1 2 3 4 5 6);
+def_access_tuple!($ access_tuple8, 1 2 3 4 5 6 7);
+def_access_tuple!($ access_tuple9, 1 2 3 4 5 6 7 8);
+def_access_tuple!($ access_tupleA, 1 2 3 4 5 6 7 8 9);
+
+/// Similar to `Union`, but internally uses a tuple to hold the strategies.
+///
+/// This allows better performance than vanilla `Union` since one does not need
+/// to resort to boxing and dynamic dispatch to handle heterogeneous
+/// strategies.
+///
+/// The difference between this and `TupleUnion` is that with this, value trees
+/// for variants that aren't picked at first are generated lazily.
+#[must_use = "strategies do nothing unless used"]
+#[derive(Clone, Copy, Debug)]
+pub struct TupleUnion<T>(T);
+
+impl<T> TupleUnion<T> {
+ /// Wrap `tuple` in a `TupleUnion`.
+ ///
+ /// The struct definition allows any `T` for `tuple`, but to be useful, it
+ /// must be a 2- to 10-tuple of `(u32, Arc<impl Strategy>)` pairs where all
+ /// strategies ultimately produce the same value. Each `u32` indicates the
+ /// relative weight of its corresponding strategy.
+ /// You may use `WA<S>` as an alias for `(u32, Arc<S>)`.
+ ///
+ /// Using this constructor directly is discouraged; prefer to use
+ /// `prop_oneof!` since it is generally clearer.
+ pub fn new(tuple: T) -> Self {
+ TupleUnion(tuple)
+ }
+}
+
+macro_rules! tuple_union {
+ ($($gen:ident $ix:tt)*) => {
+ impl<A : Strategy, $($gen: Strategy<Value = A::Value>),*>
+ Strategy for TupleUnion<(WA<A>, $(WA<$gen>),*)> {
+ type Tree = TupleUnionValueTree<
+ (LazyValueTree<A>, $(Option<LazyValueTree<$gen>>),*)>;
+ type Value = A::Value;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let weights = [((self.0).0).0, $(((self.0).$ix).0),*];
+ let pick = pick_weighted(runner, weights.iter().cloned(),
+ weights.iter().cloned());
+
+ Ok(TupleUnionValueTree {
+ options: (
+ if 0 == pick {
+ LazyValueTree::new_initialized(
+ ((self.0).0).1.new_tree(runner)?)
+ } else {
+ LazyValueTree::new(
+ Arc::clone(&((self.0).0).1), runner)
+ },
+ $(
+ if $ix == pick {
+ Some(LazyValueTree::new_initialized(
+ ((self.0).$ix).1.new_tree(runner)?))
+ } else if $ix < pick {
+ Some(LazyValueTree::new(
+ Arc::clone(&((self.0).$ix).1), runner))
+ } else {
+ None
+ }),*),
+ pick: pick,
+ min_pick: 0,
+ prev_pick: None,
+ })
+ }
+ }
+ }
+}
+
+tuple_union!(B 1);
+tuple_union!(B 1 C 2);
+tuple_union!(B 1 C 2 D 3);
+tuple_union!(B 1 C 2 D 3 E 4);
+tuple_union!(B 1 C 2 D 3 E 4 F 5);
+tuple_union!(B 1 C 2 D 3 E 4 F 5 G 6);
+tuple_union!(B 1 C 2 D 3 E 4 F 5 G 6 H 7);
+tuple_union!(B 1 C 2 D 3 E 4 F 5 G 6 H 7 I 8);
+tuple_union!(B 1 C 2 D 3 E 4 F 5 G 6 H 7 I 8 J 9);
+
+/// `ValueTree` type produced by `TupleUnion`.
+#[derive(Clone, Copy, Debug)]
+pub struct TupleUnionValueTree<T> {
+ options: T,
+ pick: usize,
+ min_pick: usize,
+ prev_pick: Option<usize>,
+}
+
+macro_rules! value_tree_tuple {
+ ($access:ident, $($gen:ident)*) => {
+ impl<A : Strategy, $($gen: Strategy<Value = A::Value>),*> ValueTree
+ for TupleUnionValueTree<
+ (LazyValueTree<A>, $(Option<LazyValueTree<$gen>>),*)
+ > {
+ lazy_union_value_tree_body!(A::Value, $access);
+ }
+ }
+}
+
+value_tree_tuple!(access_tuple2, B);
+value_tree_tuple!(access_tuple3, B C);
+value_tree_tuple!(access_tuple4, B C D);
+value_tree_tuple!(access_tuple5, B C D E);
+value_tree_tuple!(access_tuple6, B C D E F);
+value_tree_tuple!(access_tuple7, B C D E F G);
+value_tree_tuple!(access_tuple8, B C D E F G H);
+value_tree_tuple!(access_tuple9, B C D E F G H I);
+value_tree_tuple!(access_tupleA, B C D E F G H I J);
+
+const WEIGHT_BASE: u32 = 0x8000_0000;
+
+/// Convert a floating-point weight in the range (0.0,1.0) to a pair of weights
+/// that can be used with `Union` and similar.
+///
+/// The first return value is the weight corresponding to `f`; the second
+/// return value is the weight corresponding to `1.0 - f`.
+///
+/// This call does not make any guarantees as to what range of weights it may
+/// produce, except that adding the two return values will never overflow a
+/// `u32`. As such, it is generally not meaningful to combine any other weights
+/// with the two returned.
+///
+/// ## Panics
+///
+/// Panics if `f` is not a real number between 0.0 and 1.0, both exclusive.
+pub fn float_to_weight(f: f64) -> (u32, u32) {
+ assert!(f > 0.0 && f < 1.0, "Invalid probability: {}", f);
+
+ // Clamp to 1..WEIGHT_BASE-1 so that we never produce a weight of 0.
+ let pos = max(
+ 1,
+ min(WEIGHT_BASE - 1, (f * f64::from(WEIGHT_BASE)).round() as u32),
+ );
+ let neg = WEIGHT_BASE - pos;
+
+ (pos, neg)
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use crate::strategy::just::Just;
+
+ // FIXME(2018-06-01): figure out a way to run this test on no_std.
+ // The problem is that the default seed is fixed and does not produce
+ // enough passed tests. We need some universal source of non-determinism
+ // for the seed, which is unlikely.
+ #[cfg(feature = "std")]
+ #[test]
+ fn test_union() {
+ let input = (10u32..20u32).prop_union(30u32..40u32);
+ // Expect that 25% of cases pass (left input happens to be < 15, and
+ // left is chosen as initial value). Of the 75% that fail, 50% should
+ // converge to 15 and 50% to 30 (the latter because the left is beneath
+ // the passing threshold).
+ let mut passed = 0;
+ let mut converged_low = 0;
+ let mut converged_high = 0;
+ let mut runner = TestRunner::deterministic();
+ for _ in 0..256 {
+ let case = input.new_tree(&mut runner).unwrap();
+ let result = runner.run_one(case, |v| {
+ prop_assert!(v < 15);
+ Ok(())
+ });
+
+ match result {
+ Ok(true) => passed += 1,
+ Err(TestError::Fail(_, 15)) => converged_low += 1,
+ Err(TestError::Fail(_, 30)) => converged_high += 1,
+ e => panic!("Unexpected result: {:?}", e),
+ }
+ }
+
+ assert!(passed >= 32 && passed <= 96, "Bad passed count: {}", passed);
+ assert!(
+ converged_low >= 32 && converged_low <= 160,
+ "Bad converged_low count: {}",
+ converged_low
+ );
+ assert!(
+ converged_high >= 32 && converged_high <= 160,
+ "Bad converged_high count: {}",
+ converged_high
+ );
+ }
+
+ #[test]
+ fn test_union_weighted() {
+ let input = Union::new_weighted(vec![
+ (1, Just(0usize)),
+ (2, Just(1usize)),
+ (1, Just(2usize)),
+ ]);
+
+ let mut counts = [0, 0, 0];
+ let mut runner = TestRunner::deterministic();
+ for _ in 0..65536 {
+ counts[input.new_tree(&mut runner).unwrap().current()] += 1;
+ }
+
+ println!("{:?}", counts);
+ assert!(counts[0] > 0);
+ assert!(counts[2] > 0);
+ assert!(counts[1] > counts[0] * 3 / 2);
+ assert!(counts[1] > counts[2] * 3 / 2);
+ }
+
+ #[test]
+ fn test_union_sanity() {
+ check_strategy_sanity(
+ Union::new_weighted(vec![
+ (1, 0i32..100),
+ (2, 200i32..300),
+ (1, 400i32..500),
+ ]),
+ None,
+ );
+ }
+
+ // FIXME(2018-06-01): See note on `test_union`.
+ #[cfg(feature = "std")]
+ #[test]
+ fn test_tuple_union() {
+ let input = TupleUnion::new((
+ (1, Arc::new(10u32..20u32)),
+ (1, Arc::new(30u32..40u32)),
+ ));
+ // Expect that 25% of cases pass (left input happens to be < 15, and
+ // left is chosen as initial value). Of the 75% that fail, 50% should
+ // converge to 15 and 50% to 30 (the latter because the left is beneath
+ // the passing threshold).
+ let mut passed = 0;
+ let mut converged_low = 0;
+ let mut converged_high = 0;
+ let mut runner = TestRunner::deterministic();
+ for _ in 0..256 {
+ let case = input.new_tree(&mut runner).unwrap();
+ let result = runner.run_one(case, |v| {
+ prop_assert!(v < 15);
+ Ok(())
+ });
+
+ match result {
+ Ok(true) => passed += 1,
+ Err(TestError::Fail(_, 15)) => converged_low += 1,
+ Err(TestError::Fail(_, 30)) => converged_high += 1,
+ e => panic!("Unexpected result: {:?}", e),
+ }
+ }
+
+ assert!(passed >= 32 && passed <= 96, "Bad passed count: {}", passed);
+ assert!(
+ converged_low >= 32 && converged_low <= 160,
+ "Bad converged_low count: {}",
+ converged_low
+ );
+ assert!(
+ converged_high >= 32 && converged_high <= 160,
+ "Bad converged_high count: {}",
+ converged_high
+ );
+ }
+
+ #[test]
+ fn test_tuple_union_weighting() {
+ let input = TupleUnion::new((
+ (1, Arc::new(Just(0usize))),
+ (2, Arc::new(Just(1usize))),
+ (1, Arc::new(Just(2usize))),
+ ));
+
+ let mut counts = [0, 0, 0];
+ let mut runner = TestRunner::deterministic();
+ for _ in 0..65536 {
+ counts[input.new_tree(&mut runner).unwrap().current()] += 1;
+ }
+
+ println!("{:?}", counts);
+ assert!(counts[0] > 0);
+ assert!(counts[2] > 0);
+ assert!(counts[1] > counts[0] * 3 / 2);
+ assert!(counts[1] > counts[2] * 3 / 2);
+ }
+
+ #[test]
+ fn test_tuple_union_all_sizes() {
+ let mut runner = TestRunner::deterministic();
+ let r = Arc::new(1i32..10);
+
+ macro_rules! test {
+ ($($part:expr),*) => {{
+ let input = TupleUnion::new((
+ $((1, $part.clone())),*,
+ (1, Arc::new(Just(0i32)))
+ ));
+
+ let mut pass = false;
+ for _ in 0..1024 {
+ if 0 == input.new_tree(&mut runner).unwrap().current() {
+ pass = true;
+ break;
+ }
+ }
+
+ assert!(pass);
+ }}
+ }
+
+ test!(r); // 2
+ test!(r, r); // 3
+ test!(r, r, r); // 4
+ test!(r, r, r, r); // 5
+ test!(r, r, r, r, r); // 6
+ test!(r, r, r, r, r, r); // 7
+ test!(r, r, r, r, r, r, r); // 8
+ test!(r, r, r, r, r, r, r, r); // 9
+ test!(r, r, r, r, r, r, r, r, r); // 10
+ }
+
+ #[test]
+ fn test_tuple_union_sanity() {
+ check_strategy_sanity(
+ TupleUnion::new((
+ (1, Arc::new(0i32..100i32)),
+ (1, Arc::new(200i32..1000i32)),
+ (1, Arc::new(2000i32..3000i32)),
+ )),
+ None,
+ );
+ }
+
+ /// Test that unions work even if local filtering causes errors.
+ #[test]
+ fn test_filter_union_sanity() {
+ let filter_strategy = (0u32..256).prop_filter("!%5", |&v| 0 != v % 5);
+ check_strategy_sanity(
+ Union::new(vec![filter_strategy; 8]),
+ Some(filter_sanity_options()),
+ );
+ }
+
+ /// Test that tuple unions work even if local filtering causes errors.
+ #[test]
+ fn test_filter_tuple_union_sanity() {
+ let filter_strategy = (0u32..256).prop_filter("!%5", |&v| 0 != v % 5);
+ check_strategy_sanity(
+ TupleUnion::new((
+ (1, Arc::new(filter_strategy.clone())),
+ (1, Arc::new(filter_strategy.clone())),
+ (1, Arc::new(filter_strategy.clone())),
+ (1, Arc::new(filter_strategy.clone())),
+ )),
+ Some(filter_sanity_options()),
+ );
+ }
+
+ fn filter_sanity_options() -> CheckStrategySanityOptions {
+ CheckStrategySanityOptions {
+ // Due to internal rejection sampling, `simplify()` can
+ // converge back to what `complicate()` would do.
+ strict_complicate_after_simplify: false,
+ // Make failed filters return errors to test edge cases.
+ error_on_local_rejects: true,
+ ..CheckStrategySanityOptions::default()
+ }
+ }
+}
diff --git a/vendor/proptest/src/string.rs b/vendor/proptest/src/string.rs
new file mode 100644
index 000000000..195d75077
--- /dev/null
+++ b/vendor/proptest/src/string.rs
@@ -0,0 +1,560 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+//! Strategies for generating strings and byte strings from regular
+//! expressions.
+
+use crate::std_facade::{Box, Cow, String, ToOwned, Vec};
+use core::fmt;
+use core::mem;
+use core::ops::RangeInclusive;
+use core::u32;
+
+use regex_syntax::hir::{
+ self, Hir,
+ HirKind::*,
+ Literal::*,
+ RepetitionKind::{self, *},
+ RepetitionRange::*,
+};
+use regex_syntax::{Error as ParseError, Parser};
+
+use crate::bool;
+use crate::char;
+use crate::collection::{size_range, vec, SizeRange};
+use crate::strategy::*;
+use crate::test_runner::*;
+
+/// Wraps the regex that forms the `Strategy` for `String` so that a sensible
+/// `Default` can be given. The default is a string of non-control characters.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct StringParam(&'static str);
+
+impl From<StringParam> for &'static str {
+ fn from(x: StringParam) -> Self {
+ x.0
+ }
+}
+
+impl From<&'static str> for StringParam {
+ fn from(x: &'static str) -> Self {
+ StringParam(x)
+ }
+}
+
+impl Default for StringParam {
+ fn default() -> Self {
+ StringParam("\\PC*")
+ }
+}
+
+// quick_error! uses bare trait objects, so we enclose its invocation here in a
+// module so the lint can be disabled just for it.
+#[allow(bare_trait_objects)]
+mod error_container {
+ use super::*;
+
+ quick_error! {
+ /// Errors which may occur when preparing a regular expression for use with
+ /// string generation.
+ #[derive(Debug)]
+ pub enum Error {
+ /// The string passed as the regex was not syntactically valid.
+ RegexSyntax(err: ParseError) {
+ from()
+ source(err)
+ display("{}", err)
+ }
+ /// The regex was syntactically valid, but contains elements not
+ /// supported by proptest.
+ UnsupportedRegex(message: &'static str) {
+ display("{}", message)
+ }
+ }
+ }
+}
+
+pub use self::error_container::Error;
+
+opaque_strategy_wrapper! {
+ /// Strategy which generates values (i.e., `String` or `Vec<u8>`) matching
+ /// a regular expression.
+ ///
+ /// Created by various functions in this module.
+ #[derive(Debug)]
+ pub struct RegexGeneratorStrategy[<T>][where T : fmt::Debug]
+ (SBoxedStrategy<T>) -> RegexGeneratorValueTree<T>;
+ /// `ValueTree` corresponding to `RegexGeneratorStrategy`.
+ pub struct RegexGeneratorValueTree[<T>][where T : fmt::Debug]
+ (Box<dyn ValueTree<Value = T>>) -> T;
+}
+
+impl Strategy for str {
+ type Tree = RegexGeneratorValueTree<String>;
+ type Value = String;
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ string_regex(self).unwrap().new_tree(runner)
+ }
+}
+
+type ParseResult<T> = Result<RegexGeneratorStrategy<T>, Error>;
+
+#[doc(hidden)]
+/// A type which knows how to produce a `Strategy` from a regular expression
+/// generating the type.
+///
+/// This trait exists for the benefit of `#[proptest(regex = "...")]`.
+/// It is semver exempt, so use at your own risk.
+/// If you found a use for the trait beyond `Vec<u8>` and `String`,
+/// please file an issue at https://github.com/AltSysrq/proptest.
+pub trait StrategyFromRegex: Sized + fmt::Debug {
+ type Strategy: Strategy<Value = Self>;
+
+ /// Produce a strategy for `Self` from the `regex`.
+ fn from_regex(regex: &str) -> Self::Strategy;
+}
+
+impl StrategyFromRegex for String {
+ type Strategy = RegexGeneratorStrategy<Self>;
+
+ fn from_regex(regex: &str) -> Self::Strategy {
+ string_regex(regex).unwrap()
+ }
+}
+
+impl StrategyFromRegex for Vec<u8> {
+ type Strategy = RegexGeneratorStrategy<Self>;
+
+ fn from_regex(regex: &str) -> Self::Strategy {
+ bytes_regex(regex).unwrap()
+ }
+}
+
+/// Creates a strategy which generates strings matching the given regular
+/// expression.
+///
+/// If you don't need error handling and aren't limited by setup time, it is
+/// also possible to directly use a `&str` as a strategy with the same effect.
+pub fn string_regex(regex: &str) -> ParseResult<String> {
+ string_regex_parsed(&regex_to_hir(regex)?)
+}
+
+/// Like `string_regex()`, but allows providing a pre-parsed expression.
+pub fn string_regex_parsed(expr: &Hir) -> ParseResult<String> {
+ bytes_regex_parsed(expr)
+ .map(|v| {
+ v.prop_map(|bytes| {
+ String::from_utf8(bytes).expect("non-utf8 string")
+ })
+ .sboxed()
+ })
+ .map(RegexGeneratorStrategy)
+}
+
+/// Creates a strategy which generates byte strings matching the given regular
+/// expression.
+pub fn bytes_regex(regex: &str) -> ParseResult<Vec<u8>> {
+ bytes_regex_parsed(&regex_to_hir(regex)?)
+}
+
+/// Like `bytes_regex()`, but allows providing a pre-parsed expression.
+pub fn bytes_regex_parsed(expr: &Hir) -> ParseResult<Vec<u8>> {
+ match expr.kind() {
+ Empty => Ok(Just(vec![]).sboxed()),
+
+ Literal(lit) => Ok(Just(match lit {
+ Unicode(scalar) => to_bytes(*scalar),
+ Byte(byte) => vec![*byte],
+ })
+ .sboxed()),
+
+ Class(class) => Ok(match class {
+ hir::Class::Unicode(class) => {
+ unicode_class_strategy(class).prop_map(to_bytes).sboxed()
+ }
+ hir::Class::Bytes(class) => {
+ let subs = class.iter().map(|r| r.start()..=r.end());
+ Union::new(subs).prop_map(|b| vec![b]).sboxed()
+ }
+ }),
+
+ Repetition(rep) => Ok(vec(
+ bytes_regex_parsed(&rep.hir)?,
+ to_range(rep.kind.clone())?,
+ )
+ .prop_map(|parts| {
+ parts.into_iter().fold(vec![], |mut acc, child| {
+ acc.extend(child);
+ acc
+ })
+ })
+ .sboxed()),
+
+ Group(group) => bytes_regex_parsed(&group.hir).map(|v| v.0),
+
+ Concat(subs) => {
+ let subs = ConcatIter {
+ iter: subs.iter(),
+ buf: vec![],
+ next: None,
+ };
+ let ext = |(mut lhs, rhs): (Vec<_>, _)| {
+ lhs.extend(rhs);
+ lhs
+ };
+ Ok(subs
+ .fold(Ok(None), |accum: Result<_, Error>, rhs| {
+ Ok(match accum? {
+ None => Some(rhs?.sboxed()),
+ Some(accum) => {
+ Some((accum, rhs?).prop_map(ext).sboxed())
+ }
+ })
+ })?
+ .unwrap_or_else(|| Just(vec![]).sboxed()))
+ }
+
+ Alternation(subs) => {
+ Ok(Union::try_new(subs.iter().map(bytes_regex_parsed))?.sboxed())
+ }
+
+ Anchor(_) => {
+ unsupported("line/text anchors not supported for string generation")
+ }
+
+ WordBoundary(_) => unsupported(
+ "word boundary tests not supported for string generation",
+ ),
+ }
+ .map(RegexGeneratorStrategy)
+}
+
+fn unicode_class_strategy(
+ class: &hir::ClassUnicode,
+) -> char::CharStrategy<'static> {
+ static NONL_RANGES: &[RangeInclusive<char>] = &[
+ '\x00'..='\x09',
+ // Multiple instances of the latter range to partially make up
+ // for the bias of having such a tiny range in the control
+ // characters.
+ '\x0B'..=::core::char::MAX,
+ '\x0B'..=::core::char::MAX,
+ '\x0B'..=::core::char::MAX,
+ '\x0B'..=::core::char::MAX,
+ '\x0B'..=::core::char::MAX,
+ ];
+
+ let dotnnl = |x: &hir::ClassUnicodeRange, y: &hir::ClassUnicodeRange| {
+ x.start() == '\0'
+ && x.end() == '\x09'
+ && y.start() == '\x0B'
+ && y.end() == '\u{10FFFF}'
+ };
+
+ char::ranges(match class.ranges() {
+ [x, y] if dotnnl(x, y) || dotnnl(y, x) => Cow::Borrowed(NONL_RANGES),
+ _ => Cow::Owned(class.iter().map(|r| r.start()..=r.end()).collect()),
+ })
+}
+
+struct ConcatIter<'a, I> {
+ buf: Vec<u8>,
+ iter: I,
+ next: Option<&'a Hir>,
+}
+
+fn flush_lit_buf<I>(
+ it: &mut ConcatIter<'_, I>,
+) -> Option<ParseResult<Vec<u8>>> {
+ Some(Ok(RegexGeneratorStrategy(
+ Just(mem::replace(&mut it.buf, vec![])).sboxed(),
+ )))
+}
+
+impl<'a, I: Iterator<Item = &'a Hir>> Iterator for ConcatIter<'a, I> {
+ type Item = ParseResult<Vec<u8>>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // A left-over node, process it first:
+ if let Some(next) = self.next.take() {
+ return Some(bytes_regex_parsed(next));
+ }
+
+ // Accumulate a literal sequence as long as we can:
+ while let Some(next) = self.iter.next() {
+ match next.kind() {
+ // A literal. Accumulate:
+ Literal(Unicode(scalar)) => self.buf.extend(to_bytes(*scalar)),
+ Literal(Byte(byte)) => self.buf.push(*byte),
+ // Encountered a non-literal.
+ _ => {
+ return if !self.buf.is_empty() {
+ // We've accumulated a literal from before, flush it out.
+ // Store this node so we deal with it the next call.
+ self.next = Some(next);
+ flush_lit_buf(self)
+ } else {
+ // We didn't; just yield this node.
+ Some(bytes_regex_parsed(next))
+ };
+ }
+ }
+ }
+
+ // Flush out any accumulated literal from before.
+ if !self.buf.is_empty() {
+ flush_lit_buf(self)
+ } else {
+ self.next.take().map(bytes_regex_parsed)
+ }
+ }
+}
+
+fn to_range(kind: RepetitionKind) -> Result<SizeRange, Error> {
+ Ok(match kind {
+ ZeroOrOne => size_range(0..=1),
+ ZeroOrMore => size_range(0..=32),
+ OneOrMore => size_range(1..=32),
+ Range(range) => match range {
+ Exactly(count) if u32::MAX == count => {
+ return unsupported(
+ "Cannot have repetition of exactly u32::MAX",
+ )
+ }
+ Exactly(count) => size_range(count as usize),
+ AtLeast(min) => {
+ let max = if min < u32::MAX as u32 / 2 {
+ min as usize * 2
+ } else {
+ u32::MAX as usize
+ };
+ size_range((min as usize)..max)
+ }
+ Bounded(_, max) if u32::MAX == max => {
+ return unsupported("Cannot have repetition max of u32::MAX")
+ }
+ Bounded(min, max) => size_range((min as usize)..(max as usize + 1)),
+ },
+ })
+}
+
+fn to_bytes(khar: char) -> Vec<u8> {
+ let mut buf = [0u8; 4];
+ khar.encode_utf8(&mut buf).as_bytes().to_owned()
+}
+
+fn regex_to_hir(pattern: &str) -> Result<Hir, Error> {
+ Ok(Parser::new().parse(pattern)?)
+}
+
+fn unsupported<T>(error: &'static str) -> Result<T, Error> {
+ Err(Error::UnsupportedRegex(error))
+}
+
+#[cfg(test)]
+mod test {
+ use std::collections::HashSet;
+
+ use regex::Regex;
+
+ use super::*;
+
+ fn do_test(
+ pattern: &str,
+ min_distinct: usize,
+ max_distinct: usize,
+ iterations: usize,
+ ) {
+ let generated = generate_values_matching_regex(pattern, iterations);
+ assert!(
+ generated.len() >= min_distinct,
+ "Expected to generate at least {} strings, but only \
+ generated {}",
+ min_distinct,
+ generated.len()
+ );
+ assert!(
+ generated.len() <= max_distinct,
+ "Expected to generate at most {} strings, but \
+ generated {}",
+ max_distinct,
+ generated.len()
+ );
+ }
+
+ fn generate_values_matching_regex(
+ pattern: &str,
+ iterations: usize,
+ ) -> HashSet<String> {
+ let rx = Regex::new(pattern).unwrap();
+ let mut generated = HashSet::new();
+
+ let strategy = string_regex(pattern).unwrap();
+ let mut runner = TestRunner::deterministic();
+ for _ in 0..iterations {
+ let mut value = strategy.new_tree(&mut runner).unwrap();
+
+ loop {
+ let s = value.current();
+ let ok = if let Some(matsch) = rx.find(&s) {
+ 0 == matsch.start() && s.len() == matsch.end()
+ } else {
+ false
+ };
+ if !ok {
+ panic!(
+ "Generated string {:?} which does not match {:?}",
+ s, pattern
+ );
+ }
+
+ generated.insert(s);
+
+ if !value.simplify() {
+ break;
+ }
+ }
+ }
+ generated
+ }
+
+ #[test]
+ fn test_case_insensitive_produces_all_available_values() {
+ let mut expected: HashSet<String> = HashSet::new();
+ expected.insert("a".into());
+ expected.insert("b".into());
+ expected.insert("A".into());
+ expected.insert("B".into());
+ assert_eq!(generate_values_matching_regex("(?i:a|B)", 64), expected);
+ }
+
+ #[test]
+ fn test_literal() {
+ do_test("foo", 1, 1, 8);
+ }
+
+ #[test]
+ fn test_casei_literal() {
+ do_test("(?i:fOo)", 8, 8, 64);
+ }
+
+ #[test]
+ fn test_alternation() {
+ do_test("foo|bar|baz", 3, 3, 16);
+ }
+
+ #[test]
+ fn test_repitition() {
+ do_test("a{0,8}", 9, 9, 64);
+ }
+
+ #[test]
+ fn test_question() {
+ do_test("a?", 2, 2, 16);
+ }
+
+ #[test]
+ fn test_star() {
+ do_test("a*", 33, 33, 256);
+ }
+
+ #[test]
+ fn test_plus() {
+ do_test("a+", 32, 32, 256);
+ }
+
+ #[test]
+ fn test_n_to_range() {
+ do_test("a{4,}", 4, 4, 64);
+ }
+
+ #[test]
+ fn test_concatenation() {
+ do_test("(foo|bar)(xyzzy|plugh)", 4, 4, 32);
+ }
+
+ #[test]
+ fn test_ascii_class() {
+ do_test("[[:digit:]]", 10, 10, 256);
+ }
+
+ #[test]
+ fn test_unicode_class() {
+ do_test("\\p{Greek}", 24, 512, 256);
+ }
+
+ #[test]
+ fn test_dot() {
+ do_test(".", 200, 65536, 256);
+ }
+
+ #[test]
+ fn test_dot_s() {
+ do_test("(?s).", 200, 65536, 256);
+ }
+
+ #[test]
+ fn test_backslash_d_plus() {
+ do_test("\\d+", 1, 65536, 256);
+ }
+
+ fn assert_send_and_sync<T: Send + Sync>(_: T) {}
+
+ #[test]
+ fn regex_strategy_is_send_and_sync() {
+ assert_send_and_sync(string_regex(".").unwrap());
+ }
+
+ macro_rules! consistent {
+ ($name:ident, $value:expr) => {
+ #[test]
+ fn $name() {
+ test_generates_matching_strings($value);
+ }
+ };
+ }
+
+ fn test_generates_matching_strings(pattern: &str) {
+ use std::time;
+
+ let mut runner = TestRunner::default();
+ let start = time::Instant::now();
+
+ // If we don't support this regex, just move on quietly
+ if let Ok(strategy) = string_regex(pattern) {
+ let rx = Regex::new(pattern).unwrap();
+
+ for _ in 0..1000 {
+ let mut val = strategy.new_tree(&mut runner).unwrap();
+ // No more than 1000 simplify steps to keep test time down
+ for _ in 0..1000 {
+ let s = val.current();
+ assert!(
+ rx.is_match(&s),
+ "Produced string {:?}, which does not match {:?}",
+ s,
+ pattern
+ );
+
+ if !val.simplify() {
+ break;
+ }
+ }
+
+ // Quietly stop testing if we've run for >10 s
+ if start.elapsed().as_secs() > 10 {
+ break;
+ }
+ }
+ }
+ }
+
+ include!("regex-contrib/crates_regex.rs");
+}
diff --git a/vendor/proptest/src/sugar.rs b/vendor/proptest/src/sugar.rs
new file mode 100644
index 000000000..42ba5c194
--- /dev/null
+++ b/vendor/proptest/src/sugar.rs
@@ -0,0 +1,1637 @@
+//-
+// Copyright 2017, 2019 The proptest 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.
+
+use crate::std_facade::fmt;
+
+/// Easily define `proptest` tests.
+///
+/// Within `proptest!`, define one or more functions without return type
+/// normally, except instead of putting `: type` after each parameter, write
+/// `in strategy`, where `strategy` is an expression evaluating to some
+/// `Strategy`.
+///
+/// Each function will be wrapped in a function which sets up a `TestRunner`,
+/// and then invokes the function body with inputs generated according to the
+/// strategies.
+///
+/// ### Example
+///
+/// ```
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// # /*
+/// #[test]
+/// # */
+/// fn test_addition(a in 0..10, b in 0..10) {
+/// prop_assert!(a + b <= 18);
+/// }
+///
+/// # /*
+/// #[test]
+/// # */
+/// fn test_string_concat(a in ".*", b in ".*") {
+/// let cat = format!("{}{}", a, b);
+/// prop_assert_eq!(a.len() + b.len(), cat.len());
+/// }
+/// }
+/// #
+/// # fn main() { test_addition(); test_string_concat(); }
+/// ```
+///
+/// You can also use the normal argument syntax `pattern: type` as in:
+///
+/// ```rust
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// # /*
+/// #[test]
+/// # */
+/// fn addition_is_commutative(a: u8, b: u8) {
+/// prop_assert_eq!(a as u16 + b as u16, b as u16 + a as u16);
+/// }
+///
+/// # /*
+/// #[test]
+/// # */
+/// fn test_string_concat(a in ".*", b: String) {
+/// let cat = format!("{}{}", a, b);
+/// prop_assert_eq!(a.len() + b.len(), cat.len());
+/// }
+/// }
+/// #
+/// # fn main() { addition_is_commutative(); test_string_concat(); }
+/// ```
+///
+/// As you can see, you can mix `pattern: type` and `pattern in expr`.
+/// Due to limitations in `macro_rules!`, `pattern: type` does not work in
+/// all circumstances. In such a case, use `(pattern): type` instead.
+///
+/// To override the default configuration, you can start the `proptest!` block
+/// with `#![proptest_config(expr)]`, where `expr` is an expression that
+/// evaluates to a `proptest::test_runner::Config` (or a reference to one).
+///
+/// ```
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// #![proptest_config(ProptestConfig {
+/// cases: 99, .. ProptestConfig::default()
+/// })]
+/// # /*
+/// #[test]
+/// # */
+/// fn test_addition(a in 0..10, b in 0..10) {
+/// prop_assert!(a + b <= 18);
+/// }
+/// }
+/// #
+/// # fn main() { test_addition(); }
+/// ```
+///
+/// ## Closure-Style Invocation
+///
+/// As of proptest 0.8.1, an alternative, "closure-style" invocation is
+/// supported. In this form, `proptest!` is a function-like macro taking a
+/// closure-esque argument. This makes it possible to run multiple tests that
+/// require some expensive setup process. Note that the "fork" and "timeout"
+/// features are _not_ supported in closure style.
+///
+/// To use a custom configuration, pass the `Config` object as a first
+/// argument.
+///
+/// ### Example
+///
+/// ```
+/// use proptest::prelude::*;
+///
+/// #[derive(Debug)]
+/// struct BigStruct { /* Lots of fields ... */ }
+///
+/// fn very_expensive_function() -> BigStruct {
+/// // Lots of code...
+/// BigStruct { /* fields */ }
+/// }
+///
+/// # /*
+/// #[test]
+/// # */
+/// fn my_test() {
+/// // We create just one `BigStruct`
+/// let big_struct = very_expensive_function();
+///
+/// // But now can run multiple tests without needing to build it every time.
+/// // Note the extra parentheses around the arguments are currently
+/// // required.
+/// proptest!(|(x in 0u32..42u32, y in 1000u32..100000u32)| {
+/// // Test stuff
+/// });
+///
+/// // `move` closures are also supported
+/// proptest!(move |(x in 0u32..42u32)| {
+/// // Test other stuff
+/// });
+///
+/// // You can pass a custom configuration as the first argument
+/// proptest!(ProptestConfig::with_cases(1000), |(x: i32)| {
+/// // Test more stuff
+/// });
+/// }
+/// #
+/// # fn main() { my_test(); }
+/// ```
+#[macro_export]
+macro_rules! proptest {
+ (#![proptest_config($config:expr)]
+ $(
+ $(#[$meta:meta])*
+ fn $test_name:ident($($parm:pat in $strategy:expr),+ $(,)?) $body:block
+ )*) => {
+ $(
+ $(#[$meta])*
+ fn $test_name() {
+ let mut config = $config.clone();
+ config.test_name = Some(
+ concat!(module_path!(), "::", stringify!($test_name)));
+ $crate::proptest_helper!(@_BODY config ($($parm in $strategy),+) [] $body);
+ }
+ )*
+ };
+ (#![proptest_config($config:expr)]
+ $(
+ $(#[$meta:meta])*
+ fn $test_name:ident($($arg:tt)+) $body:block
+ )*) => {
+ $(
+ $(#[$meta])*
+ fn $test_name() {
+ let mut config = $config.clone();
+ config.test_name = Some(
+ concat!(module_path!(), "::", stringify!($test_name)));
+ $crate::proptest_helper!(@_BODY2 config ($($arg)+) [] $body);
+ }
+ )*
+ };
+
+ ($(
+ $(#[$meta:meta])*
+ fn $test_name:ident($($parm:pat in $strategy:expr),+ $(,)?) $body:block
+ )*) => { $crate::proptest! {
+ #![proptest_config($crate::test_runner::Config::default())]
+ $($(#[$meta])*
+ fn $test_name($($parm in $strategy),+) $body)*
+ } };
+
+ ($(
+ $(#[$meta:meta])*
+ fn $test_name:ident($($arg:tt)+) $body:block
+ )*) => { $crate::proptest! {
+ #![proptest_config($crate::test_runner::Config::default())]
+ $($(#[$meta])*
+ fn $test_name($($arg)+) $body)*
+ } };
+
+ (|($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => {
+ $crate::proptest!(
+ $crate::test_runner::Config::default(),
+ |($($parm in $strategy),+)| $body)
+ };
+
+ (move |($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => {
+ $crate::proptest!(
+ $crate::test_runner::Config::default(),
+ move |($($parm in $strategy),+)| $body)
+ };
+
+ (|($($arg:tt)+)| $body:expr) => {
+ $crate::proptest!(
+ $crate::test_runner::Config::default(),
+ |($($arg)+)| $body)
+ };
+
+ (move |($($arg:tt)+)| $body:expr) => {
+ $crate::proptest!(
+ $crate::test_runner::Config::default(),
+ move |($($arg)+)| $body)
+ };
+
+ ($config:expr, |($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => { {
+ let mut config = $config.__sugar_to_owned();
+ $crate::sugar::force_no_fork(&mut config);
+ $crate::proptest_helper!(@_BODY config ($($parm in $strategy),+) [] $body)
+ } };
+
+ ($config:expr, move |($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => { {
+ let mut config = $config.__sugar_to_owned();
+ $crate::sugar::force_no_fork(&mut config);
+ $crate::proptest_helper!(@_BODY config ($($parm in $strategy),+) [move] $body)
+ } };
+
+ ($config:expr, |($($arg:tt)+)| $body:expr) => { {
+ let mut config = $config.__sugar_to_owned();
+ $crate::sugar::force_no_fork(&mut config);
+ $crate::proptest_helper!(@_BODY2 config ($($arg)+) [] $body);
+ } };
+
+ ($config:expr, move |($($arg:tt)+)| $body:expr) => { {
+ let mut config = $config.__sugar_to_owned();
+ $crate::sugar::force_no_fork(&mut config);
+ $crate::proptest_helper!(@_BODY2 config ($($arg)+) [move] $body);
+ } };
+}
+
+/// Rejects the test input if assumptions are not met.
+///
+/// Used directly within a function defined with `proptest!` or in any function
+/// returning `Result<_, TestCaseError>`.
+///
+/// This is invoked as `prop_assume!(condition, format, args...)`. `condition`
+/// is evaluated; if it is false, `Err(TestCaseError::Reject)` is returned. The
+/// message includes the point of invocation and the format message. `format`
+/// and `args` may be omitted to simply use the condition itself as the
+/// message.
+#[macro_export]
+macro_rules! prop_assume {
+ ($expr:expr) => {
+ $crate::prop_assume!($expr, "{}", stringify!($expr))
+ };
+
+ ($expr:expr, $fmt:tt $(, $fmt_arg:expr),* $(,)?) => {
+ if !$expr {
+ return ::core::result::Result::Err(
+ $crate::test_runner::TestCaseError::reject(
+ format!(concat!("{}:{}:{}: ", $fmt),
+ file!(), line!(), column!()
+ $(, $fmt_arg)*)));
+ }
+ };
+}
+
+/// Produce a strategy which picks one of the listed choices.
+///
+/// This is conceptually equivalent to calling `prop_union` on the first two
+/// elements and then chaining `.or()` onto the rest after implicitly boxing
+/// all of them. As with `Union`, values shrink across elements on the
+/// assumption that earlier ones are "simpler", so they should be listed in
+/// order of ascending complexity when possible.
+///
+/// The macro invocation has two forms. The first is to simply list the
+/// strategies separated by commas; this will cause value generation to pick
+/// from the strategies uniformly. The other form is to provide a weight in the
+/// form of a `u32` before each strategy, separated from the strategy with
+/// `=>`.
+///
+/// Note that the exact type returned by the macro varies depending on how many
+/// inputs there are. In particular, if given exactly one option, it will
+/// return it unmodified. It is not recommended to depend on the particular
+/// type produced by this macro.
+///
+/// ## Example
+///
+/// ```rust,no_run
+/// use proptest::prelude::*;
+///
+/// #[derive(Clone, Copy, Debug)]
+/// enum MyEnum {
+/// Big(u64),
+/// Medium(u32),
+/// Little(i16),
+/// }
+///
+/// # #[allow(unused_variables)]
+/// # fn main() {
+/// let my_enum_strategy = prop_oneof![
+/// prop::num::i16::ANY.prop_map(MyEnum::Little),
+/// prop::num::u32::ANY.prop_map(MyEnum::Medium),
+/// prop::num::u64::ANY.prop_map(MyEnum::Big),
+/// ];
+///
+/// let my_weighted_strategy = prop_oneof![
+/// 1 => prop::num::i16::ANY.prop_map(MyEnum::Little),
+/// // Chose `Medium` twice as frequently as either `Little` or `Big`; i.e.,
+/// // around 50% of values will be `Medium`, and 25% for each of `Little`
+/// // and `Big`.
+/// 2 => prop::num::u32::ANY.prop_map(MyEnum::Medium),
+/// 1 => prop::num::u64::ANY.prop_map(MyEnum::Big),
+/// ];
+/// # }
+/// ```
+#[macro_export]
+macro_rules! prop_oneof {
+ ($($item:expr),+ $(,)?) => {
+ $crate::prop_oneof![
+ $(1 => $item),*
+ ]
+ };
+
+ ($_weight0:expr => $item0:expr $(,)?) => { $item0 };
+
+ ($weight0:expr => $item0:expr,
+ $weight1:expr => $item1:expr $(,)?) => {
+ $crate::strategy::TupleUnion::new(
+ (($weight0, $crate::std_facade::Arc::new($item0)),
+ ($weight1, $crate::std_facade::Arc::new($item1))))
+ };
+
+ ($weight0:expr => $item0:expr,
+ $weight1:expr => $item1:expr,
+ $weight2:expr => $item2:expr $(,)?) => {
+ $crate::strategy::TupleUnion::new(
+ (($weight0, $crate::std_facade::Arc::new($item0)),
+ ($weight1, $crate::std_facade::Arc::new($item1)),
+ ($weight2, $crate::std_facade::Arc::new($item2))))
+ };
+
+ ($weight0:expr => $item0:expr,
+ $weight1:expr => $item1:expr,
+ $weight2:expr => $item2:expr,
+ $weight3:expr => $item3:expr $(,)?) => {
+ $crate::strategy::TupleUnion::new(
+ (($weight0, $crate::std_facade::Arc::new($item0)),
+ ($weight1, $crate::std_facade::Arc::new($item1)),
+ ($weight2, $crate::std_facade::Arc::new($item2)),
+ ($weight3, $crate::std_facade::Arc::new($item3))))
+ };
+
+ ($weight0:expr => $item0:expr,
+ $weight1:expr => $item1:expr,
+ $weight2:expr => $item2:expr,
+ $weight3:expr => $item3:expr,
+ $weight4:expr => $item4:expr $(,)?) => {
+ $crate::strategy::TupleUnion::new(
+ (($weight0, $crate::std_facade::Arc::new($item0)),
+ ($weight1, $crate::std_facade::Arc::new($item1)),
+ ($weight2, $crate::std_facade::Arc::new($item2)),
+ ($weight3, $crate::std_facade::Arc::new($item3)),
+ ($weight4, $crate::std_facade::Arc::new($item4))))
+ };
+
+ ($weight0:expr => $item0:expr,
+ $weight1:expr => $item1:expr,
+ $weight2:expr => $item2:expr,
+ $weight3:expr => $item3:expr,
+ $weight4:expr => $item4:expr,
+ $weight5:expr => $item5:expr $(,)?) => {
+ $crate::strategy::TupleUnion::new(
+ (($weight0, $crate::std_facade::Arc::new($item0)),
+ ($weight1, $crate::std_facade::Arc::new($item1)),
+ ($weight2, $crate::std_facade::Arc::new($item2)),
+ ($weight3, $crate::std_facade::Arc::new($item3)),
+ ($weight4, $crate::std_facade::Arc::new($item4)),
+ ($weight5, $crate::std_facade::Arc::new($item5))))
+ };
+
+ ($weight0:expr => $item0:expr,
+ $weight1:expr => $item1:expr,
+ $weight2:expr => $item2:expr,
+ $weight3:expr => $item3:expr,
+ $weight4:expr => $item4:expr,
+ $weight5:expr => $item5:expr,
+ $weight6:expr => $item6:expr $(,)?) => {
+ $crate::strategy::TupleUnion::new(
+ (($weight0, $crate::std_facade::Arc::new($item0)),
+ ($weight1, $crate::std_facade::Arc::new($item1)),
+ ($weight2, $crate::std_facade::Arc::new($item2)),
+ ($weight3, $crate::std_facade::Arc::new($item3)),
+ ($weight4, $crate::std_facade::Arc::new($item4)),
+ ($weight5, $crate::std_facade::Arc::new($item5)),
+ ($weight6, $crate::std_facade::Arc::new($item6))))
+ };
+
+ ($weight0:expr => $item0:expr,
+ $weight1:expr => $item1:expr,
+ $weight2:expr => $item2:expr,
+ $weight3:expr => $item3:expr,
+ $weight4:expr => $item4:expr,
+ $weight5:expr => $item5:expr,
+ $weight6:expr => $item6:expr,
+ $weight7:expr => $item7:expr $(,)?) => {
+ $crate::strategy::TupleUnion::new(
+ (($weight0, $crate::std_facade::Arc::new($item0)),
+ ($weight1, $crate::std_facade::Arc::new($item1)),
+ ($weight2, $crate::std_facade::Arc::new($item2)),
+ ($weight3, $crate::std_facade::Arc::new($item3)),
+ ($weight4, $crate::std_facade::Arc::new($item4)),
+ ($weight5, $crate::std_facade::Arc::new($item5)),
+ ($weight6, $crate::std_facade::Arc::new($item6)),
+ ($weight7, $crate::std_facade::Arc::new($item7))))
+ };
+
+ ($weight0:expr => $item0:expr,
+ $weight1:expr => $item1:expr,
+ $weight2:expr => $item2:expr,
+ $weight3:expr => $item3:expr,
+ $weight4:expr => $item4:expr,
+ $weight5:expr => $item5:expr,
+ $weight6:expr => $item6:expr,
+ $weight7:expr => $item7:expr,
+ $weight8:expr => $item8:expr $(,)?) => {
+ $crate::strategy::TupleUnion::new(
+ (($weight0, $crate::std_facade::Arc::new($item0)),
+ ($weight1, $crate::std_facade::Arc::new($item1)),
+ ($weight2, $crate::std_facade::Arc::new($item2)),
+ ($weight3, $crate::std_facade::Arc::new($item3)),
+ ($weight4, $crate::std_facade::Arc::new($item4)),
+ ($weight5, $crate::std_facade::Arc::new($item5)),
+ ($weight6, $crate::std_facade::Arc::new($item6)),
+ ($weight7, $crate::std_facade::Arc::new($item7)),
+ ($weight8, $crate::std_facade::Arc::new($item8))))
+ };
+
+ ($weight0:expr => $item0:expr,
+ $weight1:expr => $item1:expr,
+ $weight2:expr => $item2:expr,
+ $weight3:expr => $item3:expr,
+ $weight4:expr => $item4:expr,
+ $weight5:expr => $item5:expr,
+ $weight6:expr => $item6:expr,
+ $weight7:expr => $item7:expr,
+ $weight8:expr => $item8:expr,
+ $weight9:expr => $item9:expr $(,)?) => {
+ $crate::strategy::TupleUnion::new(
+ (($weight0, $crate::std_facade::Arc::new($item0)),
+ ($weight1, $crate::std_facade::Arc::new($item1)),
+ ($weight2, $crate::std_facade::Arc::new($item2)),
+ ($weight3, $crate::std_facade::Arc::new($item3)),
+ ($weight4, $crate::std_facade::Arc::new($item4)),
+ ($weight5, $crate::std_facade::Arc::new($item5)),
+ ($weight6, $crate::std_facade::Arc::new($item6)),
+ ($weight7, $crate::std_facade::Arc::new($item7)),
+ ($weight8, $crate::std_facade::Arc::new($item8)),
+ ($weight9, $crate::std_facade::Arc::new($item9))))
+ };
+
+ ($($weight:expr => $item:expr),+ $(,)?) => {
+ $crate::strategy::Union::new_weighted(vec![
+ $(($weight, $crate::strategy::Strategy::boxed($item))),*
+ ])
+ };
+}
+
+/// Convenience to define functions which produce new strategies.
+///
+/// The macro has two general forms. In the first, you define a function with
+/// two argument lists. The first argument list uses the usual syntax and
+/// becomes exactly the argument list of the defined function. The second
+/// argument list uses the `in strategy` syntax as with `proptest!`, and is
+/// used to generate the other inputs for the function. The second argument
+/// list has access to all arguments in the first. The return type indicates
+/// the type of value being generated; the final return type of the function is
+/// `impl Strategy<Value = $type>`.
+///
+/// ```rust,no_run
+/// # #![allow(dead_code)]
+/// use proptest::prelude::*;
+///
+/// #[derive(Clone, Debug)]
+/// struct MyStruct {
+/// integer: u32,
+/// string: String,
+/// }
+///
+/// prop_compose! {
+/// fn my_struct_strategy(max_integer: u32)
+/// (integer in 0..max_integer, string in ".*")
+/// -> MyStruct {
+/// MyStruct { integer, string }
+/// }
+/// }
+/// #
+/// # fn main() { }
+/// ```
+///
+/// This form is simply sugar around making a tuple and then calling `prop_map`
+/// on it. You can also use `arg: type` as in `proptest! { .. }`:
+///
+/// ```rust,no_run
+/// # #![allow(dead_code)]
+/// # use proptest::prelude::*;
+/// #
+/// # #[derive(Clone, Debug)]
+/// # struct MyStruct {
+/// # integer: u32,
+/// # string: String,
+/// # }
+///
+/// prop_compose! {
+/// fn my_struct_strategy(max_integer: u32)
+/// (integer in 0..max_integer, string: String)
+/// -> MyStruct {
+/// MyStruct { integer, string }
+/// }
+/// }
+/// #
+/// # fn main() { }
+/// ```
+///
+/// The second form is mostly the same, except that it takes _three_ argument
+/// lists. The third argument list can see all values in both prior, which
+/// permits producing strategies based on other strategies.
+///
+/// ```rust,no_run
+/// # #![allow(dead_code)]
+/// use proptest::prelude::*;
+///
+/// prop_compose! {
+/// fn nearby_numbers()(centre in -1000..1000)
+/// (a in centre-10..centre+10,
+/// b in centre-10..centre+10)
+/// -> (i32, i32) {
+/// (a, b)
+/// }
+/// }
+/// #
+/// # fn main() { }
+/// ```
+///
+/// However, the body of the function does _not_ have access to the second
+/// argument list. If the body needs access to those values, they must be
+/// passed through explicitly.
+///
+/// ```rust,no_run
+/// # #![allow(dead_code)]
+/// use proptest::prelude::*;
+///
+/// prop_compose! {
+/// fn vec_and_index
+/// (max_length: usize)
+/// (vec in prop::collection::vec(1..10, 1..max_length))
+/// (index in 0..vec.len(), vec in Just(vec))
+/// -> (Vec<i32>, usize)
+/// {
+/// (vec, index)
+/// }
+/// }
+/// # fn main() { }
+/// ```
+///
+/// The second form is sugar around making a strategy tuple, calling
+/// `prop_flat_map()`, then `prop_map()`.
+///
+/// To give the function any modifier which isn't a visibility modifier, put it
+/// in brackets before the `fn` token but after any visibility modifier.
+///
+/// ```rust,no_run
+/// # #![allow(dead_code)]
+/// use proptest::prelude::*;
+///
+/// prop_compose! {
+/// pub(crate) [unsafe] fn pointer()(v in prop::num::usize::ANY)
+/// -> *const () {
+/// v as *const ()
+/// }
+/// }
+/// # fn main() { }
+/// ```
+///
+/// ## Comparison with Hypothesis' `@composite`
+///
+/// `prop_compose!` makes it easy to do a lot of things you can do with
+/// [Hypothesis' `@composite`](https://hypothesis.readthedocs.io/en/latest/data.html#composite-strategies),
+/// but not everything.
+///
+/// - You can't filter via this macro. For filtering, you need to make the
+/// strategy the "normal" way and use `prop_filter()`.
+///
+/// - More than two layers of strategies or arbitrary logic between the two
+/// layers. If you need either of these, you can achieve them by calling
+/// `prop_flat_map()` by hand.
+#[macro_export]
+macro_rules! prop_compose {
+ ($(#[$meta:meta])*
+ $vis:vis
+ $([$($modi:tt)*])? fn $name:ident $params:tt
+ ($($var:pat in $strategy:expr),+ $(,)?)
+ -> $return_type:ty $body:block) =>
+ {
+ #[must_use = "strategies do nothing unless used"]
+ $(#[$meta])*
+ $vis
+ $($($modi)*)? fn $name $params
+ -> impl $crate::strategy::Strategy<Value = $return_type> {
+ let strat = $crate::proptest_helper!(@_WRAP ($($strategy)*));
+ $crate::strategy::Strategy::prop_map(strat,
+ move |$crate::proptest_helper!(@_WRAPPAT ($($var),*))| $body)
+ }
+ };
+
+ ($(#[$meta:meta])*
+ $vis:vis
+ $([$($modi:tt)*])? fn $name:ident $params:tt
+ ($($var:pat in $strategy:expr),+ $(,)?)
+ ($($var2:pat in $strategy2:expr),+ $(,)?)
+ -> $return_type:ty $body:block) =>
+ {
+ #[must_use = "strategies do nothing unless used"]
+ $(#[$meta])*
+ $vis
+ $($($modi)*)? fn $name $params
+ -> impl $crate::strategy::Strategy<Value = $return_type> {
+ let strat = $crate::proptest_helper!(@_WRAP ($($strategy)*));
+ let strat = $crate::strategy::Strategy::prop_flat_map(
+ strat,
+ move |$crate::proptest_helper!(@_WRAPPAT ($($var),*))|
+ $crate::proptest_helper!(@_WRAP ($($strategy2)*)));
+ $crate::strategy::Strategy::prop_map(strat,
+ move |$crate::proptest_helper!(@_WRAPPAT ($($var2),*))| $body)
+ }
+ };
+
+ ($(#[$meta:meta])*
+ $vis:vis
+ $([$($modi:tt)*])? fn $name:ident $params:tt
+ ($($arg:tt)+)
+ -> $return_type:ty $body:block) =>
+ {
+ #[must_use = "strategies do nothing unless used"]
+ $(#[$meta])*
+ $vis
+ $($($modi)*)? fn $name $params
+ -> impl $crate::strategy::Strategy<Value = $return_type> {
+ let strat = $crate::proptest_helper!(@_EXT _STRAT ($($arg)+));
+ $crate::strategy::Strategy::prop_map(strat,
+ move |$crate::proptest_helper!(@_EXT _PAT ($($arg)+))| $body)
+ }
+ };
+
+ ($(#[$meta:meta])*
+ $vis:vis
+ $([$($modi:tt)*])? fn $name:ident $params:tt
+ ($($arg:tt)+ $(,)?)
+ ($($arg2:tt)+ $(,)?)
+ -> $return_type:ty $body:block) =>
+ {
+ #[must_use = "strategies do nothing unless used"]
+ $(#[$meta])*
+ $vis
+ $($($modi)*)? fn $name $params
+ -> impl $crate::strategy::Strategy<Value = $return_type> {
+ let strat = $crate::proptest_helper!(@_WRAP ($($strategy)*));
+ let strat = $crate::strategy::Strategy::prop_flat_map(
+ strat,
+ move |$crate::proptest_helper!(@_EXT _PAT ($($arg)+))|
+ $crate::proptest_helper!(@_EXT _STRAT ($($arg2)*)));
+ $crate::strategy::Strategy::prop_map(strat,
+ move |$crate::proptest_helper!(@_EXT _PAT ($($arg2)*))| $body)
+ }
+ };
+}
+
+/// Similar to `assert!` from std, but returns a test failure instead of
+/// panicking if the condition fails.
+///
+/// This can be used in any function that returns a `Result<_, TestCaseError>`,
+/// including the top-level function inside `proptest!`.
+///
+/// Both panicking via `assert!` and returning a test case failure have the
+/// same effect as far as proptest is concerned; however, the Rust runtime
+/// implicitly prints every panic to stderr by default (including a backtrace
+/// if enabled), which can make test failures unnecessarily noisy. By using
+/// `prop_assert!` instead, the only output on a failing test case is the final
+/// panic including the minimal test case.
+///
+/// ## Example
+///
+/// ```
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// # /*
+/// #[test]
+/// # */
+/// fn triangle_inequality(a in 0.0f64..10.0, b in 0.0f64..10.0) {
+/// // Called with just a condition will print the condition on failure
+/// prop_assert!((a*a + b*b).sqrt() <= a + b);
+/// // You can also provide a custom failure message
+/// prop_assert!((a*a + b*b).sqrt() <= a + b,
+/// "Triangle inequality didn't hold for ({}, {})", a, b);
+/// // If calling another function that can return failure, don't forget
+/// // the `?` to propagate the failure.
+/// assert_from_other_function(a, b)?;
+/// }
+/// }
+///
+/// // The macro can be used from another function provided it has a compatible
+/// // return type.
+/// fn assert_from_other_function(a: f64, b: f64) -> Result<(), TestCaseError> {
+/// prop_assert!((a*a + b*b).sqrt() <= a + b);
+/// Ok(())
+/// }
+/// #
+/// # fn main() { triangle_inequality(); }
+/// ```
+#[macro_export]
+macro_rules! prop_assert {
+ ($cond:expr) => {
+ $crate::prop_assert!($cond, concat!("assertion failed: ", stringify!($cond)))
+ };
+
+ ($cond:expr, $($fmt:tt)*) => {
+ if !$cond {
+ let message = format!($($fmt)*);
+ let message = format!("{} at {}:{}", message, file!(), line!());
+ return ::core::result::Result::Err(
+ $crate::test_runner::TestCaseError::fail(message));
+ }
+ };
+}
+
+/// Similar to `assert_eq!` from std, but returns a test failure instead of
+/// panicking if the condition fails.
+///
+/// See `prop_assert!` for a more in-depth discussion.
+///
+/// ## Example
+///
+/// ```
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// # /*
+/// #[test]
+/// # */
+/// fn concat_string_length(ref a in ".*", ref b in ".*") {
+/// let cat = format!("{}{}", a, b);
+/// // Use with default message
+/// prop_assert_eq!(a.len() + b.len(), cat.len());
+/// // Can also provide custom message (added after the normal
+/// // assertion message)
+/// prop_assert_eq!(a.len() + b.len(), cat.len(),
+/// "a = {:?}, b = {:?}", a, b);
+/// }
+/// }
+/// #
+/// # fn main() { concat_string_length(); }
+/// ```
+#[macro_export]
+macro_rules! prop_assert_eq {
+ ($left:expr, $right:expr) => {{
+ let left = $left;
+ let right = $right;
+ $crate::prop_assert!(
+ left == right,
+ "assertion failed: `(left == right)` \
+ \n left: `{:?}`,\n right: `{:?}`",
+ left, right);
+ }};
+
+ ($left:expr, $right:expr, $fmt:tt $($args:tt)*) => {{
+ let left = $left;
+ let right = $right;
+ $crate::prop_assert!(
+ left == right,
+ concat!(
+ "assertion failed: `(left == right)` \
+ \n left: `{:?}`, \n right: `{:?}`: ", $fmt),
+ left, right $($args)*);
+ }};
+}
+
+/// Similar to `assert_ne!` from std, but returns a test failure instead of
+/// panicking if the condition fails.
+///
+/// See `prop_assert!` for a more in-depth discussion.
+///
+/// ## Example
+///
+/// ```
+/// use proptest::prelude::*;
+///
+/// proptest! {
+/// # /*
+/// #[test]
+/// # */
+/// fn test_addition(a in 0i32..100i32, b in 1i32..100i32) {
+/// // Use with default message
+/// prop_assert_ne!(a, a + b);
+/// // Can also provide custom message added after the common message
+/// prop_assert_ne!(a, a + b, "a = {}, b = {}", a, b);
+/// }
+/// }
+/// #
+/// # fn main() { test_addition(); }
+/// ```
+#[macro_export]
+macro_rules! prop_assert_ne {
+ ($left:expr, $right:expr) => {{
+ let left = $left;
+ let right = $right;
+ $crate::prop_assert!(
+ left != right,
+ "assertion failed: `(left != right)`\
+ \n left: `{:?}`,\n right: `{:?}`",
+ left, right);
+ }};
+
+ ($left:expr, $right:expr, $fmt:tt $($args:tt)*) => {{
+ let left = $left;
+ let right = $right;
+ $crate::prop_assert!(left != right, concat!(
+ "assertion failed: `(left != right)`\
+ \n left: `{:?}`,\n right: `{:?}`: ", $fmt),
+ left, right $($args)*);
+ }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! proptest_helper {
+ (@_WRAP ($a:tt)) => { $a };
+ (@_WRAP ($a0:tt $a1:tt)) => { ($a0, $a1) };
+ (@_WRAP ($a0:tt $a1:tt $a2:tt)) => { ($a0, $a1, $a2) };
+ (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt)) => { ($a0, $a1, $a2, $a3) };
+ (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt)) => {
+ ($a0, $a1, $a2, $a3, $a4)
+ };
+ (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt $a5:tt)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5)
+ };
+ (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt $a5:tt $a6:tt)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5, $a6)
+ };
+ (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt
+ $a4:tt $a5:tt $a6:tt $a7:tt)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7)
+ };
+ (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt
+ $a5:tt $a6:tt $a7:tt $a8:tt)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8)
+ };
+ (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt
+ $a5:tt $a6:tt $a7:tt $a8:tt $a9:tt)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9)
+ };
+ (@_WRAP ($a:tt $($rest:tt)*)) => {
+ ($a, $crate::proptest_helper!(@_WRAP ($($rest)*)))
+ };
+ (@_WRAPPAT ($item:pat)) => { $item };
+ (@_WRAPPAT ($a0:pat, $a1:pat)) => { ($a0, $a1) };
+ (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat)) => { ($a0, $a1, $a2) };
+ (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat)) => {
+ ($a0, $a1, $a2, $a3)
+ };
+ (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat)) => {
+ ($a0, $a1, $a2, $a3, $a4)
+ };
+ (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat, $a5:pat)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5)
+ };
+ (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
+ $a4:pat, $a5:pat, $a6:pat)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5, $a6)
+ };
+ (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
+ $a4:pat, $a5:pat, $a6:pat, $a7:pat)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7)
+ };
+ (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
+ $a5:pat, $a6:pat, $a7:pat, $a8:pat)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8)
+ };
+ (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
+ $a5:pat, $a6:pat, $a7:pat, $a8:pat, $a9:pat)) => {
+ ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9)
+ };
+ (@_WRAPPAT ($a:pat, $($rest:pat),*)) => {
+ ($a, $crate::proptest_helper!(@_WRAPPAT ($($rest),*)))
+ };
+ (@_WRAPSTR ($item:pat)) => { stringify!($item) };
+ (@_WRAPSTR ($a0:pat, $a1:pat)) => { (stringify!($a0), stringify!($a1)) };
+ (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat)) => {
+ (stringify!($a0), stringify!($a1), stringify!($a2))
+ };
+ (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat)) => {
+ (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3))
+ };
+ (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat)) => {
+ (stringify!($a0), stringify!($a1), stringify!($a2),
+ stringify!($a3), stringify!($a4))
+ };
+ (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat, $a5:pat)) => {
+ (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
+ stringify!($a4), stringify!($a5))
+ };
+ (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
+ $a4:pat, $a5:pat, $a6:pat)) => {
+ (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
+ stringify!($a4), stringify!($a5), stringify!($a6))
+ };
+ (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
+ $a4:pat, $a5:pat, $a6:pat, $a7:pat)) => {
+ (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
+ stringify!($a4), stringify!($a5), stringify!($a6), stringify!($a7))
+ };
+ (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
+ $a5:pat, $a6:pat, $a7:pat, $a8:pat)) => {
+ (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
+ stringify!($a4), stringify!($a5), stringify!($a6), stringify!($a7),
+ stringify!($a8))
+ };
+ (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
+ $a5:pat, $a6:pat, $a7:pat, $a8:pat, $a9:pat)) => {
+ (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
+ stringify!($a4), stringify!($a5), stringify!($a6), stringify!($a7),
+ stringify!($a8), stringify!($a9))
+ };
+ (@_WRAPSTR ($a:pat, $($rest:pat),*)) => {
+ (stringify!($a), $crate::proptest_helper!(@_WRAPSTR ($($rest),*)))
+ };
+ // build a property testing block that when executed, executes the full property test.
+ (@_BODY $config:ident ($($parm:pat in $strategy:expr),+) [$($mod:tt)*] $body:expr) => {{
+ $config.source_file = Some(file!());
+ let mut runner = $crate::test_runner::TestRunner::new($config);
+ let names = $crate::proptest_helper!(@_WRAPSTR ($($parm),*));
+ match runner.run(
+ &$crate::strategy::Strategy::prop_map(
+ $crate::proptest_helper!(@_WRAP ($($strategy)*)),
+ |values| $crate::sugar::NamedArguments(names, values)),
+ $($mod)* |$crate::sugar::NamedArguments(
+ _, $crate::proptest_helper!(@_WRAPPAT ($($parm),*)))|
+ {
+ let _: () = $body;
+ Ok(())
+ })
+ {
+ Ok(_) => (),
+ Err(e) => panic!("{}\n{}", e, runner),
+ }
+ }};
+ // build a property testing block that when executed, executes the full property test.
+ (@_BODY2 $config:ident ($($arg:tt)+) [$($mod:tt)*] $body:expr) => {{
+ $config.source_file = Some(file!());
+ let mut runner = $crate::test_runner::TestRunner::new($config);
+ let names = $crate::proptest_helper!(@_EXT _STR ($($arg)*));
+ match runner.run(
+ &$crate::strategy::Strategy::prop_map(
+ $crate::proptest_helper!(@_EXT _STRAT ($($arg)*)),
+ |values| $crate::sugar::NamedArguments(names, values)),
+ $($mod)* |$crate::sugar::NamedArguments(
+ _, $crate::proptest_helper!(@_EXT _PAT ($($arg)*)))|
+ {
+ let _: () = $body;
+ Ok(())
+ })
+ {
+ Ok(_) => (),
+ Err(e) => panic!("{}\n{}", e, runner),
+ }
+ }};
+
+ // The logic below helps support `pat: type` in the proptest! macro.
+
+ // These matchers define the actual logic:
+ (@_STRAT [$s:ty] [$p:pat]) => { $crate::arbitrary::any::<$s>() };
+ (@_PAT [$s:ty] [$p:pat]) => { $p };
+ (@_STR [$s:ty] [$p:pat]) => { stringify!($p) };
+ (@_STRAT in [$s:expr] [$p:pat]) => { $s };
+ (@_PAT in [$s:expr] [$p:pat]) => { $p };
+ (@_STR in [$s:expr] [$p:pat]) => { stringify!($p) };
+
+ // These matchers rewrite into the above extractors.
+ // We have to do this because `:` can't FOLLOW(pat).
+ // Note that this is not the full `pat` grammar...
+ // See https://docs.rs/syn/0.14.2/syn/enum.Pat.html for that.
+ (@_EXT $cmd:ident ($p:pat in $s:expr $(,)?)) => {
+ $crate::proptest_helper!(@$cmd in [$s] [$p])
+ };
+ (@_EXT $cmd:ident (($p:pat) : $s:ty $(,)?)) => {
+ // Users can wrap in parens as a last resort.
+ $crate::proptest_helper!(@$cmd [$s] [$p])
+ };
+ (@_EXT $cmd:ident (_ : $s:ty $(,)?)) => {
+ $crate::proptest_helper!(@$cmd [$s] [_])
+ };
+ (@_EXT $cmd:ident (ref mut $p:ident : $s:ty $(,)?)) => {
+ $crate::proptest_helper!(@$cmd [$s] [ref mut $p])
+ };
+ (@_EXT $cmd:ident (ref $p:ident : $s:ty $(,)?)) => {
+ $crate::proptest_helper!(@$cmd [$s] [ref $p])
+ };
+ (@_EXT $cmd:ident (mut $p:ident : $s:ty $(,)?)) => {
+ $crate::proptest_helper!(@$cmd [$s] [mut $p])
+ };
+ (@_EXT $cmd:ident ($p:ident : $s:ty $(,)?)) => {
+ $crate::proptest_helper!(@$cmd [$s] [$p])
+ };
+ (@_EXT $cmd:ident ([$($p:tt)*] : $s:ty $(,)?)) => {
+ $crate::proptest_helper!(@$cmd [$s] [[$($p)*]])
+ };
+
+ // Rewrite, Inductive case:
+ (@_EXT $cmd:ident ($p:pat in $s:expr, $($r:tt)*)) => {
+ ($crate::proptest_helper!(@$cmd in [$s] [$p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
+ };
+ (@_EXT $cmd:ident (($p:pat) : $s:ty, $($r:tt)*)) => {
+ ($crate::proptest_helper!(@$cmd [$s] [$p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
+ };
+ (@_EXT $cmd:ident (_ : $s:ty, $($r:tt)*)) => {
+ ($crate::proptest_helper!(@$cmd [$s] [_]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
+ };
+ (@_EXT $cmd:ident (ref mut $p:ident : $s:ty, $($r:tt)*)) => {
+ ($crate::proptest_helper!(@$cmd [$s] [ref mut $p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
+ };
+ (@_EXT $cmd:ident (ref $p:ident : $s:ty, $($r:tt)*)) => {
+ ($crate::proptest_helper!(@$cmd [$s] [ref $p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
+ };
+ (@_EXT $cmd:ident (mut $p:ident : $s:ty, $($r:tt)*)) => {
+ ($crate::proptest_helper!(@$cmd [$s] [mut $p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
+ };
+ (@_EXT $cmd:ident ($p:ident : $s:ty, $($r:tt)*)) => {
+ ($crate::proptest_helper!(@$cmd [$s] [$p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
+ };
+ (@_EXT $cmd:ident ([$($p:tt)*] : $s:ty, $($r:tt)*)) => {
+ ($crate::proptest_helper!(@$cmd [$s] [[$($p)*]]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
+ };
+}
+
+#[doc(hidden)]
+#[derive(Clone, Copy)]
+pub struct NamedArguments<N, V>(#[doc(hidden)] pub N, #[doc(hidden)] pub V);
+
+impl<V: fmt::Debug> fmt::Debug for NamedArguments<&'static str, V> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{} = ", self.0)?;
+ self.1.fmt(f)
+ }
+}
+
+macro_rules! named_arguments_tuple {
+ ($($ix:tt $argn:ident $argv:ident)*) => {
+ impl<'a, $($argn : Copy),*, $($argv),*> fmt::Debug
+ for NamedArguments<($($argn,)*),&'a ($($argv,)*)>
+ where $(NamedArguments<$argn, &'a $argv> : fmt::Debug),*,
+ $($argv : 'a),*
+ {
+ #[allow(unused_assignments)]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut first = true;
+ $(
+ if !first {
+ write!(f, ", ")?;
+ }
+ first = false;
+ fmt::Debug::fmt(
+ &NamedArguments((self.0).$ix, &(self.1).$ix), f)?;
+ )*
+ Ok(())
+ }
+ }
+
+ impl<$($argn : Copy),*, $($argv),*> fmt::Debug
+ for NamedArguments<($($argn,)*), ($($argv,)*)>
+ where $(for<'a> NamedArguments<$argn, &'a $argv> : fmt::Debug),*
+ {
+ #[allow(unused_assignments)]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut first = true;
+ $(
+ if !first {
+ write!(f, ", ")?;
+ }
+ first = false;
+ fmt::Debug::fmt(
+ &NamedArguments((self.0).$ix, &(self.1).$ix), f)?;
+ )*
+ Ok(())
+ }
+ }
+ }
+}
+
+named_arguments_tuple!(0 AN AV);
+named_arguments_tuple!(0 AN AV 1 BN BV);
+named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV);
+named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV);
+named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV);
+named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
+ 5 FN FV);
+named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
+ 5 FN FV 6 GN GV);
+named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
+ 5 FN FV 6 GN GV 7 HN HV);
+named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
+ 5 FN FV 6 GN GV 7 HN HV 8 IN IV);
+named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
+ 5 FN FV 6 GN GV 7 HN HV 8 IN IV 9 JN JV);
+
+#[cfg(feature = "std")]
+#[doc(hidden)]
+pub fn force_no_fork(config: &mut crate::test_runner::Config) {
+ if config.fork() {
+ eprintln!(
+ "proptest: Forking/timeout not supported in closure-style \
+ invocations; ignoring"
+ );
+
+ #[cfg(feature = "fork")]
+ {
+ config.fork = false;
+ }
+ #[cfg(feature = "timeout")]
+ {
+ config.timeout = 0;
+ }
+ assert!(!config.fork());
+ }
+}
+
+#[cfg(not(feature = "std"))]
+pub fn force_no_fork(_: &mut crate::test_runner::Config) {}
+
+#[cfg(test)]
+mod test {
+ use crate::strategy::Just;
+
+ prop_compose! {
+ /// These are docs!
+ #[allow(dead_code)]
+ fn two_ints(relative: i32)(a in 0..relative, b in relative..)
+ -> (i32, i32) {
+ (a, b)
+ }
+ }
+
+ prop_compose! {
+ /// These are docs!
+ #[allow(dead_code)]
+ pub fn two_ints_pub(relative: i32)(a in 0..relative, b in relative..)
+ -> (i32, i32) {
+ (a, b)
+ }
+ }
+
+ prop_compose! {
+ /// These are docs!
+ #[allow(dead_code, improper_ctypes_definitions)]
+ pub [extern "C"] fn two_ints_pub_with_attrs
+ (relative: i32)(a in 0..relative, b in relative..)
+ -> (i32, i32)
+ {
+ (a, b)
+ }
+ }
+
+ prop_compose! {
+ // The only modifier we can usefully put here is "unsafe", but we want
+ // to keep this crate unsafe-free, even nominally. "const" may
+ // eventually work, but is not allowed right now since the generated
+ // code contains local variables. `extern "C"` is accepted, even though
+ // the result is useless since the return type isn't C-compatible.
+ #[allow(dead_code, improper_ctypes_definitions)]
+ [extern "C"] fn with_modifier(relative: i32)(a in 0..relative) -> i32 {
+ a
+ }
+ }
+
+ prop_compose! {
+ #[allow(dead_code)]
+ fn a_less_than_b()(b in 0..1000)(a in 0..b, b in Just(b))
+ -> (i32, i32) {
+ (a, b)
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn test_something(a in 0u32..42u32, b in 1u32..10u32) {
+ prop_assume!(a != 41 || b != 9);
+ assert!(a + b < 50);
+ }
+ }
+
+ prop_compose! {
+ #[allow(dead_code)]
+ fn single_closure_is_move(base: u64)(off in 0..10u64) -> u64 {
+ base + off
+ }
+ }
+
+ prop_compose! {
+ #[allow(dead_code)]
+ fn double_closure_is_move
+ (base: u64)
+ (off1 in 0..10u64)
+ (off2 in off1..off1+10)
+ -> u64
+ {
+ base + off2
+ }
+ }
+
+ #[allow(unused_variables)]
+ mod test_arg_counts {
+ use crate::strategy::Just;
+
+ proptest! {
+ #[test]
+ fn test_1_arg(a in Just(0)) { }
+ #[test]
+ fn test_2_arg(a in Just(0), b in Just(0)) { }
+ #[test]
+ fn test_3_arg(a in Just(0), b in Just(0), c in Just(0)) { }
+ #[test]
+ fn test_4_arg(a in Just(0), b in Just(0), c in Just(0),
+ d in Just(0)) { }
+ #[test]
+ fn test_5_arg(a in Just(0), b in Just(0), c in Just(0),
+ d in Just(0), e in Just(0)) { }
+ #[test]
+ fn test_6_arg(a in Just(0), b in Just(0), c in Just(0),
+ d in Just(0), e in Just(0), f in Just(0)) { }
+ #[test]
+ fn test_7_arg(a in Just(0), b in Just(0), c in Just(0),
+ d in Just(0), e in Just(0), f in Just(0),
+ g in Just(0)) { }
+ #[test]
+ fn test_8_arg(a in Just(0), b in Just(0), c in Just(0),
+ d in Just(0), e in Just(0), f in Just(0),
+ g in Just(0), h in Just(0)) { }
+ #[test]
+ fn test_9_arg(a in Just(0), b in Just(0), c in Just(0),
+ d in Just(0), e in Just(0), f in Just(0),
+ g in Just(0), h in Just(0), i in Just(0)) { }
+ #[test]
+ fn test_a_arg(a in Just(0), b in Just(0), c in Just(0),
+ d in Just(0), e in Just(0), f in Just(0),
+ g in Just(0), h in Just(0), i in Just(0),
+ j in Just(0)) { }
+ #[test]
+ fn test_b_arg(a in Just(0), b in Just(0), c in Just(0),
+ d in Just(0), e in Just(0), f in Just(0),
+ g in Just(0), h in Just(0), i in Just(0),
+ j in Just(0), k in Just(0)) { }
+ #[test]
+ fn test_c_arg(a in Just(0), b in Just(0), c in Just(0),
+ d in Just(0), e in Just(0), f in Just(0),
+ g in Just(0), h in Just(0), i in Just(0),
+ j in Just(0), k in Just(0), l in Just(0)) { }
+ }
+ }
+
+ #[test]
+ fn named_arguments_is_debug_for_needed_cases() {
+ use super::NamedArguments;
+
+ println!("{:?}", NamedArguments("foo", &"bar"));
+ println!("{:?}", NamedArguments(("foo",), &(1,)));
+ println!("{:?}", NamedArguments(("foo", "bar"), &(1, 2)));
+ println!("{:?}", NamedArguments(("a", "b", "c"), &(1, 2, 3)));
+ println!("{:?}", NamedArguments(("a", "b", "c", "d"), &(1, 2, 3, 4)));
+ println!(
+ "{:?}",
+ NamedArguments(("a", "b", "c", "d", "e"), &(1, 2, 3, 4, 5))
+ );
+ println!(
+ "{:?}",
+ NamedArguments(("a", "b", "c", "d", "e", "f"), &(1, 2, 3, 4, 5, 6))
+ );
+ println!(
+ "{:?}",
+ NamedArguments(
+ ("a", "b", "c", "d", "e", "f", "g"),
+ &(1, 2, 3, 4, 5, 6, 7)
+ )
+ );
+ println!(
+ "{:?}",
+ NamedArguments(
+ ("a", "b", "c", "d", "e", "f", "g", "h"),
+ &(1, 2, 3, 4, 5, 6, 7, 8)
+ )
+ );
+ println!(
+ "{:?}",
+ NamedArguments(
+ ("a", "b", "c", "d", "e", "f", "g", "h", "i"),
+ &(1, 2, 3, 4, 5, 6, 7, 8, 9)
+ )
+ );
+ println!(
+ "{:?}",
+ NamedArguments(
+ ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
+ &(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ )
+ );
+ println!(
+ "{:?}",
+ NamedArguments((("a", "b"), "c", "d"), &((1, 2), 3, 4))
+ );
+ }
+
+ #[test]
+ fn oneof_all_counts() {
+ use crate::strategy::{Just as J, Strategy, TupleUnion, Union};
+
+ fn expect_count(n: usize, s: impl Strategy<Value = i32>) {
+ use crate::strategy::*;
+ use crate::test_runner::*;
+ use std::collections::HashSet;
+
+ let mut runner = TestRunner::default();
+ let mut seen = HashSet::new();
+ for _ in 0..1024 {
+ seen.insert(s.new_tree(&mut runner).unwrap().current());
+ }
+
+ assert_eq!(n, seen.len());
+ }
+
+ fn assert_static<T>(v: TupleUnion<T>) -> TupleUnion<T> {
+ v
+ }
+ fn assert_dynamic<T: Strategy>(v: Union<T>) -> Union<T> {
+ v
+ }
+
+ expect_count(1, prop_oneof![J(0i32)]);
+ expect_count(2, assert_static(prop_oneof![J(0i32), J(1i32),]));
+ expect_count(3, assert_static(prop_oneof![J(0i32), J(1i32), J(2i32),]));
+ expect_count(
+ 4,
+ assert_static(prop_oneof![J(0i32), J(1i32), J(2i32), J(3i32),]),
+ );
+ expect_count(
+ 5,
+ assert_static(prop_oneof![
+ J(0i32),
+ J(1i32),
+ J(2i32),
+ J(3i32),
+ J(4i32),
+ ]),
+ );
+ expect_count(
+ 6,
+ assert_static(prop_oneof![
+ J(0i32),
+ J(1i32),
+ J(2i32),
+ J(3i32),
+ J(4i32),
+ J(5i32),
+ ]),
+ );
+ expect_count(
+ 7,
+ assert_static(prop_oneof![
+ J(0i32),
+ J(1i32),
+ J(2i32),
+ J(3i32),
+ J(4i32),
+ J(5i32),
+ J(6i32),
+ ]),
+ );
+ expect_count(
+ 8,
+ assert_static(prop_oneof![
+ J(0i32),
+ J(1i32),
+ J(2i32),
+ J(3i32),
+ J(4i32),
+ J(5i32),
+ J(6i32),
+ J(7i32),
+ ]),
+ );
+ expect_count(
+ 9,
+ assert_static(prop_oneof![
+ J(0i32),
+ J(1i32),
+ J(2i32),
+ J(3i32),
+ J(4i32),
+ J(5i32),
+ J(6i32),
+ J(7i32),
+ J(8i32),
+ ]),
+ );
+ expect_count(
+ 10,
+ assert_static(prop_oneof![
+ J(0i32),
+ J(1i32),
+ J(2i32),
+ J(3i32),
+ J(4i32),
+ J(5i32),
+ J(6i32),
+ J(7i32),
+ J(8i32),
+ J(9i32),
+ ]),
+ );
+ expect_count(
+ 11,
+ assert_dynamic(prop_oneof![
+ J(0i32),
+ J(1i32),
+ J(2i32),
+ J(3i32),
+ J(4i32),
+ J(5i32),
+ J(6i32),
+ J(7i32),
+ J(8i32),
+ J(9i32),
+ J(10i32),
+ ]),
+ );
+ }
+}
+
+#[cfg(all(test, feature = "timeout"))]
+mod test_timeout {
+ proptest! {
+ #![proptest_config(crate::test_runner::Config {
+ fork: true,
+ .. crate::test_runner::Config::default()
+ })]
+
+ // Ensure that the macro sets the test name properly. If it doesn't,
+ // this test will fail to run correctly.
+ #[test]
+ fn test_name_set_correctly_for_fork(_ in 0u32..1u32) { }
+ }
+}
+
+#[cfg(test)]
+mod another_test {
+ use crate::sugar;
+
+ // Ensure that we can access the `[pub]` composed function above.
+ #[allow(dead_code)]
+ fn can_access_pub_compose() {
+ let _ = sugar::test::two_ints_pub(42);
+ let _ = sugar::test::two_ints_pub_with_attrs(42);
+ }
+}
+
+#[cfg(test)]
+mod ownership_tests {
+ #[cfg(feature = "std")]
+ proptest! {
+ #[test]
+ fn accept_ref_arg(ref s in "[0-9]") {
+ use crate::std_facade::String;
+ fn assert_string(_s: &String) {}
+ assert_string(s);
+ }
+
+ #[test]
+ fn accept_move_arg(s in "[0-9]") {
+ use crate::std_facade::String;
+ fn assert_string(_s: String) {}
+ assert_string(s);
+ }
+ }
+
+ #[derive(Debug)]
+ struct NotClone();
+ const MK: fn() -> NotClone = NotClone;
+
+ proptest! {
+ #[test]
+ fn accept_noclone_arg(nc in MK) {
+ let _nc2: NotClone = nc;
+ }
+
+ #[test]
+ fn accept_noclone_ref_arg(ref nc in MK) {
+ let _nc2: &NotClone = nc;
+ }
+ }
+}
+
+#[cfg(test)]
+mod closure_tests {
+ #[test]
+ fn test_simple() {
+ let x = 420;
+
+ proptest!(|(y: i32)| {
+ assert!(x != y);
+ });
+
+ proptest!(|(y in 0..100)| {
+ println!("{}", y);
+ assert!(x != y);
+ });
+
+ proptest!(|(y: i32,)| {
+ assert!(x != y);
+ });
+
+ proptest!(|(y in 0..100,)| {
+ println!("{}", y);
+ assert!(x != y);
+ });
+ }
+
+ #[test]
+ fn test_move() {
+ let foo = Foo;
+
+ proptest!(move |(x in 1..100, y in 0..100)| {
+ assert!(x + y > 0, "foo: {:?}", foo);
+ });
+
+ let foo = Foo;
+ proptest!(move |(x: (), y: ())| {
+ assert!(x == y, "foo: {:?}", foo);
+ });
+
+ #[derive(Debug)]
+ struct Foo;
+ }
+
+ #[test]
+ #[should_panic]
+ #[allow(unreachable_code)]
+ fn fails_if_closure_panics() {
+ proptest!(|(_ in 0..1)| {
+ panic!()
+ });
+ }
+
+ #[test]
+ fn accepts_unblocked_syntax() {
+ proptest!(|(x in 0u32..10, y in 10u32..20)| assert!(x < y));
+ proptest!(|(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
+ }
+
+ #[test]
+ fn accepts_custom_config() {
+ let conf = crate::test_runner::Config::default();
+
+ proptest!(conf, |(x in 0u32..10, y in 10u32..20)| assert!(x < y));
+ proptest!(&conf, |(x in 0u32..10, y in 10u32..20)| assert!(x < y));
+ proptest!(conf, move |(x in 0u32..10, y in 10u32..20)| assert!(x < y));
+ proptest!(conf, |(_x: u32, _y: u32)| { });
+ proptest!(conf, move |(_x: u32, _y: u32)| { });
+
+ // Same as above, but with extra trailing comma
+ proptest!(conf, |(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
+ proptest!(&conf, |(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
+ proptest!(conf, move |(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
+ proptest!(conf, |(_x: u32, _y: u32,)| { });
+ proptest!(conf, move |(_x: u32, _y: u32,)| { });
+ }
+}
+
+#[cfg(test)]
+mod any_tests {
+ proptest! {
+ #[test]
+ fn test_something
+ (
+ a: bool,
+ b in 25u8..,
+ c in 25u8..,
+ _d: (),
+ mut _e: (),
+ ref _f: (),
+ ref mut _g: (),
+ [_, _]: [(); 2],
+ ) {
+ if a {} // Assert bool.
+ assert!(b as usize + c as usize >= 50);
+ }
+ }
+
+ // Test that the macro accepts some of the inputs we expect it to:
+ #[test]
+ fn proptest_ext_test() {
+ struct Y(pub u8);
+
+ let _ = proptest_helper!(@_EXT _STRAT( _ : u8 ));
+ let _ = proptest_helper!(@_EXT _STRAT( x : u8 ));
+ let _ = proptest_helper!(@_EXT _STRAT( ref x : u8 ));
+ let _ = proptest_helper!(@_EXT _STRAT( mut x : u8 ));
+ let _ = proptest_helper!(@_EXT _STRAT( ref mut x : u8 ));
+ let _ = proptest_helper!(@_EXT _STRAT( [_, _] : u8 ));
+ let _ = proptest_helper!(@_EXT _STRAT( (&mut &Y(ref x)) : u8 ));
+ let _ = proptest_helper!(@_EXT _STRAT( x in 1..2 ));
+
+ let proptest_helper!(@_EXT _PAT( _ : u8 )) = 1;
+ let proptest_helper!(@_EXT _PAT( _x : u8 )) = 1;
+ let proptest_helper!(@_EXT _PAT( mut _x : u8 )) = 1;
+ let proptest_helper!(@_EXT _PAT( ref _x : u8 )) = 1;
+ let proptest_helper!(@_EXT _PAT( ref mut _x : u8 )) = 1;
+ let proptest_helper!(@_EXT _PAT( [_, _] : u8 )) = [1, 2];
+ let proptest_helper!(@_EXT _PAT( (&mut &Y(ref _x)) : u8 )) = &mut &Y(1);
+ let proptest_helper!(@_EXT _PAT( _x in 1..2 )) = 1;
+ }
+}
diff --git a/vendor/proptest/src/test_runner/config.rs b/vendor/proptest/src/test_runner/config.rs
new file mode 100644
index 000000000..a3d30846a
--- /dev/null
+++ b/vendor/proptest/src/test_runner/config.rs
@@ -0,0 +1,516 @@
+//-
+// Copyright 2017, 2018, 2019 The proptest 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.
+
+use crate::std_facade::Box;
+use core::u32;
+
+#[cfg(feature = "std")]
+use std::env;
+#[cfg(feature = "std")]
+use std::ffi::OsString;
+#[cfg(feature = "std")]
+use std::fmt;
+#[cfg(feature = "std")]
+use std::str::FromStr;
+
+use crate::test_runner::result_cache::{noop_result_cache, ResultCache};
+use crate::test_runner::rng::RngAlgorithm;
+use crate::test_runner::FailurePersistence;
+#[cfg(feature = "std")]
+use crate::test_runner::FileFailurePersistence;
+
+#[cfg(feature = "std")]
+const CASES: &str = "PROPTEST_CASES";
+#[cfg(feature = "std")]
+const MAX_LOCAL_REJECTS: &str = "PROPTEST_MAX_LOCAL_REJECTS";
+#[cfg(feature = "std")]
+const MAX_GLOBAL_REJECTS: &str = "PROPTEST_MAX_GLOBAL_REJECTS";
+#[cfg(feature = "std")]
+const MAX_FLAT_MAP_REGENS: &str = "PROPTEST_MAX_FLAT_MAP_REGENS";
+#[cfg(feature = "std")]
+const MAX_SHRINK_TIME: &str = "PROPTEST_MAX_SHRINK_TIME";
+#[cfg(feature = "std")]
+const MAX_SHRINK_ITERS: &str = "PROPTEST_MAX_SHRINK_ITERS";
+#[cfg(feature = "fork")]
+const FORK: &str = "PROPTEST_FORK";
+#[cfg(feature = "timeout")]
+const TIMEOUT: &str = "PROPTEST_TIMEOUT";
+#[cfg(feature = "std")]
+const VERBOSE: &str = "PROPTEST_VERBOSE";
+#[cfg(feature = "std")]
+const RNG_ALGORITHM: &str = "PROPTEST_RNG_ALGORITHM";
+#[cfg(feature = "std")]
+const DISABLE_FAILURE_PERSISTENCE: &str =
+ "PROPTEST_DISABLE_FAILURE_PERSISTENCE";
+
+#[cfg(feature = "std")]
+fn contextualize_config(mut result: Config) -> Config {
+ fn parse_or_warn<T: FromStr + fmt::Display>(
+ src: &OsString,
+ dst: &mut T,
+ typ: &str,
+ var: &str,
+ ) {
+ if let Some(src) = src.to_str() {
+ if let Ok(value) = src.parse() {
+ *dst = value;
+ } else {
+ eprintln!(
+ "proptest: The env-var {}={} can't be parsed as {}, \
+ using default of {}.",
+ var, src, typ, *dst
+ );
+ }
+ } else {
+ eprintln!(
+ "proptest: The env-var {} is not valid, using \
+ default of {}.",
+ var, *dst
+ );
+ }
+ }
+
+ result.failure_persistence =
+ Some(Box::new(FileFailurePersistence::default()));
+ for (var, value) in
+ env::vars_os().filter_map(|(k, v)| k.into_string().ok().map(|k| (k, v)))
+ {
+ match var.as_str() {
+ CASES => parse_or_warn(&value, &mut result.cases, "u32", CASES),
+ MAX_LOCAL_REJECTS => parse_or_warn(
+ &value,
+ &mut result.max_local_rejects,
+ "u32",
+ MAX_LOCAL_REJECTS,
+ ),
+ MAX_GLOBAL_REJECTS => parse_or_warn(
+ &value,
+ &mut result.max_global_rejects,
+ "u32",
+ MAX_GLOBAL_REJECTS,
+ ),
+ MAX_FLAT_MAP_REGENS => parse_or_warn(
+ &value,
+ &mut result.max_flat_map_regens,
+ "u32",
+ MAX_FLAT_MAP_REGENS,
+ ),
+ #[cfg(feature = "fork")]
+ FORK => parse_or_warn(&value, &mut result.fork, "bool", FORK),
+ #[cfg(feature = "timeout")]
+ TIMEOUT => {
+ parse_or_warn(&value, &mut result.timeout, "timeout", TIMEOUT)
+ }
+ MAX_SHRINK_TIME => parse_or_warn(
+ &value,
+ &mut result.max_shrink_time,
+ "u32",
+ MAX_SHRINK_TIME,
+ ),
+ MAX_SHRINK_ITERS => parse_or_warn(
+ &value,
+ &mut result.max_shrink_iters,
+ "u32",
+ MAX_SHRINK_ITERS,
+ ),
+ VERBOSE => {
+ parse_or_warn(&value, &mut result.verbose, "u32", VERBOSE)
+ }
+ RNG_ALGORITHM => parse_or_warn(
+ &value,
+ &mut result.rng_algorithm,
+ "RngAlgorithm",
+ RNG_ALGORITHM,
+ ),
+ DISABLE_FAILURE_PERSISTENCE => result.failure_persistence = None,
+
+ _ => {
+ if var.starts_with("PROPTEST_") {
+ eprintln!("proptest: Ignoring unknown env-var {}.", var);
+ }
+ }
+ }
+ }
+
+ result
+}
+
+#[cfg(not(feature = "std"))]
+fn contextualize_config(result: Config) -> Config {
+ result
+}
+
+fn default_default_config() -> Config {
+ Config {
+ cases: 256,
+ max_local_rejects: 65_536,
+ max_global_rejects: 1024,
+ max_flat_map_regens: 1_000_000,
+ failure_persistence: None,
+ source_file: None,
+ test_name: None,
+ #[cfg(feature = "fork")]
+ fork: false,
+ #[cfg(feature = "timeout")]
+ timeout: 0,
+ #[cfg(feature = "std")]
+ max_shrink_time: 0,
+ max_shrink_iters: u32::MAX,
+ result_cache: noop_result_cache,
+ #[cfg(feature = "std")]
+ verbose: 0,
+ rng_algorithm: RngAlgorithm::default(),
+ _non_exhaustive: (),
+ }
+}
+
+// The default config, computed by combining environment variables and
+// defaults.
+#[cfg(feature = "std")]
+lazy_static! {
+ static ref DEFAULT_CONFIG: Config =
+ contextualize_config(default_default_config());
+}
+
+/// Configuration for how a proptest test should be run.
+#[derive(Clone, Debug, PartialEq)]
+pub struct Config {
+ /// The number of successful test cases that must execute for the test as a
+ /// whole to pass.
+ ///
+ /// This does not include implicitly-replayed persisted failing cases.
+ ///
+ /// The default is 256, which can be overridden by setting the
+ /// `PROPTEST_CASES` environment variable. (The variable is only considered
+ /// when the `std` feature is enabled, which it is by default.)
+ pub cases: u32,
+
+ /// The maximum number of individual inputs that may be rejected before the
+ /// test as a whole aborts.
+ ///
+ /// The default is 65536, which can be overridden by setting the
+ /// `PROPTEST_MAX_LOCAL_REJECTS` environment variable. (The variable is only
+ /// considered when the `std` feature is enabled, which it is by default.)
+ pub max_local_rejects: u32,
+
+ /// The maximum number of combined inputs that may be rejected before the
+ /// test as a whole aborts.
+ ///
+ /// The default is 1024, which can be overridden by setting the
+ /// `PROPTEST_MAX_GLOBAL_REJECTS` environment variable. (The variable is
+ /// only considered when the `std` feature is enabled, which it is by
+ /// default.)
+ pub max_global_rejects: u32,
+
+ /// The maximum number of times all `Flatten` combinators will attempt to
+ /// regenerate values. This puts a limit on the worst-case exponential
+ /// explosion that can happen with nested `Flatten`s.
+ ///
+ /// The default is 1_000_000, which can be overridden by setting the
+ /// `PROPTEST_MAX_FLAT_MAP_REGENS` environment variable. (The variable is
+ /// only considered when the `std` feature is enabled, which it is by
+ /// default.)
+ pub max_flat_map_regens: u32,
+
+ /// Indicates whether and how to persist failed test results.
+ ///
+ /// When compiling with "std" feature (i.e. the standard library is available), the default
+ /// is `Some(Box::new(FileFailurePersistence::SourceParallel("proptest-regressions")))`.
+ ///
+ /// Without the standard library, the default is `None`, and no persistence occurs.
+ ///
+ /// See the docs of [`FileFailurePersistence`](enum.FileFailurePersistence.html)
+ /// and [`MapFailurePersistence`](struct.MapFailurePersistence.html) for more information.
+ ///
+ /// You can disable failure persistence with the `PROPTEST_DISABLE_FAILURE_PERSISTENCE`
+ /// environment variable but its not currently possible to set the persistence file
+ /// with an environment variable. (The variable is
+ /// only considered when the `std` feature is enabled, which it is by
+ /// default.)
+ pub failure_persistence: Option<Box<dyn FailurePersistence>>,
+
+ /// File location of the current test, relevant for persistence
+ /// and debugging.
+ ///
+ /// Note the use of `&str` rather than `Path` to be compatible with
+ /// `#![no_std]` use cases where `Path` is unavailable.
+ ///
+ /// See the docs of [`FileFailurePersistence`](enum.FileFailurePersistence.html)
+ /// for more information on how it may be used for persistence.
+ pub source_file: Option<&'static str>,
+
+ /// The fully-qualified name of the test being run, as would be passed to
+ /// the test executable to run just that test.
+ ///
+ /// This must be set if `fork` is `true`. Otherwise, it is unused. It is
+ /// automatically set by `proptest!`.
+ ///
+ /// This must include the crate name at the beginning, as produced by
+ /// `module_path!()`.
+ pub test_name: Option<&'static str>,
+
+ /// If true, tests are run in a subprocess.
+ ///
+ /// Forking allows proptest to work with tests which may fail by aborting
+ /// the process, causing a segmentation fault, etc, but can be a lot slower
+ /// in certain environments or when running a very large number of tests.
+ ///
+ /// For forking to work correctly, both the `Strategy` and the content of
+ /// the test case itself must be deterministic.
+ ///
+ /// This requires the "fork" feature, enabled by default.
+ ///
+ /// The default is `false`, which can be overridden by setting the
+ /// `PROPTEST_FORK` environment variable. (The variable is
+ /// only considered when the `std` feature is enabled, which it is by
+ /// default.)
+ #[cfg(feature = "fork")]
+ pub fork: bool,
+
+ /// If non-zero, tests are run in a subprocess and each generated case
+ /// fails if it takes longer than this number of milliseconds.
+ ///
+ /// This implicitly enables forking, even if the `fork` field is `false`.
+ ///
+ /// The type here is plain `u32` (rather than
+ /// `Option<std::time::Duration>`) for the sake of ergonomics.
+ ///
+ /// This requires the "timeout" feature, enabled by default.
+ ///
+ /// Setting a timeout to less than the time it takes the process to start
+ /// up and initialise the first test case will cause the whole test to be
+ /// aborted.
+ ///
+ /// The default is `0` (i.e., no timeout), which can be overridden by
+ /// setting the `PROPTEST_TIMEOUT` environment variable. (The variable is
+ /// only considered when the `std` feature is enabled, which it is by
+ /// default.)
+ #[cfg(feature = "timeout")]
+ pub timeout: u32,
+
+ /// If non-zero, give up the shrinking process after this many milliseconds
+ /// have elapsed since the start of the shrinking process.
+ ///
+ /// This will not cause currently running test cases to be interrupted.
+ ///
+ /// This configuration is only available when the `std` feature is enabled
+ /// (which it is by default).
+ ///
+ /// The default is `0` (i.e., no limit), which can be overridden by setting
+ /// the `PROPTEST_MAX_SHRINK_TIME` environment variable. (The variable is
+ /// only considered when the `std` feature is enabled, which it is by
+ /// default.)
+ #[cfg(feature = "std")]
+ pub max_shrink_time: u32,
+
+ /// Give up on shrinking if more than this number of iterations of the test
+ /// code are run.
+ ///
+ /// Setting this to `std::u32::MAX` causes the actual limit to be four
+ /// times the number of test cases.
+ ///
+ /// Setting this value to `0` disables shrinking altogether.
+ ///
+ /// Note that the type of this field will change in a future version of
+ /// proptest to better accommodate its special values.
+ ///
+ /// The default is `std::u32::MAX`, which can be overridden by setting the
+ /// `PROPTEST_MAX_SHRINK_ITERS` environment variable. (The variable is only
+ /// considered when the `std` feature is enabled, which it is by default.)
+ pub max_shrink_iters: u32,
+
+ /// A function to create new result caches.
+ ///
+ /// The default is to do no caching. The easiest way to enable caching is
+ /// to set this field to `basic_result_cache` (though that is currently
+ /// only available with the `std` feature).
+ ///
+ /// This is useful for strategies which have a tendency to produce
+ /// duplicate values, or for tests where shrinking can take a very long
+ /// time due to exploring the same output multiple times.
+ ///
+ /// When caching is enabled, generated values themselves are not stored, so
+ /// this does not pose a risk of memory exhaustion for large test inputs
+ /// unless using extraordinarily large test case counts.
+ ///
+ /// Caching incurs its own overhead, and may very well make your test run
+ /// more slowly.
+ pub result_cache: fn() -> Box<dyn ResultCache>,
+
+ /// Set to non-zero values to cause proptest to emit human-targeted
+ /// messages to stderr as it runs.
+ ///
+ /// Greater values cause greater amounts of logs to be emitted. The exact
+ /// meaning of certain levels other than 0 is subject to change.
+ ///
+ /// - 0: No extra output.
+ /// - 1: Log test failure messages.
+ /// - 2: Trace low-level details.
+ ///
+ /// This is only available with the `std` feature (enabled by default)
+ /// since on nostd proptest has no way to produce output.
+ ///
+ /// The default is `0`, which can be overridden by setting the
+ /// `PROPTEST_VERBOSE` environment variable. (The variable is only considered
+ /// when the `std` feature is enabled, which it is by default.)
+ #[cfg(feature = "std")]
+ pub verbose: u32,
+
+ /// The RNG algorithm to use when not using a user-provided RNG.
+ ///
+ /// The default is `RngAlgorithm::default()`, which can be overridden by
+ /// setting the `PROPTEST_RNG_ALGORITHM` environment variable to one of the following:
+ ///
+ /// - `xs` — `RngAlgorithm::XorShift`
+ /// - `cc` — `RngAlgorithm::ChaCha`
+ ///
+ /// (The variable is only considered when the `std` feature is enabled,
+ /// which it is by default.)
+ pub rng_algorithm: RngAlgorithm,
+
+ // Needs to be public so FRU syntax can be used.
+ #[doc(hidden)]
+ pub _non_exhaustive: (),
+}
+
+impl Config {
+ /// Constructs a `Config` only differing from the `default()` in the
+ /// number of test cases required to pass the test successfully.
+ ///
+ /// This is simply a more concise alternative to using field-record update
+ /// syntax:
+ ///
+ /// ```
+ /// # use proptest::test_runner::Config;
+ /// assert_eq!(
+ /// Config::with_cases(42),
+ /// Config { cases: 42, .. Config::default() }
+ /// );
+ /// ```
+ pub fn with_cases(cases: u32) -> Self {
+ Self {
+ cases,
+ ..Config::default()
+ }
+ }
+
+ /// Constructs a `Config` only differing from the `default()` in the
+ /// source_file of the present test.
+ ///
+ /// This is simply a more concise alternative to using field-record update
+ /// syntax:
+ ///
+ /// ```
+ /// # use proptest::test_runner::Config;
+ /// assert_eq!(
+ /// Config::with_source_file("computer/question"),
+ /// Config { source_file: Some("computer/question"), .. Config::default() }
+ /// );
+ /// ```
+ pub fn with_source_file(source_file: &'static str) -> Self {
+ Self {
+ source_file: Some(source_file),
+ ..Config::default()
+ }
+ }
+
+ /// Constructs a `Config` only differing from the provided Config instance, `self`,
+ /// in the source_file of the present test.
+ ///
+ /// This is simply a more concise alternative to using field-record update
+ /// syntax:
+ ///
+ /// ```
+ /// # use proptest::test_runner::Config;
+ /// let a = Config::with_source_file("computer/question");
+ /// let b = a.clone_with_source_file("answer/42");
+ /// assert_eq!(
+ /// a,
+ /// Config { source_file: Some("computer/question"), .. Config::default() }
+ /// );
+ /// assert_eq!(
+ /// b,
+ /// Config { source_file: Some("answer/42"), .. Config::default() }
+ /// );
+ /// ```
+ pub fn clone_with_source_file(&self, source_file: &'static str) -> Self {
+ let mut result = self.clone();
+ result.source_file = Some(source_file);
+ result
+ }
+
+ /// Return whether this configuration implies forking.
+ ///
+ /// This method exists even if the "fork" feature is disabled, in which
+ /// case it simply returns false.
+ pub fn fork(&self) -> bool {
+ self._fork() || self.timeout() > 0
+ }
+
+ #[cfg(feature = "fork")]
+ fn _fork(&self) -> bool {
+ self.fork
+ }
+
+ #[cfg(not(feature = "fork"))]
+ fn _fork(&self) -> bool {
+ false
+ }
+
+ /// Returns the configured timeout.
+ ///
+ /// This method exists even if the "timeout" feature is disabled, in which
+ /// case it simply returns 0.
+ #[cfg(feature = "timeout")]
+ pub fn timeout(&self) -> u32 {
+ self.timeout
+ }
+
+ /// Returns the configured timeout.
+ ///
+ /// This method exists even if the "timeout" feature is disabled, in which
+ /// case it simply returns 0.
+ #[cfg(not(feature = "timeout"))]
+ pub fn timeout(&self) -> u32 {
+ 0
+ }
+
+ /// Returns the configured limit on shrinking iterations.
+ ///
+ /// This takes into account the special "automatic" behaviour.
+ pub fn max_shrink_iters(&self) -> u32 {
+ if u32::MAX == self.max_shrink_iters {
+ self.cases.saturating_mul(4)
+ } else {
+ self.max_shrink_iters
+ }
+ }
+
+ // Used by macros to force the config to be owned without depending on
+ // certain traits being `use`d.
+ #[allow(missing_docs)]
+ #[doc(hidden)]
+ pub fn __sugar_to_owned(&self) -> Self {
+ self.clone()
+ }
+}
+
+#[cfg(feature = "std")]
+impl Default for Config {
+ fn default() -> Self {
+ DEFAULT_CONFIG.clone()
+ }
+}
+
+#[cfg(not(feature = "std"))]
+impl Default for Config {
+ fn default() -> Self {
+ default_default_config()
+ }
+}
diff --git a/vendor/proptest/src/test_runner/errors.rs b/vendor/proptest/src/test_runner/errors.rs
new file mode 100644
index 000000000..dfa4a4852
--- /dev/null
+++ b/vendor/proptest/src/test_runner/errors.rs
@@ -0,0 +1,135 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+use crate::std_facade::fmt;
+
+#[cfg(feature = "std")]
+use std::string::ToString;
+
+use crate::test_runner::Reason;
+
+/// Errors which can be returned from test cases to indicate non-successful
+/// completion.
+///
+/// Note that in spite of the name, `TestCaseError` is currently *not* an
+/// instance of `Error`, since otherwise `impl<E : Error> From<E>` could not be
+/// provided.
+///
+/// Any `Error` can be converted to a `TestCaseError`, which places
+/// `Error::display()` into the `Fail` case.
+#[derive(Debug, Clone)]
+pub enum TestCaseError {
+ /// The input was not valid for the test case. This does not count as a
+ /// test failure (nor a success); rather, it simply signals to generate
+ /// a new input and try again.
+ Reject(Reason),
+ /// The code under test failed the test.
+ Fail(Reason),
+}
+
+/// Indicates the type of test that ran successfully.
+///
+/// This is used for managing whether or not a success is counted against
+/// configured `PROPTEST_CASES`; only `NewCases` shall be counted.
+///
+/// TODO-v2: Ideally `TestCaseResult = Result<TestCaseOk, TestCaseError>`
+/// however this breaks source compability in version 1.x.x because
+/// `TestCaseResult` is public.
+#[derive(Debug, Clone)]
+pub(crate) enum TestCaseOk {
+ NewCaseSuccess,
+ PersistedCaseSuccess,
+ ReplayFromForkSuccess,
+ CacheHitSuccess,
+ Reject,
+}
+
+/// Convenience for the type returned by test cases.
+pub type TestCaseResult = Result<(), TestCaseError>;
+
+/// Intended to replace `TestCaseResult` in v2.
+///
+/// TODO-v2: Ideally `TestCaseResult = Result<TestCaseOk, TestCaseError>`
+/// however this breaks source compability in version 1.x.x because
+/// `TestCaseResult` is public.
+pub(crate) type TestCaseResultV2 = Result<TestCaseOk, TestCaseError>;
+
+impl TestCaseError {
+ /// Rejects the generated test input as invalid for this test case. This
+ /// does not count as a test failure (nor a success); rather, it simply
+ /// signals to generate a new input and try again.
+ ///
+ /// The string gives the location and context of the rejection, and
+ /// should be suitable for formatting like `Foo did X at {whence}`.
+ pub fn reject(reason: impl Into<Reason>) -> Self {
+ TestCaseError::Reject(reason.into())
+ }
+
+ /// The code under test failed the test.
+ ///
+ /// The string should indicate the location of the failure, but may
+ /// generally be any string.
+ pub fn fail(reason: impl Into<Reason>) -> Self {
+ TestCaseError::Fail(reason.into())
+ }
+}
+
+impl fmt::Display for TestCaseError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ TestCaseError::Reject(ref whence) => {
+ write!(f, "Input rejected at {}", whence)
+ }
+ TestCaseError::Fail(ref why) => write!(f, "Case failed: {}", why),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl<E: ::std::error::Error> From<E> for TestCaseError {
+ fn from(cause: E) -> Self {
+ TestCaseError::fail(cause.to_string())
+ }
+}
+
+/// A failure state from running test cases for a single test.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum TestError<T> {
+ /// The test was aborted for the given reason, for example, due to too many
+ /// inputs having been rejected.
+ Abort(Reason),
+ /// A failing test case was found. The string indicates where and/or why
+ /// the test failed. The `T` is the minimal input found to reproduce the
+ /// failure.
+ Fail(Reason, T),
+}
+
+impl<T: fmt::Debug> fmt::Display for TestError<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ TestError::Abort(ref why) => write!(f, "Test aborted: {}", why),
+ TestError::Fail(ref why, ref what) => write!(
+ f,
+ "Test failed: {}; minimal failing input: {:?}",
+ why, what
+ ),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+#[allow(deprecated)] // description()
+impl<T: fmt::Debug> ::std::error::Error for TestError<T> {
+ fn description(&self) -> &str {
+ match *self {
+ TestError::Abort(..) => "Abort",
+ TestError::Fail(..) => "Fail",
+ }
+ }
+}
diff --git a/vendor/proptest/src/test_runner/failure_persistence/file.rs b/vendor/proptest/src/test_runner/failure_persistence/file.rs
new file mode 100644
index 000000000..61d7dcf6a
--- /dev/null
+++ b/vendor/proptest/src/test_runner/failure_persistence/file.rs
@@ -0,0 +1,536 @@
+//-
+// Copyright 2017, 2018, 2019 The proptest 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.
+
+use core::any::Any;
+use core::fmt::Debug;
+use std::borrow::{Cow, ToOwned};
+use std::boxed::Box;
+use std::env;
+use std::fs;
+use std::io::{self, BufRead, Write};
+use std::path::{Path, PathBuf};
+use std::string::{String, ToString};
+use std::sync::RwLock;
+use std::vec::Vec;
+
+use self::FileFailurePersistence::*;
+use crate::test_runner::failure_persistence::{
+ FailurePersistence, PersistedSeed,
+};
+
+/// Describes how failing test cases are persisted.
+///
+/// Note that file names in this enum are `&str` rather than `&Path` since
+/// constant functions are not yet in Rust stable as of 2017-12-16.
+///
+/// In all cases, if a derived path references a directory which does not yet
+/// exist, proptest will attempt to create all necessary parent directories.
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum FileFailurePersistence {
+ /// Completely disables persistence of failing test cases.
+ ///
+ /// This is semantically equivalent to `Direct("/dev/null")` on Unix and
+ /// `Direct("NUL")` on Windows (though it is internally handled by simply
+ /// not doing any I/O).
+ Off,
+ /// The path given to `TestRunner::set_source_file()` is parsed. The path
+ /// is traversed up the directory tree until a directory containing a file
+ /// named `lib.rs` or `main.rs` is found. A sibling to that directory with
+ /// the name given by the string in this configuration is created, and a
+ /// file with the same name and path relative to the source directory, but
+ /// with the extension changed to `.txt`, is used.
+ ///
+ /// For example, given a source path of
+ /// `/home/jsmith/code/project/src/foo/bar.rs` and a configuration of
+ /// `SourceParallel("proptest-regressions")` (the default), assuming the
+ /// `src` directory has a `lib.rs` or `main.rs`, the resulting file would
+ /// be `/home/jsmith/code/project/proptest-regressions/foo/bar.txt`.
+ ///
+ /// If no `lib.rs` or `main.rs` can be found, a warning is printed and this
+ /// behaves like `WithSource`.
+ ///
+ /// If no source file has been configured, a warning is printed and this
+ /// behaves like `Off`.
+ SourceParallel(&'static str),
+ /// The path given to `TestRunner::set_source_file()` is parsed. The
+ /// extension of the path is changed to the string given in this
+ /// configuration, and that filename is used.
+ ///
+ /// For example, given a source path of
+ /// `/home/jsmith/code/project/src/foo/bar.rs` and a configuration of
+ /// `WithSource("regressions")`, the resulting path would be
+ /// `/home/jsmith/code/project/src/foo/bar.regressions`.
+ WithSource(&'static str),
+ /// The string given in this option is directly used as a file path without
+ /// any further processing.
+ Direct(&'static str),
+ #[doc(hidden)]
+ #[allow(missing_docs)]
+ _NonExhaustive,
+}
+
+impl Default for FileFailurePersistence {
+ fn default() -> Self {
+ SourceParallel("proptest-regressions")
+ }
+}
+
+impl FailurePersistence for FileFailurePersistence {
+ fn load_persisted_failures2(
+ &self,
+ source_file: Option<&'static str>,
+ ) -> Vec<PersistedSeed> {
+ let p = self.resolve(
+ source_file
+ .and_then(|s| absolutize_source_file(Path::new(s)))
+ .as_ref()
+ .map(|cow| &**cow),
+ );
+
+ let path: Option<&PathBuf> = p.as_ref();
+ let result: io::Result<Vec<PersistedSeed>> = path.map_or_else(
+ || Ok(vec![]),
+ |path| {
+ // .ok() instead of .unwrap() so we don't propagate panics here
+ let _lock = PERSISTENCE_LOCK.read().ok();
+ io::BufReader::new(fs::File::open(path)?)
+ .lines()
+ .enumerate()
+ .filter_map(|(lineno, line)| match line {
+ Err(err) => Some(Err(err)),
+ Ok(line) => parse_seed_line(line, path, lineno).map(Ok),
+ })
+ .collect()
+ },
+ );
+
+ unwrap_or!(result, err => {
+ if io::ErrorKind::NotFound != err.kind() {
+ eprintln!(
+ "proptest: failed to open {}: {}",
+ &path.map(|x| &**x)
+ .unwrap_or_else(|| Path::new("??"))
+ .display(),
+ err
+ );
+ }
+ vec![]
+ })
+ }
+
+ fn save_persisted_failure2(
+ &mut self,
+ source_file: Option<&'static str>,
+ seed: PersistedSeed,
+ shrunken_value: &dyn Debug,
+ ) {
+ let path = self.resolve(source_file.map(Path::new));
+ if let Some(path) = path {
+ // .ok() instead of .unwrap() so we don't propagate panics here
+ let _lock = PERSISTENCE_LOCK.write().ok();
+ let is_new = !path.is_file();
+
+ let mut to_write = Vec::<u8>::new();
+ if is_new {
+ write_header(&mut to_write)
+ .expect("proptest: couldn't write header.");
+ }
+
+ write_seed_line(&mut to_write, &seed, shrunken_value)
+ .expect("proptest: couldn't write seed line.");
+
+ if let Err(e) = write_seed_data_to_file(&path, &to_write) {
+ eprintln!(
+ "proptest: failed to append to {}: {}",
+ path.display(),
+ e
+ );
+ } else if is_new {
+ eprintln!(
+ "proptest: Saving this and future failures in {}\n\
+ proptest: If this test was run on a CI system, you may \
+ wish to add the following line to your copy of the file.{}\n\
+ {}",
+ path.display(),
+ if is_new { " (You may need to create it.)" } else { "" },
+ seed);
+ }
+ }
+ }
+
+ fn box_clone(&self) -> Box<dyn FailurePersistence> {
+ Box::new(*self)
+ }
+
+ fn eq(&self, other: &dyn FailurePersistence) -> bool {
+ other
+ .as_any()
+ .downcast_ref::<Self>()
+ .map_or(false, |x| x == self)
+ }
+
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+}
+
+/// Ensure that the source file to use for resolving the location of the persisted
+/// failing cases file is absolute.
+///
+/// The source location can only be used if it is absolute. If `source` is
+/// not an absolute path, an attempt will be made to determine the absolute
+/// path based on the current working directory and its parents. If no
+/// absolute path can be determined, a warning will be printed and proptest
+/// will continue as if this function had never been called.
+///
+/// See [`FileFailurePersistence`](enum.FileFailurePersistence.html) for details on
+/// how this value is used once it is made absolute.
+///
+/// This is normally called automatically by the `proptest!` macro, which
+/// passes `file!()`.
+///
+fn absolutize_source_file<'a>(source: &'a Path) -> Option<Cow<'a, Path>> {
+ absolutize_source_file_with_cwd(env::current_dir, source)
+}
+
+fn absolutize_source_file_with_cwd<'a>(
+ getcwd: impl FnOnce() -> io::Result<PathBuf>,
+ source: &'a Path,
+) -> Option<Cow<'a, Path>> {
+ if source.is_absolute() {
+ // On Unix, `file!()` is absolute. In these cases, we can use
+ // that path directly.
+ Some(Cow::Borrowed(source))
+ } else {
+ // On Windows, `file!()` is relative to the crate root, but the
+ // test is not generally run with the crate root as the working
+ // directory, so the path is not directly usable. However, the
+ // working directory is almost always a subdirectory of the crate
+ // root, so pop directories off until pushing the source onto the
+ // directory results in a path that refers to an existing file.
+ // Once we find such a path, we can use that.
+ //
+ // If we can't figure out an absolute path, print a warning and act
+ // as if no source had been given.
+ match getcwd() {
+ Ok(mut cwd) => loop {
+ let joined = cwd.join(source);
+ if joined.is_file() {
+ break Some(Cow::Owned(joined));
+ }
+
+ if !cwd.pop() {
+ eprintln!(
+ "proptest: Failed to find absolute path of \
+ source file '{:?}'. Ensure the test is \
+ being run from somewhere within the crate \
+ directory hierarchy.",
+ source
+ );
+ break None;
+ }
+ },
+
+ Err(e) => {
+ eprintln!(
+ "proptest: Failed to determine current \
+ directory, so the relative source path \
+ '{:?}' cannot be resolved: {}",
+ source, e
+ );
+ None
+ }
+ }
+ }
+}
+
+fn parse_seed_line(
+ mut line: String,
+ path: &Path,
+ lineno: usize,
+) -> Option<PersistedSeed> {
+ // Remove anything after and including '#':
+ if let Some(comment_start) = line.find('#') {
+ line.truncate(comment_start);
+ }
+
+ if line.len() > 0 {
+ let ret = line.parse::<PersistedSeed>().ok();
+ if !ret.is_some() {
+ eprintln!(
+ "proptest: {}:{}: unparsable line, ignoring",
+ path.display(),
+ lineno + 1
+ );
+ }
+ return ret;
+ }
+
+ None
+}
+
+fn write_seed_line(
+ buf: &mut Vec<u8>,
+ seed: &PersistedSeed,
+ shrunken_value: &dyn Debug,
+) -> io::Result<()> {
+ // Write the seed itself
+ write!(buf, "{}", seed.to_string())?;
+
+ // Write out comment:
+ let debug_start = buf.len();
+ write!(buf, " # shrinks to {:?}", shrunken_value)?;
+
+ // Ensure there are no newlines in the debug output
+ for byte in &mut buf[debug_start..] {
+ if b'\n' == *byte || b'\r' == *byte {
+ *byte = b' ';
+ }
+ }
+
+ buf.push(b'\n');
+
+ Ok(())
+}
+
+fn write_header(buf: &mut Vec<u8>) -> io::Result<()> {
+ writeln!(
+ buf,
+ "\
+# Seeds for failure cases proptest has generated in the past. It is
+# automatically read and these particular cases re-run before any
+# novel cases are generated.
+#
+# It is recommended to check this file in to source control so that
+# everyone who runs the test benefits from these saved cases."
+ )
+}
+
+fn write_seed_data_to_file(dst: &Path, data: &[u8]) -> io::Result<()> {
+ if let Some(parent) = dst.parent() {
+ fs::create_dir_all(parent)?;
+ }
+
+ let mut options = fs::OpenOptions::new();
+ options.append(true).create(true);
+ let mut out = options.open(dst)?;
+ out.write_all(data)?;
+
+ Ok(())
+}
+
+impl FileFailurePersistence {
+ /// Given the nominal source path, determine the location of the failure
+ /// persistence file, if any.
+ pub(super) fn resolve(&self, source: Option<&Path>) -> Option<PathBuf> {
+ let source = source.and_then(absolutize_source_file);
+
+ match *self {
+ Off => None,
+
+ SourceParallel(sibling) => match source {
+ Some(source_path) => {
+ let mut dir = Cow::into_owned(source_path.clone());
+ let mut found = false;
+ while dir.pop() {
+ if dir.join("lib.rs").is_file()
+ || dir.join("main.rs").is_file()
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if !found {
+ eprintln!(
+ "proptest: FileFailurePersistence::SourceParallel set, \
+ but failed to find lib.rs or main.rs"
+ );
+ WithSource(sibling).resolve(Some(&*source_path))
+ } else {
+ let suffix = source_path
+ .strip_prefix(&dir)
+ .expect("parent of source is not a prefix of it?")
+ .to_owned();
+ let mut result = dir;
+ // If we've somehow reached the root, or someone gave
+ // us a relative path that we've exhausted, just accept
+ // creating a subdirectory instead.
+ let _ = result.pop();
+ result.push(sibling);
+ result.push(&suffix);
+ result.set_extension("txt");
+ Some(result)
+ }
+ }
+ None => {
+ eprintln!(
+ "proptest: FileFailurePersistence::SourceParallel set, \
+ but no source file known"
+ );
+ None
+ }
+ },
+
+ WithSource(extension) => match source {
+ Some(source_path) => {
+ let mut result = Cow::into_owned(source_path);
+ result.set_extension(extension);
+ Some(result)
+ }
+
+ None => {
+ eprintln!(
+ "proptest: FileFailurePersistence::WithSource set, \
+ but no source file known"
+ );
+ None
+ }
+ },
+
+ Direct(path) => Some(Path::new(path).to_owned()),
+
+ _NonExhaustive => {
+ panic!("FailurePersistence set to _NonExhaustive")
+ }
+ }
+ }
+}
+
+lazy_static! {
+ /// Used to guard access to the persistence file(s) so that a single
+ /// process will not step on its own toes.
+ ///
+ /// We don't have much protecting us should two separate process try to
+ /// write to the same file at once (depending on how atomic append mode is
+ /// on the OS), but this should be extremely rare.
+ static ref PERSISTENCE_LOCK: RwLock<()> = RwLock::new(());
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ struct TestPaths {
+ crate_root: &'static Path,
+ src_file: PathBuf,
+ subdir_file: PathBuf,
+ misplaced_file: PathBuf,
+ }
+
+ lazy_static! {
+ static ref TEST_PATHS: TestPaths = {
+ let crate_root = Path::new(env!("CARGO_MANIFEST_DIR"));
+ let lib_root = crate_root.join("src");
+ let src_subdir = lib_root.join("strategy");
+ let src_file = lib_root.join("foo.rs");
+ let subdir_file = src_subdir.join("foo.rs");
+ let misplaced_file = crate_root.join("foo.rs");
+ TestPaths {
+ crate_root,
+ src_file,
+ subdir_file,
+ misplaced_file,
+ }
+ };
+ }
+
+ #[test]
+ fn persistence_file_location_resolved_correctly() {
+ // If off, there is never a file
+ assert_eq!(None, Off.resolve(None));
+ assert_eq!(None, Off.resolve(Some(&TEST_PATHS.subdir_file)));
+
+ // For direct, we don't care about the source file, and instead always
+ // use whatever is in the config.
+ assert_eq!(
+ Some(Path::new("bar.txt").to_owned()),
+ Direct("bar.txt").resolve(None)
+ );
+ assert_eq!(
+ Some(Path::new("bar.txt").to_owned()),
+ Direct("bar.txt").resolve(Some(&TEST_PATHS.subdir_file))
+ );
+
+ // For WithSource, only the extension changes, but we get nothing if no
+ // source file was configured.
+ // Accounting for the way absolute paths work on Windows would be more
+ // complex, so for now don't test that case.
+ #[cfg(unix)]
+ fn absolute_path_case() {
+ assert_eq!(
+ Some(Path::new("/foo/bar.ext").to_owned()),
+ WithSource("ext").resolve(Some(Path::new("/foo/bar.rs")))
+ );
+ }
+ #[cfg(not(unix))]
+ fn absolute_path_case() {}
+ absolute_path_case();
+ assert_eq!(None, WithSource("ext").resolve(None));
+
+ // For SourceParallel, we make a sibling directory tree and change the
+ // extensions to .txt ...
+ assert_eq!(
+ Some(TEST_PATHS.crate_root.join("sib").join("foo.txt")),
+ SourceParallel("sib").resolve(Some(&TEST_PATHS.src_file))
+ );
+ assert_eq!(
+ Some(
+ TEST_PATHS
+ .crate_root
+ .join("sib")
+ .join("strategy")
+ .join("foo.txt")
+ ),
+ SourceParallel("sib").resolve(Some(&TEST_PATHS.subdir_file))
+ );
+ // ... but if we can't find lib.rs / main.rs, give up and set the
+ // extension instead ...
+ assert_eq!(
+ Some(TEST_PATHS.crate_root.join("foo.sib")),
+ SourceParallel("sib").resolve(Some(&TEST_PATHS.misplaced_file))
+ );
+ // ... and if no source is configured, we do nothing
+ assert_eq!(None, SourceParallel("ext").resolve(None));
+ }
+
+ #[test]
+ fn relative_source_files_absolutified() {
+ const TEST_RUNNER_PATH: &[&str] = &["src", "test_runner", "mod.rs"];
+ lazy_static! {
+ static ref TEST_RUNNER_RELATIVE: PathBuf =
+ TEST_RUNNER_PATH.iter().collect();
+ }
+ const CARGO_DIR: &str = env!("CARGO_MANIFEST_DIR");
+
+ let expected = ::std::iter::once(CARGO_DIR)
+ .chain(TEST_RUNNER_PATH.iter().map(|s| *s))
+ .collect::<PathBuf>();
+
+ // Running from crate root
+ assert_eq!(
+ &*expected,
+ absolutize_source_file_with_cwd(
+ || Ok(Path::new(CARGO_DIR).to_owned()),
+ &TEST_RUNNER_RELATIVE
+ )
+ .unwrap()
+ );
+
+ // Running from test subdirectory
+ assert_eq!(
+ &*expected,
+ absolutize_source_file_with_cwd(
+ || Ok(Path::new(CARGO_DIR).join("target")),
+ &TEST_RUNNER_RELATIVE
+ )
+ .unwrap()
+ );
+ }
+}
diff --git a/vendor/proptest/src/test_runner/failure_persistence/map.rs b/vendor/proptest/src/test_runner/failure_persistence/map.rs
new file mode 100644
index 000000000..322e554c6
--- /dev/null
+++ b/vendor/proptest/src/test_runner/failure_persistence/map.rs
@@ -0,0 +1,99 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+use crate::std_facade::{fmt, BTreeMap, BTreeSet, Box, Vec};
+use core::any::Any;
+
+use crate::test_runner::failure_persistence::FailurePersistence;
+use crate::test_runner::failure_persistence::PersistedSeed;
+
+/// Failure persistence option that loads and saves seeds in memory
+/// on the heap. This may be useful when accumulating test failures
+/// across multiple `TestRunner` instances for external reporting
+/// or batched persistence.
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct MapFailurePersistence {
+ /// Backing map, keyed by source_file.
+ pub map: BTreeMap<&'static str, BTreeSet<PersistedSeed>>,
+}
+
+impl FailurePersistence for MapFailurePersistence {
+ fn load_persisted_failures2(
+ &self,
+ source_file: Option<&'static str>,
+ ) -> Vec<PersistedSeed> {
+ source_file
+ .and_then(|source| self.map.get(source))
+ .map(|seeds| seeds.iter().cloned().collect::<Vec<_>>())
+ .unwrap_or_default()
+ }
+
+ fn save_persisted_failure2(
+ &mut self,
+ source_file: Option<&'static str>,
+ seed: PersistedSeed,
+ _shrunken_value: &dyn fmt::Debug,
+ ) {
+ let s = match source_file {
+ Some(sf) => sf,
+ None => return,
+ };
+ let set = self.map.entry(s).or_insert_with(BTreeSet::new);
+ set.insert(seed);
+ }
+
+ fn box_clone(&self) -> Box<dyn FailurePersistence> {
+ Box::new(self.clone())
+ }
+
+ fn eq(&self, other: &dyn FailurePersistence) -> bool {
+ other
+ .as_any()
+ .downcast_ref::<Self>()
+ .map_or(false, |x| x == self)
+ }
+
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::test_runner::failure_persistence::tests::*;
+
+ #[test]
+ fn initial_map_is_empty() {
+ assert!(MapFailurePersistence::default()
+ .load_persisted_failures2(HI_PATH)
+ .is_empty())
+ }
+
+ #[test]
+ fn seeds_recoverable() {
+ let mut p = MapFailurePersistence::default();
+ p.save_persisted_failure2(HI_PATH, INC_SEED, &"");
+ let restored = p.load_persisted_failures2(HI_PATH);
+ assert_eq!(1, restored.len());
+ assert_eq!(INC_SEED, *restored.first().unwrap());
+
+ assert!(p.load_persisted_failures2(None).is_empty());
+ assert!(p.load_persisted_failures2(UNREL_PATH).is_empty());
+ }
+
+ #[test]
+ fn seeds_deduplicated() {
+ let mut p = MapFailurePersistence::default();
+ p.save_persisted_failure2(HI_PATH, INC_SEED, &"");
+ p.save_persisted_failure2(HI_PATH, INC_SEED, &"");
+ let restored = p.load_persisted_failures2(HI_PATH);
+ assert_eq!(1, restored.len());
+ }
+}
diff --git a/vendor/proptest/src/test_runner/failure_persistence/mod.rs b/vendor/proptest/src/test_runner/failure_persistence/mod.rs
new file mode 100644
index 000000000..6d21c4002
--- /dev/null
+++ b/vendor/proptest/src/test_runner/failure_persistence/mod.rs
@@ -0,0 +1,156 @@
+//-
+// Copyright 2017, 2018, 2019 The proptest 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.
+
+use crate::std_facade::{fmt, Box, Vec};
+use core::any::Any;
+use core::fmt::Display;
+use core::result::Result;
+use core::str::FromStr;
+
+#[cfg(feature = "std")]
+mod file;
+mod map;
+mod noop;
+
+#[cfg(feature = "std")]
+pub use self::file::*;
+pub use self::map::*;
+pub use self::noop::*;
+
+use crate::test_runner::Seed;
+
+/// Opaque struct representing a seed which can be persisted.
+///
+/// The `Display` and `FromStr` implementations go to and from the format
+/// Proptest uses for its persistence file.
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct PersistedSeed(pub(crate) Seed);
+
+impl Display for PersistedSeed {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.0.to_persistence())
+ }
+}
+
+impl FromStr for PersistedSeed {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, ()> {
+ Seed::from_persistence(s).map(PersistedSeed).ok_or(())
+ }
+}
+
+/// Provides external persistence for historical test failures by storing seeds.
+///
+/// **Note**: Implementing `load_persisted_failures` and
+/// `save_persisted_failures` is **deprecated** and these methods will be
+/// removed in proptest 0.10.0. Instead, implement `load_persisted_failures2`
+/// and `save_persisted_failures2`.
+pub trait FailurePersistence: Send + Sync + fmt::Debug {
+ /// Supply seeds associated with the given `source_file` that may be used
+ /// by a `TestRunner`'s random number generator in order to consistently
+ /// recreate a previously-failing `Strategy`-provided value.
+ ///
+ /// The default implementation is **for backwards compatibility**. It
+ /// delegates to `load_persisted_failures` and converts the results into
+ /// XorShift seeds.
+ #[allow(deprecated)]
+ fn load_persisted_failures2(
+ &self,
+ source_file: Option<&'static str>,
+ ) -> Vec<PersistedSeed> {
+ self.load_persisted_failures(source_file)
+ .into_iter()
+ .map(|seed| PersistedSeed(Seed::XorShift(seed)))
+ .collect()
+ }
+
+ /// Use `load_persisted_failures2` instead.
+ ///
+ /// This function inadvertently exposes the implementation of seeds prior
+ /// to Proptest 0.9.1 and only works with XorShift seeds.
+ #[deprecated]
+ #[allow(unused_variables)]
+ fn load_persisted_failures(
+ &self,
+ source_file: Option<&'static str>,
+ ) -> Vec<[u8; 16]> {
+ panic!("load_persisted_failures2 not implemented");
+ }
+
+ /// Store a new failure-generating seed associated with the given `source_file`.
+ ///
+ /// The default implementation is **for backwards compatibility**. It
+ /// delegates to `save_persisted_failure` if `seed` is a XorShift seed.
+ #[allow(deprecated)]
+ fn save_persisted_failure2(
+ &mut self,
+ source_file: Option<&'static str>,
+ seed: PersistedSeed,
+ shrunken_value: &dyn fmt::Debug,
+ ) {
+ match seed.0 {
+ Seed::XorShift(seed) => {
+ self.save_persisted_failure(source_file, seed, shrunken_value)
+ }
+ _ => (),
+ }
+ }
+
+ /// Use `save_persisted_failures2` instead.
+ ///
+ /// This function inadvertently exposes the implementation of seeds prior
+ /// to Proptest 0.9.1 and only works with XorShift seeds.
+ #[deprecated]
+ #[allow(unused_variables)]
+ fn save_persisted_failure(
+ &mut self,
+ source_file: Option<&'static str>,
+ seed: [u8; 16],
+ shrunken_value: &dyn fmt::Debug,
+ ) {
+ panic!("save_persisted_failure2 not implemented");
+ }
+
+ /// Delegate method for producing a trait object usable with `Clone`
+ fn box_clone(&self) -> Box<dyn FailurePersistence>;
+
+ /// Equality testing delegate required due to constraints of trait objects.
+ fn eq(&self, other: &dyn FailurePersistence) -> bool;
+
+ /// Assistant method for trait object comparison.
+ fn as_any(&self) -> &dyn Any;
+}
+
+impl<'a, 'b> PartialEq<dyn FailurePersistence + 'b>
+ for dyn FailurePersistence + 'a
+{
+ fn eq(&self, other: &(dyn FailurePersistence + 'b)) -> bool {
+ FailurePersistence::eq(self, other)
+ }
+}
+
+impl Clone for Box<dyn FailurePersistence> {
+ fn clone(&self) -> Box<dyn FailurePersistence> {
+ self.box_clone()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::PersistedSeed;
+ use crate::test_runner::rng::Seed;
+
+ pub const INC_SEED: PersistedSeed = PersistedSeed(Seed::XorShift([
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ ]));
+
+ pub const HI_PATH: Option<&str> = Some("hi");
+ pub const UNREL_PATH: Option<&str> = Some("unrelated");
+}
diff --git a/vendor/proptest/src/test_runner/failure_persistence/noop.rs b/vendor/proptest/src/test_runner/failure_persistence/noop.rs
new file mode 100644
index 000000000..59538392a
--- /dev/null
+++ b/vendor/proptest/src/test_runner/failure_persistence/noop.rs
@@ -0,0 +1,76 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+use crate::std_facade::{fmt, Box, Vec};
+use core::any::Any;
+
+use crate::test_runner::failure_persistence::{
+ FailurePersistence, PersistedSeed,
+};
+
+/// Failure persistence option that loads and saves nothing at all.
+#[derive(Debug, Default, PartialEq)]
+struct NoopFailurePersistence;
+
+impl FailurePersistence for NoopFailurePersistence {
+ fn load_persisted_failures2(
+ &self,
+ _source_file: Option<&'static str>,
+ ) -> Vec<PersistedSeed> {
+ Vec::new()
+ }
+
+ fn save_persisted_failure2(
+ &mut self,
+ _source_file: Option<&'static str>,
+ _seed: PersistedSeed,
+ _shrunken_value: &dyn fmt::Debug,
+ ) {
+ }
+
+ fn box_clone(&self) -> Box<dyn FailurePersistence> {
+ Box::new(NoopFailurePersistence)
+ }
+
+ fn eq(&self, other: &dyn FailurePersistence) -> bool {
+ other
+ .as_any()
+ .downcast_ref::<Self>()
+ .map_or(false, |x| x == self)
+ }
+
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::test_runner::failure_persistence::tests::*;
+
+ #[test]
+ fn default_load_is_empty() {
+ assert!(NoopFailurePersistence::default()
+ .load_persisted_failures2(None)
+ .is_empty());
+ assert!(NoopFailurePersistence::default()
+ .load_persisted_failures2(HI_PATH)
+ .is_empty());
+ }
+
+ #[test]
+ fn seeds_not_recoverable() {
+ let mut p = NoopFailurePersistence::default();
+ p.save_persisted_failure2(HI_PATH, INC_SEED, &"");
+ assert!(p.load_persisted_failures2(HI_PATH).is_empty());
+ assert!(p.load_persisted_failures2(None).is_empty());
+ assert!(p.load_persisted_failures2(UNREL_PATH).is_empty());
+ }
+}
diff --git a/vendor/proptest/src/test_runner/mod.rs b/vendor/proptest/src/test_runner/mod.rs
new file mode 100644
index 000000000..d7516ab96
--- /dev/null
+++ b/vendor/proptest/src/test_runner/mod.rs
@@ -0,0 +1,31 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+//! State and functions for running proptest tests.
+//!
+//! You do not normally need to access things in this module directly except
+//! when implementing new low-level strategies.
+
+mod config;
+mod errors;
+mod failure_persistence;
+mod reason;
+#[cfg(feature = "fork")]
+mod replay;
+mod result_cache;
+mod rng;
+mod runner;
+
+pub use self::config::*;
+pub use self::errors::*;
+pub use self::failure_persistence::*;
+pub use self::reason::*;
+pub use self::result_cache::*;
+pub use self::rng::*;
+pub use self::runner::*;
diff --git a/vendor/proptest/src/test_runner/reason.rs b/vendor/proptest/src/test_runner/reason.rs
new file mode 100644
index 000000000..38cc7e322
--- /dev/null
+++ b/vendor/proptest/src/test_runner/reason.rs
@@ -0,0 +1,54 @@
+//-
+// Copyright 2017, 2018 The proptest 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.
+
+use crate::std_facade::{fmt, Box, Cow, String};
+
+/// The reason for why something, such as a generated value, was rejected.
+///
+/// Currently this is merely a wrapper around a message, but more properties
+/// may be added in the future.
+///
+/// This is constructed via `.into()` on a `String`, `&'static str`, or
+/// `Box<str>`.
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Reason(Cow<'static, str>);
+
+impl Reason {
+ /// Return the message for this `Reason`.
+ ///
+ /// The message is intended for human consumption, and is not guaranteed to
+ /// have any format in particular.
+ pub fn message(&self) -> &str {
+ &*self.0
+ }
+}
+
+impl From<&'static str> for Reason {
+ fn from(s: &'static str) -> Self {
+ Reason(s.into())
+ }
+}
+
+impl From<String> for Reason {
+ fn from(s: String) -> Self {
+ Reason(s.into())
+ }
+}
+
+impl From<Box<str>> for Reason {
+ fn from(s: Box<str>) -> Self {
+ Reason(String::from(s).into())
+ }
+}
+
+impl fmt::Display for Reason {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(self.message(), f)
+ }
+}
diff --git a/vendor/proptest/src/test_runner/replay.rs b/vendor/proptest/src/test_runner/replay.rs
new file mode 100644
index 000000000..4365d5538
--- /dev/null
+++ b/vendor/proptest/src/test_runner/replay.rs
@@ -0,0 +1,189 @@
+//-
+// Copyright 2018 The proptest 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.
+
+#![allow(dead_code)]
+
+use std::fs;
+use std::io::{self, BufRead, Read, Seek, Write};
+use std::path::Path;
+use std::string::String;
+use std::vec::Vec;
+
+use crate::test_runner::{Seed, TestCaseError, TestCaseResult};
+
+const SENTINEL: &'static str = "proptest-forkfile";
+
+/// A "replay" of a `TestRunner` invocation.
+///
+/// The replay mechanism is used to support forking. When a child process
+/// exits, the parent can read the replay to reproduce the state the child had;
+/// similarly, if a child crashes, a new one can be started and given a replay
+/// which steps it one complication past the input that caused the crash.
+///
+/// The replay system is tightly coupled to the `TestRunner` itself. It does
+/// not carry enough information to be used in different builds of the same
+/// application, or even two different runs of the test process since changes
+/// to the persistence file will perturb the replay.
+///
+/// `Replay` has a special string format for being stored in files. It starts
+/// with a line just containing the text in `SENTINEL`, then 16 lines
+/// containing the values of `seed`, then an unterminated line consisting of
+/// `+`, `-`, and `!` characters to indicate test case passes/failures/rejects,
+/// `.` to indicate termination of the test run, or ` ` as a dummy "I'm alive"
+/// signal. This format makes it easy for the child process to blindly append
+/// to the file without having to worry about the possibility of appends being
+/// non-atomic.
+#[derive(Clone, Debug)]
+pub(crate) struct Replay {
+ /// The seed of the RNG used to start running the test cases.
+ pub(crate) seed: Seed,
+ /// A log of whether certain test cases passed or failed. The runner will
+ /// assume the same results occur without actually running the test cases.
+ pub(crate) steps: Vec<TestCaseResult>,
+}
+
+impl Replay {
+ /// If `other` is longer than `self`, add the extra elements to `self`.
+ pub fn merge(&mut self, other: &Replay) {
+ if other.steps.len() > self.steps.len() {
+ let sl = self.steps.len();
+ self.steps.extend_from_slice(&other.steps[sl..]);
+ }
+ }
+}
+
+/// Result of loading a replay file.
+#[derive(Clone, Debug)]
+pub(crate) enum ReplayFileStatus {
+ /// The file is valid and represents a currently-in-progress test.
+ InProgress(Replay),
+ /// The file is valid, but indicates that all testing has completed.
+ Terminated(Replay),
+ /// The file is not parsable.
+ Corrupt,
+}
+
+/// Open the file in the usual read+append+create mode.
+pub(crate) fn open_file(path: impl AsRef<Path>) -> io::Result<fs::File> {
+ fs::OpenOptions::new()
+ .read(true)
+ .append(true)
+ .create(true)
+ .truncate(false)
+ .open(path)
+}
+
+fn step_to_char(step: &TestCaseResult) -> char {
+ match *step {
+ Ok(_) => '+',
+ Err(TestCaseError::Reject(_)) => '!',
+ Err(TestCaseError::Fail(_)) => '-',
+ }
+}
+
+/// Append the given step to the given output.
+pub(crate) fn append(
+ mut file: impl Write,
+ step: &TestCaseResult,
+) -> io::Result<()> {
+ write!(file, "{}", step_to_char(step))
+}
+
+/// Append a no-op step to the given output.
+pub(crate) fn ping(mut file: impl Write) -> io::Result<()> {
+ write!(file, " ")
+}
+
+/// Append a termination mark to the given output.
+pub(crate) fn terminate(mut file: impl Write) -> io::Result<()> {
+ write!(file, ".")
+}
+
+impl Replay {
+ /// Write the full state of this `Replay` to the given output.
+ pub fn init_file(&self, mut file: impl Write) -> io::Result<()> {
+ writeln!(file, "{}", SENTINEL)?;
+ writeln!(file, "{}", self.seed.to_persistence())?;
+
+ let mut step_data = Vec::<u8>::new();
+ for step in &self.steps {
+ step_data.push(step_to_char(step) as u8);
+ }
+
+ file.write_all(&step_data)?;
+
+ Ok(())
+ }
+
+ /// Mark the replay as complete in the file.
+ pub fn complete(mut file: impl Write) -> io::Result<()> {
+ write!(file, ".")
+ }
+
+ /// Parse a `Replay` out of the given file.
+ ///
+ /// The reader is implicitly seeked to the beginning before reading.
+ pub fn parse_from(
+ mut file: impl Read + Seek,
+ ) -> io::Result<ReplayFileStatus> {
+ file.seek(io::SeekFrom::Start(0))?;
+
+ let mut reader = io::BufReader::new(&mut file);
+ let mut line = String::new();
+
+ // Ensure it starts with the sentinel. We do this since we rely on a
+ // named temporary file which could be in a location where another
+ // actor could replace it with, eg, a symlink to a location they don't
+ // control but we do. By rejecting a read from a file missing the
+ // sentinel, and not doing any writes if we can't read the file, we
+ // won't risk overwriting another file since the prospective attacker
+ // would need to be able to change the file to start with the sentinel
+ // themselves.
+ //
+ // There are still some possible symlink attacks that can work by
+ // tricking us into reading, but those are non-destructive things like
+ // interfering with a FIFO or Unix socket.
+ reader.read_line(&mut line)?;
+ if SENTINEL != line.trim() {
+ return Ok(ReplayFileStatus::Corrupt);
+ }
+
+ line.clear();
+ reader.read_line(&mut line)?;
+ let seed = match Seed::from_persistence(&line) {
+ Some(seed) => seed,
+ None => return Ok(ReplayFileStatus::Corrupt),
+ };
+
+ line.clear();
+ reader.read_line(&mut line)?;
+
+ let mut steps = Vec::new();
+ for ch in line.chars() {
+ match ch {
+ '+' => steps.push(Ok(())),
+ '-' => steps
+ .push(Err(TestCaseError::fail("failed in other process"))),
+ '!' => steps.push(Err(TestCaseError::reject(
+ "rejected in other process",
+ ))),
+ '.' => {
+ return Ok(ReplayFileStatus::Terminated(Replay {
+ seed,
+ steps,
+ }))
+ }
+ ' ' => (),
+ _ => return Ok(ReplayFileStatus::Corrupt),
+ }
+ }
+
+ Ok(ReplayFileStatus::InProgress(Replay { seed, steps }))
+ }
+}
diff --git a/vendor/proptest/src/test_runner/result_cache.rs b/vendor/proptest/src/test_runner/result_cache.rs
new file mode 100644
index 000000000..c5bc68c3a
--- /dev/null
+++ b/vendor/proptest/src/test_runner/result_cache.rs
@@ -0,0 +1,120 @@
+//-
+// Copyright 2018 The proptest 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.
+
+use crate::std_facade::fmt;
+use crate::std_facade::Box;
+#[cfg(feature = "std")]
+use std::collections::HashMap;
+
+use crate::test_runner::errors::TestCaseResult;
+
+/// A key used for the result cache.
+///
+/// The capabilities of this structure are currently quite limited; all one can
+/// do with safe code is get the `&dyn Debug` of the test input value. This may
+/// improve in the future, particularly at such a time that specialisation
+/// becomes stable.
+#[derive(Debug)]
+pub struct ResultCacheKey<'a> {
+ value: &'a dyn fmt::Debug,
+}
+
+impl<'a> ResultCacheKey<'a> {
+ pub(crate) fn new(value: &'a dyn fmt::Debug) -> Self {
+ Self { value }
+ }
+
+ /// Return the test input value as an `&dyn Debug`.
+ pub fn value_debug(&self) -> &dyn fmt::Debug {
+ self.value
+ }
+}
+
+/// An object which can cache the outcomes of tests.
+pub trait ResultCache {
+ /// Convert the given cache key into a `u64` representing that value. The
+ /// u64 is used as the key below.
+ ///
+ /// This is a separate step so that ownership of the key value can be
+ /// handed off to user code without needing to be able to clone it.
+ fn key(&self, key: &ResultCacheKey) -> u64;
+ /// Save `result` as the outcome associated with the test input in `key`.
+ ///
+ /// `result` is passed as a reference so that the decision to clone depends
+ /// on whether the cache actually plans on storing it.
+ fn put(&mut self, key: u64, result: &TestCaseResult);
+ /// If `put()` has been called with a semantically equivalent `key`, return
+ /// the saved result. Otherwise, return `None`.
+ fn get(&self, key: u64) -> Option<&TestCaseResult>;
+}
+
+#[cfg(feature = "std")]
+#[derive(Debug, Default, Clone)]
+struct BasicResultCache {
+ entries: HashMap<u64, TestCaseResult>,
+}
+
+#[cfg(feature = "std")]
+impl ResultCache for BasicResultCache {
+ fn key(&self, val: &ResultCacheKey) -> u64 {
+ use std::collections::hash_map::DefaultHasher;
+ use std::hash::Hasher;
+ use std::io::{self, Write};
+
+ struct HashWriter(DefaultHasher);
+ impl io::Write for HashWriter {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ self.0.write(buf);
+ Ok(buf.len())
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ Ok(())
+ }
+ }
+
+ let mut hash = HashWriter(DefaultHasher::default());
+ write!(hash, "{:?}", val).expect("Debug format returned Err");
+ hash.0.finish()
+ }
+
+ fn put(&mut self, key: u64, result: &TestCaseResult) {
+ self.entries.insert(key, result.clone());
+ }
+
+ fn get(&self, key: u64) -> Option<&TestCaseResult> {
+ self.entries.get(&key)
+ }
+}
+
+/// A basic result cache.
+///
+/// Values are identified by their `Debug` string representation.
+#[cfg(feature = "std")]
+pub fn basic_result_cache() -> Box<dyn ResultCache> {
+ Box::new(BasicResultCache::default())
+}
+
+pub(crate) struct NoOpResultCache;
+impl ResultCache for NoOpResultCache {
+ fn key(&self, _: &ResultCacheKey) -> u64 {
+ 0
+ }
+ fn put(&mut self, _: u64, _: &TestCaseResult) {}
+ fn get(&self, _: u64) -> Option<&TestCaseResult> {
+ None
+ }
+}
+
+/// A result cache that does nothing.
+///
+/// This is the default value of `ProptestConfig.result_cache`.
+pub fn noop_result_cache() -> Box<dyn ResultCache> {
+ Box::new(NoOpResultCache)
+}
diff --git a/vendor/proptest/src/test_runner/rng.rs b/vendor/proptest/src/test_runner/rng.rs
new file mode 100644
index 000000000..78c8d7a75
--- /dev/null
+++ b/vendor/proptest/src/test_runner/rng.rs
@@ -0,0 +1,724 @@
+//-
+// Copyright 2017, 2018, 2019, 2020 The proptest 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.
+
+use crate::std_facade::{Arc, String, ToOwned, Vec};
+use core::result::Result;
+use core::{fmt, str, u8};
+
+use byteorder::{ByteOrder, LittleEndian};
+use rand::{self, Rng, RngCore, SeedableRng};
+use rand_chacha::ChaChaRng;
+use rand_xorshift::XorShiftRng;
+
+/// Identifies a particular RNG algorithm supported by proptest.
+///
+/// Proptest supports dynamic configuration of algorithms to allow it to
+/// continue operating with persisted regression files and to allow the
+/// configuration to be expressed in the `Config` struct.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum RngAlgorithm {
+ /// The [XorShift](https://rust-random.github.io/rand/rand_xorshift/struct.XorShiftRng.html)
+ /// algorithm. This was the default up through and including Proptest 0.9.0.
+ ///
+ /// It is faster than ChaCha but produces lower quality randomness and has
+ /// some pathological cases where it may fail to produce outputs that are
+ /// random even to casual observation.
+ ///
+ /// The seed must be exactly 16 bytes.
+ XorShift,
+ /// The [ChaCha](https://rust-random.github.io/rand/rand_chacha/struct.ChaChaRng.html)
+ /// algorithm. This became the default with Proptest 0.9.1.
+ ///
+ /// The seed must be exactly 32 bytes.
+ ChaCha,
+ /// This is not an actual RNG algorithm, but instead returns data directly
+ /// from its "seed".
+ ///
+ /// This is useful when Proptest is being driven from some other entropy
+ /// source, such as a fuzzer.
+ ///
+ /// If the seed is depleted, the RNG will return 0s forever.
+ ///
+ /// Note that in cases where a new RNG is to be derived from an existing
+ /// one, *the data is split evenly between them*, regardless of how much
+ /// entropy is actually needed. This means that combinators like
+ /// `prop_perturb` and `prop_flat_map` can require extremely large inputs.
+ PassThrough,
+ /// This is equivalent to the `ChaCha` RNG, with the addition that it
+ /// records the bytes used to create a value.
+ ///
+ /// This is useful when Proptest is used for fuzzing, and a corpus of
+ /// initial inputs need to be created. Note that in these cases, you need
+ /// to use the `TestRunner` API directly yourself instead of using the
+ /// `proptest!` macro, as otherwise there is no way to obtain the bytes
+ /// this captures.
+ Recorder,
+ #[allow(missing_docs)]
+ #[doc(hidden)]
+ _NonExhaustive,
+}
+
+impl Default for RngAlgorithm {
+ fn default() -> Self {
+ RngAlgorithm::ChaCha
+ }
+}
+
+impl RngAlgorithm {
+ pub(crate) fn persistence_key(self) -> &'static str {
+ match self {
+ RngAlgorithm::XorShift => "xs",
+ RngAlgorithm::ChaCha => "cc",
+ RngAlgorithm::PassThrough => "pt",
+ RngAlgorithm::Recorder => "rc",
+ RngAlgorithm::_NonExhaustive => unreachable!(),
+ }
+ }
+
+ pub(crate) fn from_persistence_key(k: &str) -> Option<Self> {
+ match k {
+ "xs" => Some(RngAlgorithm::XorShift),
+ "cc" => Some(RngAlgorithm::ChaCha),
+ "pt" => Some(RngAlgorithm::PassThrough),
+ "rc" => Some(RngAlgorithm::Recorder),
+ _ => None,
+ }
+ }
+}
+
+// These two are only used for parsing the environment variable
+// PROPTEST_RNG_ALGORITHM.
+impl str::FromStr for RngAlgorithm {
+ type Err = ();
+ fn from_str(s: &str) -> Result<Self, ()> {
+ RngAlgorithm::from_persistence_key(s).ok_or(())
+ }
+}
+impl fmt::Display for RngAlgorithm {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.persistence_key())
+ }
+}
+
+/// Proptest's random number generator.
+#[derive(Clone, Debug)]
+pub struct TestRng {
+ rng: TestRngImpl,
+}
+
+#[derive(Clone, Debug)]
+enum TestRngImpl {
+ XorShift(XorShiftRng),
+ ChaCha(ChaChaRng),
+ PassThrough {
+ off: usize,
+ end: usize,
+ data: Arc<[u8]>,
+ },
+ Recorder {
+ rng: ChaChaRng,
+ record: Vec<u8>,
+ },
+}
+
+impl RngCore for TestRng {
+ fn next_u32(&mut self) -> u32 {
+ match &mut self.rng {
+ &mut TestRngImpl::XorShift(ref mut rng) => rng.next_u32(),
+
+ &mut TestRngImpl::ChaCha(ref mut rng) => rng.next_u32(),
+
+ &mut TestRngImpl::PassThrough { .. } => {
+ let mut buf = [0; 4];
+ self.fill_bytes(&mut buf[..]);
+ LittleEndian::read_u32(&buf[..])
+ }
+
+ &mut TestRngImpl::Recorder {
+ ref mut rng,
+ ref mut record,
+ } => {
+ let read = rng.next_u32();
+ record.extend_from_slice(&read.to_le_bytes());
+ read
+ }
+ }
+ }
+
+ fn next_u64(&mut self) -> u64 {
+ match &mut self.rng {
+ &mut TestRngImpl::XorShift(ref mut rng) => rng.next_u64(),
+
+ &mut TestRngImpl::ChaCha(ref mut rng) => rng.next_u64(),
+
+ &mut TestRngImpl::PassThrough { .. } => {
+ let mut buf = [0; 8];
+ self.fill_bytes(&mut buf[..]);
+ LittleEndian::read_u64(&buf[..])
+ }
+
+ &mut TestRngImpl::Recorder {
+ ref mut rng,
+ ref mut record,
+ } => {
+ let read = rng.next_u64();
+ record.extend_from_slice(&read.to_le_bytes());
+ read
+ }
+ }
+ }
+
+ fn fill_bytes(&mut self, dest: &mut [u8]) {
+ match &mut self.rng {
+ &mut TestRngImpl::XorShift(ref mut rng) => rng.fill_bytes(dest),
+
+ &mut TestRngImpl::ChaCha(ref mut rng) => rng.fill_bytes(dest),
+
+ &mut TestRngImpl::PassThrough {
+ ref mut off,
+ end,
+ ref data,
+ } => {
+ let bytes_to_copy = dest.len().min(end - *off);
+ dest[..bytes_to_copy]
+ .copy_from_slice(&data[*off..*off + bytes_to_copy]);
+ *off += bytes_to_copy;
+ for i in bytes_to_copy..dest.len() {
+ dest[i] = 0;
+ }
+ }
+
+ &mut TestRngImpl::Recorder {
+ ref mut rng,
+ ref mut record,
+ } => {
+ let res = rng.fill_bytes(dest);
+ record.extend_from_slice(&dest);
+ res
+ }
+ }
+ }
+
+ fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
+ match self.rng {
+ TestRngImpl::XorShift(ref mut rng) => rng.try_fill_bytes(dest),
+
+ TestRngImpl::ChaCha(ref mut rng) => rng.try_fill_bytes(dest),
+
+ TestRngImpl::PassThrough { .. } => {
+ self.fill_bytes(dest);
+ Ok(())
+ }
+
+ TestRngImpl::Recorder {
+ ref mut rng,
+ ref mut record,
+ } => {
+ let res = rng.try_fill_bytes(dest);
+ if res.is_ok() {
+ record.extend_from_slice(&dest);
+ }
+ res
+ }
+ }
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub(crate) enum Seed {
+ XorShift([u8; 16]),
+ ChaCha([u8; 32]),
+ PassThrough(Option<(usize, usize)>, Arc<[u8]>),
+ Recorder([u8; 32]),
+}
+
+impl Seed {
+ pub(crate) fn from_bytes(algorithm: RngAlgorithm, seed: &[u8]) -> Self {
+ match algorithm {
+ RngAlgorithm::XorShift => {
+ assert_eq!(16, seed.len(), "XorShift requires a 16-byte seed");
+ let mut buf = [0; 16];
+ buf.copy_from_slice(seed);
+ Seed::XorShift(buf)
+ }
+
+ RngAlgorithm::ChaCha => {
+ assert_eq!(32, seed.len(), "ChaCha requires a 32-byte seed");
+ let mut buf = [0; 32];
+ buf.copy_from_slice(seed);
+ Seed::ChaCha(buf)
+ }
+
+ RngAlgorithm::PassThrough => Seed::PassThrough(None, seed.into()),
+
+ RngAlgorithm::Recorder => {
+ assert_eq!(32, seed.len(), "Recorder requires a 32-byte seed");
+ let mut buf = [0; 32];
+ buf.copy_from_slice(seed);
+ Seed::Recorder(buf)
+ }
+
+ RngAlgorithm::_NonExhaustive => unreachable!(),
+ }
+ }
+
+ pub(crate) fn from_persistence(string: &str) -> Option<Seed> {
+ fn from_base16(dst: &mut [u8], src: &str) -> Option<()> {
+ if dst.len() * 2 != src.len() {
+ return None;
+ }
+
+ for (dst_byte, src_pair) in
+ dst.into_iter().zip(src.as_bytes().chunks(2))
+ {
+ *dst_byte =
+ u8::from_str_radix(str::from_utf8(src_pair).ok()?, 16)
+ .ok()?;
+ }
+
+ Some(())
+ }
+
+ let parts =
+ string.trim().split(char::is_whitespace).collect::<Vec<_>>();
+ RngAlgorithm::from_persistence_key(&parts[0]).and_then(
+ |alg| match alg {
+ RngAlgorithm::XorShift => {
+ if 5 != parts.len() {
+ return None;
+ }
+
+ let mut dwords = [0u32; 4];
+ for (dword, part) in
+ (&mut dwords[..]).into_iter().zip(&parts[1..])
+ {
+ *dword = part.parse().ok()?;
+ }
+
+ let mut seed = [0u8; 16];
+ LittleEndian::write_u32_into(&dwords[..], &mut seed[..]);
+ Some(Seed::XorShift(seed))
+ }
+
+ RngAlgorithm::ChaCha => {
+ if 2 != parts.len() {
+ return None;
+ }
+
+ let mut seed = [0u8; 32];
+ from_base16(&mut seed, &parts[1])?;
+ Some(Seed::ChaCha(seed))
+ }
+
+ RngAlgorithm::PassThrough => {
+ if 1 == parts.len() {
+ return Some(Seed::PassThrough(None, vec![].into()));
+ }
+
+ if 2 != parts.len() {
+ return None;
+ }
+
+ let mut seed = vec![0u8; parts[1].len() / 2];
+ from_base16(&mut seed, &parts[1])?;
+ Some(Seed::PassThrough(None, seed.into()))
+ }
+
+ RngAlgorithm::Recorder => {
+ if 2 != parts.len() {
+ return None;
+ }
+
+ let mut seed = [0u8; 32];
+ from_base16(&mut seed, &parts[1])?;
+ Some(Seed::Recorder(seed))
+ }
+
+ RngAlgorithm::_NonExhaustive => unreachable!(),
+ },
+ )
+ }
+
+ pub(crate) fn to_persistence(&self) -> String {
+ fn to_base16(dst: &mut String, src: &[u8]) {
+ for byte in src {
+ dst.push_str(&format!("{:02x}", byte));
+ }
+ }
+
+ match *self {
+ Seed::XorShift(ref seed) => {
+ let mut dwords = [0u32; 4];
+ LittleEndian::read_u32_into(seed, &mut dwords[..]);
+ format!(
+ "{} {} {} {} {}",
+ RngAlgorithm::XorShift.persistence_key(),
+ dwords[0],
+ dwords[1],
+ dwords[2],
+ dwords[3]
+ )
+ }
+
+ Seed::ChaCha(ref seed) => {
+ let mut string =
+ RngAlgorithm::ChaCha.persistence_key().to_owned();
+ string.push(' ');
+ to_base16(&mut string, seed);
+ string
+ }
+
+ Seed::PassThrough(bounds, ref data) => {
+ let data =
+ bounds.map_or(&data[..], |(start, end)| &data[start..end]);
+ let mut string =
+ RngAlgorithm::PassThrough.persistence_key().to_owned();
+ string.push(' ');
+ to_base16(&mut string, data);
+ string
+ }
+
+ Seed::Recorder(ref seed) => {
+ let mut string =
+ RngAlgorithm::Recorder.persistence_key().to_owned();
+ string.push(' ');
+ to_base16(&mut string, seed);
+ string
+ }
+ }
+ }
+}
+
+impl TestRng {
+ /// Create a new RNG with the given algorithm and seed.
+ ///
+ /// Any RNG created with the same algorithm-seed pair will produce the same
+ /// sequence of values on all systems and all supporting versions of
+ /// proptest.
+ ///
+ /// ## Panics
+ ///
+ /// Panics if `seed` is not an appropriate length for `algorithm`.
+ pub fn from_seed(algorithm: RngAlgorithm, seed: &[u8]) -> Self {
+ TestRng::from_seed_internal(Seed::from_bytes(algorithm, seed))
+ }
+
+ /// Dumps the bytes obtained from the RNG so far (only works if the RNG is
+ /// set to `Recorder`).
+ ///
+ /// ## Panics
+ ///
+ /// Panics if this RNG does not capture generated data.
+ pub fn bytes_used(&self) -> Vec<u8> {
+ match self.rng {
+ TestRngImpl::Recorder { ref record, .. } => record.clone(),
+ _ => panic!("bytes_used() called on non-Recorder RNG"),
+ }
+ }
+
+ /// Construct a default TestRng from entropy.
+ pub(crate) fn default_rng(algorithm: RngAlgorithm) -> Self {
+ #[cfg(feature = "std")]
+ {
+ Self {
+ rng: match algorithm {
+ RngAlgorithm::XorShift => {
+ TestRngImpl::XorShift(XorShiftRng::from_entropy())
+ }
+ RngAlgorithm::ChaCha => {
+ TestRngImpl::ChaCha(ChaChaRng::from_entropy())
+ }
+ RngAlgorithm::PassThrough => {
+ panic!("cannot create default instance of PassThrough")
+ }
+ RngAlgorithm::Recorder => TestRngImpl::Recorder {
+ rng: ChaChaRng::from_entropy(),
+ record: Vec::new(),
+ },
+ RngAlgorithm::_NonExhaustive => unreachable!(),
+ },
+ }
+ }
+ #[cfg(all(
+ not(feature = "std"),
+ any(target_arch = "x86", target_arch = "x86_64"),
+ feature = "hardware-rng"
+ ))]
+ {
+ return Self::hardware_rng(algorithm);
+ }
+ #[cfg(not(feature = "std"))]
+ {
+ return Self::deterministic_rng(algorithm);
+ }
+ }
+
+ const SEED_FOR_XOR_SHIFT: [u8; 16] = [
+ 0xf4, 0x16, 0x16, 0x48, 0xc3, 0xac, 0x77, 0xac, 0x72, 0x20, 0x0b, 0xea,
+ 0x99, 0x67, 0x2d, 0x6d,
+ ];
+
+ const SEED_FOR_CHA_CHA: [u8; 32] = [
+ 0xf4, 0x16, 0x16, 0x48, 0xc3, 0xac, 0x77, 0xac, 0x72, 0x20, 0x0b, 0xea,
+ 0x99, 0x67, 0x2d, 0x6d, 0xca, 0x9f, 0x76, 0xaf, 0x1b, 0x09, 0x73, 0xa0,
+ 0x59, 0x22, 0x6d, 0xc5, 0x46, 0x39, 0x1c, 0x4a,
+ ];
+
+ /// Returns a `TestRng` with a seed generated with the
+ /// RdRand instruction on x86 machines.
+ ///
+ /// This is useful in `no_std` scenarios on x86 where we don't
+ /// have a random number infrastructure but the `rdrand` instruction is
+ /// available.
+ #[cfg(all(
+ not(feature = "std"),
+ any(target_arch = "x86", target_arch = "x86_64"),
+ feature = "hardware-rng"
+ ))]
+ pub fn hardware_rng(algorithm: RngAlgorithm) -> Self {
+ use x86::random::{rdrand_slice, RdRand};
+
+ Self::from_seed_internal(match algorithm {
+ RngAlgorithm::XorShift => {
+ // Initialize to a sane seed just in case
+ let mut seed: [u8; 16] = TestRng::SEED_FOR_XOR_SHIFT;
+ unsafe {
+ let r = rdrand_slice(&mut seed);
+ debug_assert!(r, "hardware_rng should only be called on machines with support for rdrand");
+ }
+ Seed::XorShift(seed)
+ }
+ RngAlgorithm::ChaCha => {
+ // Initialize to a sane seed just in case
+ let mut seed: [u8; 32] = TestRng::SEED_FOR_CHA_CHA;
+ unsafe {
+ let r = rdrand_slice(&mut seed);
+ debug_assert!(r, "hardware_rng should only be called on machines with support for rdrand");
+ }
+ Seed::ChaCha(seed)
+ }
+ RngAlgorithm::PassThrough => {
+ panic!("deterministic RNG not available for PassThrough")
+ }
+ RngAlgorithm::Recorder => {
+ // Initialize to a sane seed just in case
+ let mut seed: [u8; 32] = TestRng::SEED_FOR_CHA_CHA;
+ unsafe {
+ let r = rdrand_slice(&mut seed);
+ debug_assert!(r, "hardware_rng should only be called on machines with support for rdrand");
+ }
+ Seed::Recorder(seed)
+ }
+ RngAlgorithm::_NonExhaustive => unreachable!(),
+ })
+ }
+
+ /// Returns a `TestRng` with a particular hard-coded seed.
+ ///
+ /// The seed value will always be the same for a particular version of
+ /// Proptest and algorithm, but may change across releases.
+ ///
+ /// This is useful for testing things like strategy implementations without
+ /// risking getting "unlucky" RNGs which deviate from average behaviour
+ /// enough to cause spurious failures. For example, a strategy for `bool`
+ /// which is supposed to produce `true` 50% of the time might have a test
+ /// which checks that the distribution is "close enough" to 50%. If every
+ /// test run starts with a different RNG, occasionally there will be
+ /// spurious test failures when the RNG happens to produce a very skewed
+ /// distribution. Using this or `TestRunner::deterministic()` avoids such
+ /// issues.
+ pub fn deterministic_rng(algorithm: RngAlgorithm) -> Self {
+ Self::from_seed_internal(match algorithm {
+ RngAlgorithm::XorShift => {
+ Seed::XorShift(TestRng::SEED_FOR_XOR_SHIFT)
+ }
+ RngAlgorithm::ChaCha => Seed::ChaCha(TestRng::SEED_FOR_CHA_CHA),
+ RngAlgorithm::PassThrough => {
+ panic!("deterministic RNG not available for PassThrough")
+ }
+ RngAlgorithm::Recorder => Seed::Recorder(TestRng::SEED_FOR_CHA_CHA),
+ RngAlgorithm::_NonExhaustive => unreachable!(),
+ })
+ }
+
+ /// Construct a TestRng by the perturbed randomized seed
+ /// from an existing TestRng.
+ pub(crate) fn gen_rng(&mut self) -> Self {
+ Self::from_seed_internal(self.new_rng_seed())
+ }
+
+ /// Overwrite the given TestRng with the provided seed.
+ pub(crate) fn set_seed(&mut self, seed: Seed) {
+ *self = Self::from_seed_internal(seed);
+ }
+
+ /// Generate a new randomized seed, set it to this TestRng,
+ /// and return the seed.
+ pub(crate) fn gen_get_seed(&mut self) -> Seed {
+ let seed = self.new_rng_seed();
+ self.set_seed(seed.clone());
+ seed
+ }
+
+ /// Randomize a perturbed randomized seed from the given TestRng.
+ pub(crate) fn new_rng_seed(&mut self) -> Seed {
+ match self.rng {
+ TestRngImpl::XorShift(ref mut rng) => {
+ let mut seed = rng.gen::<[u8; 16]>();
+
+ // Directly using XorShiftRng::from_seed() at this point would
+ // result in rng and the returned value being exactly the same.
+ // Perturb the seed with some arbitrary values to prevent this.
+ for word in seed.chunks_mut(4) {
+ word[3] ^= 0xde;
+ word[2] ^= 0xad;
+ word[1] ^= 0xbe;
+ word[0] ^= 0xef;
+ }
+
+ Seed::XorShift(seed)
+ }
+
+ TestRngImpl::ChaCha(ref mut rng) => Seed::ChaCha(rng.gen()),
+
+ TestRngImpl::PassThrough {
+ ref mut off,
+ ref mut end,
+ ref data,
+ } => {
+ let len = *end - *off;
+ let child_start = *off + len / 2;
+ let child_end = *off + len;
+ *end = child_start;
+ Seed::PassThrough(
+ Some((child_start, child_end)),
+ Arc::clone(data),
+ )
+ }
+
+ TestRngImpl::Recorder { ref mut rng, .. } => {
+ Seed::Recorder(rng.gen())
+ }
+ }
+ }
+
+ /// Construct a TestRng from a given seed.
+ fn from_seed_internal(seed: Seed) -> Self {
+ Self {
+ rng: match seed {
+ Seed::XorShift(seed) => {
+ TestRngImpl::XorShift(XorShiftRng::from_seed(seed))
+ }
+
+ Seed::ChaCha(seed) => {
+ TestRngImpl::ChaCha(ChaChaRng::from_seed(seed))
+ }
+
+ Seed::PassThrough(bounds, data) => {
+ let (start, end) = bounds.unwrap_or((0, data.len()));
+ TestRngImpl::PassThrough {
+ off: start,
+ end,
+ data,
+ }
+ }
+
+ Seed::Recorder(seed) => TestRngImpl::Recorder {
+ rng: ChaChaRng::from_seed(seed),
+ record: Vec::new(),
+ },
+ },
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use crate::std_facade::Vec;
+
+ use rand::{Rng, RngCore};
+
+ use super::{RngAlgorithm, Seed, TestRng};
+ use crate::arbitrary::any;
+ use crate::strategy::*;
+
+ proptest! {
+ #[test]
+ fn gen_parse_seeds(
+ seed in prop_oneof![
+ any::<[u8;16]>().prop_map(Seed::XorShift),
+ any::<[u8;32]>().prop_map(Seed::ChaCha),
+ any::<Vec<u8>>().prop_map(|data| Seed::PassThrough(None, data.into())),
+ any::<[u8;32]>().prop_map(Seed::Recorder),
+ ])
+ {
+ assert_eq!(seed, Seed::from_persistence(&seed.to_persistence()).unwrap());
+ }
+
+ #[test]
+ fn rngs_dont_clone_self_on_genrng(
+ seed in prop_oneof![
+ any::<[u8;16]>().prop_map(Seed::XorShift),
+ any::<[u8;32]>().prop_map(Seed::ChaCha),
+ Just(()).prop_perturb(|_, mut rng| {
+ let mut buf = vec![0u8; 2048];
+ rng.fill_bytes(&mut buf);
+ Seed::PassThrough(None, buf.into())
+ }),
+ any::<[u8;32]>().prop_map(Seed::Recorder),
+ ])
+ {
+ type Value = [u8;32];
+ let orig = TestRng::from_seed_internal(seed);
+
+ {
+ let mut rng1 = orig.clone();
+ let mut rng2 = rng1.gen_rng();
+ assert_ne!(rng1.gen::<Value>(), rng2.gen::<Value>());
+ }
+
+ {
+ let mut rng1 = orig.clone();
+ let mut rng2 = rng1.gen_rng();
+ let mut rng3 = rng1.gen_rng();
+ let mut rng4 = rng2.gen_rng();
+ let a = rng1.gen::<Value>();
+ let b = rng2.gen::<Value>();
+ let c = rng3.gen::<Value>();
+ let d = rng4.gen::<Value>();
+ assert_ne!(a, b);
+ assert_ne!(a, c);
+ assert_ne!(a, d);
+ assert_ne!(b, c);
+ assert_ne!(b, d);
+ assert_ne!(c, d);
+ }
+ }
+ }
+
+ #[test]
+ fn passthrough_rng_behaves_properly() {
+ let mut rng = TestRng::from_seed(
+ RngAlgorithm::PassThrough,
+ &[
+ 0xDE, 0xC0, 0x12, 0x34, 0x56, 0x78, 0xFE, 0xCA, 0xEF, 0xBE,
+ 0xAD, 0xDE, 0x01, 0x02, 0x03,
+ ],
+ );
+
+ assert_eq!(0x3412C0DE, rng.next_u32());
+ assert_eq!(0xDEADBEEFCAFE7856, rng.next_u64());
+
+ let mut buf = [0u8; 4];
+ rng.try_fill_bytes(&mut buf[0..4]).unwrap();
+ assert_eq!([1, 2, 3, 0], buf);
+ rng.try_fill_bytes(&mut buf[0..4]).unwrap();
+ assert_eq!([0, 0, 0, 0], buf);
+ }
+}
diff --git a/vendor/proptest/src/test_runner/runner.rs b/vendor/proptest/src/test_runner/runner.rs
new file mode 100644
index 000000000..ce540499e
--- /dev/null
+++ b/vendor/proptest/src/test_runner/runner.rs
@@ -0,0 +1,1538 @@
+//-
+// Copyright 2017, 2018, 2019 The proptest 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.
+
+use crate::std_facade::{Arc, BTreeMap, Box, String, Vec};
+use core::sync::atomic::AtomicUsize;
+use core::sync::atomic::Ordering::SeqCst;
+use core::{fmt, iter};
+#[cfg(feature = "std")]
+use std::panic::{self, AssertUnwindSafe};
+
+#[cfg(feature = "fork")]
+use rusty_fork;
+#[cfg(feature = "fork")]
+use std::cell::{Cell, RefCell};
+#[cfg(feature = "fork")]
+use std::env;
+#[cfg(feature = "fork")]
+use std::fs;
+#[cfg(feature = "fork")]
+use tempfile;
+
+use crate::strategy::*;
+use crate::test_runner::config::*;
+use crate::test_runner::errors::*;
+use crate::test_runner::failure_persistence::PersistedSeed;
+use crate::test_runner::reason::*;
+#[cfg(feature = "fork")]
+use crate::test_runner::replay;
+use crate::test_runner::result_cache::*;
+use crate::test_runner::rng::TestRng;
+
+#[cfg(feature = "fork")]
+const ENV_FORK_FILE: &'static str = "_PROPTEST_FORKFILE";
+
+const ALWAYS: u32 = 0;
+const SHOW_FALURES: u32 = 1;
+const TRACE: u32 = 2;
+
+#[cfg(feature = "std")]
+macro_rules! verbose_message {
+ ($runner:expr, $level:expr, $fmt:tt $($arg:tt)*) => { {
+ #[allow(unused_comparisons)]
+ {
+ if $runner.config.verbose >= $level {
+ eprintln!(concat!("proptest: ", $fmt) $($arg)*);
+ }
+ };
+ ()
+ } }
+}
+
+#[cfg(not(feature = "std"))]
+macro_rules! verbose_message {
+ ($runner:expr, $level:expr, $fmt:tt $($arg:tt)*) => {
+ let _ = $level;
+ };
+}
+
+type RejectionDetail = BTreeMap<Reason, u32>;
+
+/// State used when running a proptest test.
+#[derive(Clone)]
+pub struct TestRunner {
+ config: Config,
+ successes: u32,
+ local_rejects: u32,
+ global_rejects: u32,
+ rng: TestRng,
+ flat_map_regens: Arc<AtomicUsize>,
+
+ local_reject_detail: RejectionDetail,
+ global_reject_detail: RejectionDetail,
+}
+
+impl fmt::Debug for TestRunner {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("TestRunner")
+ .field("config", &self.config)
+ .field("successes", &self.successes)
+ .field("local_rejects", &self.local_rejects)
+ .field("global_rejects", &self.global_rejects)
+ .field("rng", &"<TestRng>")
+ .field("flat_map_regens", &self.flat_map_regens)
+ .field("local_reject_detail", &self.local_reject_detail)
+ .field("global_reject_detail", &self.global_reject_detail)
+ .finish()
+ }
+}
+
+impl fmt::Display for TestRunner {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "\tsuccesses: {}\n\
+ \tlocal rejects: {}\n",
+ self.successes, self.local_rejects
+ )?;
+ for (whence, count) in &self.local_reject_detail {
+ writeln!(f, "\t\t{} times at {}", count, whence)?;
+ }
+ writeln!(f, "\tglobal rejects: {}", self.global_rejects)?;
+ for (whence, count) in &self.global_reject_detail {
+ writeln!(f, "\t\t{} times at {}", count, whence)?;
+ }
+
+ Ok(())
+ }
+}
+
+/// Equivalent to: `TestRunner::new(Config::default())`.
+impl Default for TestRunner {
+ fn default() -> Self {
+ Self::new(Config::default())
+ }
+}
+
+#[cfg(feature = "fork")]
+#[derive(Debug)]
+struct ForkOutput {
+ file: Option<fs::File>,
+}
+
+#[cfg(feature = "fork")]
+impl ForkOutput {
+ fn append(&mut self, result: &TestCaseResult) {
+ if let Some(ref mut file) = self.file {
+ replay::append(file, result)
+ .expect("Failed to append to replay file");
+ }
+ }
+
+ fn ping(&mut self) {
+ if let Some(ref mut file) = self.file {
+ replay::ping(file).expect("Failed to append to replay file");
+ }
+ }
+
+ fn terminate(&mut self) {
+ if let Some(ref mut file) = self.file {
+ replay::terminate(file).expect("Failed to append to replay file");
+ }
+ }
+
+ fn empty() -> Self {
+ ForkOutput { file: None }
+ }
+
+ fn is_in_fork(&self) -> bool {
+ self.file.is_some()
+ }
+}
+
+#[cfg(not(feature = "fork"))]
+#[derive(Debug)]
+struct ForkOutput;
+
+#[cfg(not(feature = "fork"))]
+impl ForkOutput {
+ fn append(&mut self, _result: &TestCaseResult) {}
+ fn ping(&mut self) {}
+ fn terminate(&mut self) {}
+ fn empty() -> Self {
+ ForkOutput
+ }
+ fn is_in_fork(&self) -> bool {
+ false
+ }
+}
+
+#[cfg(not(feature = "std"))]
+fn call_test<V, F, R>(
+ _runner: &mut TestRunner,
+ case: V,
+ test: &F,
+ replay_from_fork: &mut R,
+ result_cache: &mut dyn ResultCache,
+ _: &mut ForkOutput,
+ is_from_persisted_seed: bool,
+) -> TestCaseResultV2
+where
+ V: fmt::Debug,
+ F: Fn(V) -> TestCaseResult,
+ R: Iterator<Item = TestCaseResult>,
+{
+ if let Some(result) = replay_from_fork.next() {
+ return result.map(|_| TestCaseOk::ReplayFromForkSuccess);
+ }
+
+ let cache_key = result_cache.key(&ResultCacheKey::new(&case));
+ if let Some(result) = result_cache.get(cache_key) {
+ return result.clone().map(|_| TestCaseOk::CacheHitSuccess);
+ }
+
+ let result = test(case);
+ result_cache.put(cache_key, &result);
+ result.map(|_| {
+ if is_from_persisted_seed {
+ TestCaseOk::PersistedCaseSuccess
+ } else {
+ TestCaseOk::NewCaseSuccess
+ }
+ })
+}
+
+#[cfg(feature = "std")]
+fn call_test<V, F, R>(
+ runner: &mut TestRunner,
+ case: V,
+ test: &F,
+ replay_from_fork: &mut R,
+ result_cache: &mut dyn ResultCache,
+ fork_output: &mut ForkOutput,
+ is_from_persisted_seed: bool,
+) -> TestCaseResultV2
+where
+ V: fmt::Debug,
+ F: Fn(V) -> TestCaseResult,
+ R: Iterator<Item = TestCaseResult>,
+{
+ use std::time;
+
+ let timeout = runner.config.timeout();
+
+ if let Some(result) = replay_from_fork.next() {
+ return result.map(|_| TestCaseOk::ReplayFromForkSuccess);
+ }
+
+ // Now that we're about to start a new test (as far as the replay system is
+ // concerned), ping the replay file so the parent process can determine
+ // that we made it this far.
+ fork_output.ping();
+
+ verbose_message!(runner, TRACE, "Next test input: {:?}", case);
+
+ let cache_key = result_cache.key(&ResultCacheKey::new(&case));
+ if let Some(result) = result_cache.get(cache_key) {
+ verbose_message!(
+ runner,
+ TRACE,
+ "Test input hit cache, skipping execution"
+ );
+ return result.clone().map(|_| TestCaseOk::CacheHitSuccess);
+ }
+
+ let time_start = time::Instant::now();
+
+ let mut result = unwrap_or!(
+ panic::catch_unwind(AssertUnwindSafe(|| test(case))),
+ what => Err(TestCaseError::Fail(
+ what.downcast::<&'static str>().map(|s| (*s).into())
+ .or_else(|what| what.downcast::<String>().map(|b| (*b).into()))
+ .or_else(|what| what.downcast::<Box<str>>().map(|b| (*b).into()))
+ .unwrap_or_else(|_| "<unknown panic value>".into()))));
+
+ // If there is a timeout and we exceeded it, fail the test here so we get
+ // consistent behaviour. (The parent process cannot precisely time the test
+ // cases itself.)
+ if timeout > 0 && result.is_ok() {
+ let elapsed = time_start.elapsed();
+ let elapsed_millis = elapsed.as_secs() as u32 * 1000
+ + elapsed.subsec_nanos() / 1_000_000;
+
+ if elapsed_millis > timeout {
+ result = Err(TestCaseError::fail(format!(
+ "Timeout of {} ms exceeded: test took {} ms",
+ timeout, elapsed_millis
+ )));
+ }
+ }
+
+ result_cache.put(cache_key, &result);
+ fork_output.append(&result);
+
+ match result {
+ Ok(()) => verbose_message!(runner, TRACE, "Test case passed"),
+ Err(TestCaseError::Reject(ref reason)) => verbose_message!(
+ runner,
+ SHOW_FALURES,
+ "Test case rejected: {}",
+ reason
+ ),
+ Err(TestCaseError::Fail(ref reason)) => verbose_message!(
+ runner,
+ SHOW_FALURES,
+ "Test case failed: {}",
+ reason
+ ),
+ }
+
+ result.map(|_| {
+ if is_from_persisted_seed {
+ TestCaseOk::PersistedCaseSuccess
+ } else {
+ TestCaseOk::NewCaseSuccess
+ }
+ })
+}
+
+type TestRunResult<S> = Result<(), TestError<<S as Strategy>::Value>>;
+
+impl TestRunner {
+ /// Create a fresh `TestRunner` with the given configuration.
+ ///
+ /// The runner will use an RNG with a generated seed and the default
+ /// algorithm.
+ ///
+ /// In `no_std` environments, every `TestRunner` will use the same
+ /// hard-coded seed. This seed is not contractually guaranteed and may be
+ /// changed between releases without notice.
+ pub fn new(config: Config) -> Self {
+ let algorithm = config.rng_algorithm;
+ TestRunner::new_with_rng(config, TestRng::default_rng(algorithm))
+ }
+
+ /// Create a fresh `TestRunner` with the standard deterministic RNG.
+ ///
+ /// This is sugar for the following:
+ ///
+ /// ```rust
+ /// # use proptest::test_runner::*;
+ /// let config = Config::default();
+ /// let algorithm = config.rng_algorithm;
+ /// TestRunner::new_with_rng(
+ /// config,
+ /// TestRng::deterministic_rng(algorithm));
+ /// ```
+ ///
+ /// Refer to `TestRng::deterministic_rng()` for more information on the
+ /// properties of the RNG used here.
+ pub fn deterministic() -> Self {
+ let config = Config::default();
+ let algorithm = config.rng_algorithm;
+ TestRunner::new_with_rng(config, TestRng::deterministic_rng(algorithm))
+ }
+
+ /// Create a fresh `TestRunner` with the given configuration and RNG.
+ pub fn new_with_rng(config: Config, rng: TestRng) -> Self {
+ TestRunner {
+ config: config,
+ successes: 0,
+ local_rejects: 0,
+ global_rejects: 0,
+ rng: rng,
+ flat_map_regens: Arc::new(AtomicUsize::new(0)),
+ local_reject_detail: BTreeMap::new(),
+ global_reject_detail: BTreeMap::new(),
+ }
+ }
+
+ /// Create a fresh `TestRunner` with the same config and global counters as
+ /// this one, but with local state reset and an independent `Rng` (but
+ /// deterministic).
+ pub(crate) fn partial_clone(&mut self) -> Self {
+ TestRunner {
+ config: self.config.clone(),
+ successes: 0,
+ local_rejects: 0,
+ global_rejects: 0,
+ rng: self.new_rng(),
+ flat_map_regens: Arc::clone(&self.flat_map_regens),
+ local_reject_detail: BTreeMap::new(),
+ global_reject_detail: BTreeMap::new(),
+ }
+ }
+
+ /// Returns the RNG for this test run.
+ pub fn rng(&mut self) -> &mut TestRng {
+ &mut self.rng
+ }
+
+ /// Create a new, independent but deterministic RNG from the RNG in this
+ /// runner.
+ pub fn new_rng(&mut self) -> TestRng {
+ self.rng.gen_rng()
+ }
+
+ /// Returns the configuration of this runner.
+ pub fn config(&self) -> &Config {
+ &self.config
+ }
+
+ /// Dumps the bytes obtained from the RNG so far (only works if the RNG is
+ /// set to `Recorder`).
+ ///
+ /// ## Panics
+ ///
+ /// Panics if the RNG does not capture generated data.
+ pub fn bytes_used(&self) -> Vec<u8> {
+ self.rng.bytes_used()
+ }
+
+ /// Run test cases against `f`, choosing inputs via `strategy`.
+ ///
+ /// If any failure cases occur, try to find a minimal failure case and
+ /// report that. If invoking `f` panics, the panic is turned into a
+ /// `TestCaseError::Fail`.
+ ///
+ /// If failure persistence is enabled, all persisted failing cases are
+ /// tested first. If a later non-persisted case fails, its seed is
+ /// persisted before returning failure.
+ ///
+ /// Returns success or failure indicating why the test as a whole failed.
+ pub fn run<S: Strategy>(
+ &mut self,
+ strategy: &S,
+ test: impl Fn(S::Value) -> TestCaseResult,
+ ) -> TestRunResult<S> {
+ if self.config.fork() {
+ self.run_in_fork(strategy, test)
+ } else {
+ self.run_in_process(strategy, test)
+ }
+ }
+
+ #[cfg(not(feature = "fork"))]
+ fn run_in_fork<S: Strategy>(
+ &mut self,
+ _: &S,
+ _: impl Fn(S::Value) -> TestCaseResult,
+ ) -> TestRunResult<S> {
+ unreachable!()
+ }
+
+ #[cfg(feature = "fork")]
+ fn run_in_fork<S: Strategy>(
+ &mut self,
+ strategy: &S,
+ test: impl Fn(S::Value) -> TestCaseResult,
+ ) -> TestRunResult<S> {
+ let mut test = Some(test);
+
+ let test_name = rusty_fork::fork_test::fix_module_path(
+ self.config
+ .test_name
+ .expect("Must supply test_name when forking enabled"),
+ );
+ let forkfile: RefCell<Option<tempfile::NamedTempFile>> =
+ RefCell::new(None);
+ let init_forkfile_size = Cell::new(0u64);
+ let seed = self.rng.new_rng_seed();
+ let mut replay = replay::Replay {
+ seed,
+ steps: vec![],
+ };
+ let mut child_count = 0;
+ let timeout = self.config.timeout();
+
+ fn forkfile_size(forkfile: &Option<tempfile::NamedTempFile>) -> u64 {
+ forkfile.as_ref().map_or(0, |ff| {
+ ff.as_file().metadata().map(|md| md.len()).unwrap_or(0)
+ })
+ }
+
+ loop {
+ let (child_error, last_fork_file_len) = rusty_fork::fork(
+ test_name,
+ rusty_fork_id!(),
+ |cmd| {
+ let mut forkfile = forkfile.borrow_mut();
+ if forkfile.is_none() {
+ *forkfile =
+ Some(tempfile::NamedTempFile::new().expect(
+ "Failed to create temporary file for fork",
+ ));
+ replay.init_file(forkfile.as_mut().unwrap()).expect(
+ "Failed to initialise temporary file for fork",
+ );
+ }
+
+ init_forkfile_size.set(forkfile_size(&forkfile));
+
+ cmd.env(ENV_FORK_FILE, forkfile.as_ref().unwrap().path());
+ },
+ |child, _| {
+ await_child(
+ child,
+ &mut forkfile.borrow_mut().as_mut().unwrap(),
+ timeout,
+ )
+ },
+ || match self.run_in_process(strategy, test.take().unwrap()) {
+ Ok(_) => (),
+ Err(e) => panic!(
+ "Test failed normally in child process.\n{}\n{}",
+ e, self
+ ),
+ },
+ )
+ .expect("Fork failed");
+
+ let parsed = replay::Replay::parse_from(
+ &mut forkfile.borrow_mut().as_mut().unwrap(),
+ )
+ .expect("Failed to re-read fork file");
+ match parsed {
+ replay::ReplayFileStatus::InProgress(new_replay) => {
+ replay = new_replay
+ }
+ replay::ReplayFileStatus::Terminated(new_replay) => {
+ replay = new_replay;
+ break;
+ }
+ replay::ReplayFileStatus::Corrupt => {
+ panic!("Child process corrupted replay file")
+ }
+ }
+
+ let curr_forkfile_size = forkfile_size(&forkfile.borrow());
+
+ // If the child failed to append *anything* to the forkfile, it
+ // crashed or timed out before starting even one test case, so
+ // bail.
+ if curr_forkfile_size == init_forkfile_size.get() {
+ return Err(TestError::Abort(
+ "Child process crashed or timed out before the first test \
+ started running; giving up."
+ .into(),
+ ));
+ }
+
+ // The child only terminates early if it outright crashes or we
+ // kill it due to timeout, so add a synthetic failure to the
+ // output. But only do this if the length of the fork file is the
+ // same as when we last saw it, or if the child was not killed due
+ // to timeout. (This is because the child could have appended
+ // something to the file after we gave up waiting for it but before
+ // we were able to kill it).
+ if last_fork_file_len.map_or(true, |last_fork_file_len| {
+ last_fork_file_len == curr_forkfile_size
+ }) {
+ let error = Err(child_error.unwrap_or(TestCaseError::fail(
+ "Child process was terminated abruptly \
+ but with successful status",
+ )));
+ replay::append(forkfile.borrow_mut().as_mut().unwrap(), &error)
+ .expect("Failed to append to replay file");
+ replay.steps.push(error);
+ }
+
+ // Bail if we've gone through too many processes in case the
+ // shrinking process itself is crashing.
+ child_count += 1;
+ if child_count >= 10000 {
+ return Err(TestError::Abort(
+ "Giving up after 10000 child processes crashed".into(),
+ ));
+ }
+ }
+
+ // Run through the steps in-process (without ever running the actual
+ // tests) to produce the shrunken value and update the persistence
+ // file.
+ self.rng.set_seed(replay.seed);
+ self.run_in_process_with_replay(
+ strategy,
+ |_| panic!("Ran past the end of the replay"),
+ replay.steps.into_iter(),
+ ForkOutput::empty(),
+ )
+ }
+
+ fn run_in_process<S: Strategy>(
+ &mut self,
+ strategy: &S,
+ test: impl Fn(S::Value) -> TestCaseResult,
+ ) -> TestRunResult<S> {
+ let (replay_steps, fork_output) = init_replay(&mut self.rng);
+ self.run_in_process_with_replay(
+ strategy,
+ test,
+ replay_steps.into_iter(),
+ fork_output,
+ )
+ }
+
+ fn run_in_process_with_replay<S: Strategy>(
+ &mut self,
+ strategy: &S,
+ test: impl Fn(S::Value) -> TestCaseResult,
+ mut replay_from_fork: impl Iterator<Item = TestCaseResult>,
+ mut fork_output: ForkOutput,
+ ) -> TestRunResult<S> {
+ let old_rng = self.rng.clone();
+
+ let persisted_failure_seeds: Vec<PersistedSeed> = self
+ .config
+ .failure_persistence
+ .as_ref()
+ .map(|f| f.load_persisted_failures2(self.config.source_file))
+ .unwrap_or_default();
+
+ let mut result_cache = self.new_cache();
+
+ for PersistedSeed(persisted_seed) in persisted_failure_seeds {
+ self.rng.set_seed(persisted_seed);
+ self.gen_and_run_case(
+ strategy,
+ &test,
+ &mut replay_from_fork,
+ &mut *result_cache,
+ &mut fork_output,
+ true,
+ )?;
+ }
+ self.rng = old_rng;
+
+ while self.successes < self.config.cases {
+ // Generate a new seed and make an RNG from that so that we know
+ // what seed to persist if this case fails.
+ let seed = self.rng.gen_get_seed();
+ let result = self.gen_and_run_case(
+ strategy,
+ &test,
+ &mut replay_from_fork,
+ &mut *result_cache,
+ &mut fork_output,
+ false,
+ );
+ if let Err(TestError::Fail(_, ref value)) = result {
+ if let Some(ref mut failure_persistence) =
+ self.config.failure_persistence
+ {
+ let source_file = &self.config.source_file;
+
+ // Don't update the persistence file if we're a child
+ // process. The parent relies on it remaining consistent
+ // and will take care of updating it itself.
+ if !fork_output.is_in_fork() {
+ failure_persistence.save_persisted_failure2(
+ *source_file,
+ PersistedSeed(seed),
+ value,
+ );
+ }
+ }
+ }
+
+ if let Err(e) = result {
+ fork_output.terminate();
+ return Err(e.into());
+ }
+ }
+
+ fork_output.terminate();
+ Ok(())
+ }
+
+ fn gen_and_run_case<S: Strategy>(
+ &mut self,
+ strategy: &S,
+ f: &impl Fn(S::Value) -> TestCaseResult,
+ replay_from_fork: &mut impl Iterator<Item = TestCaseResult>,
+ result_cache: &mut dyn ResultCache,
+ fork_output: &mut ForkOutput,
+ is_from_persisted_seed: bool,
+ ) -> TestRunResult<S> {
+ let case = unwrap_or!(strategy.new_tree(self), msg =>
+ return Err(TestError::Abort(msg)));
+
+ // We only count new cases to our set of successful runs against
+ // `PROPTEST_CASES` config.
+ let ok_type = self.run_one_with_replay(
+ case,
+ f,
+ replay_from_fork,
+ result_cache,
+ fork_output,
+ is_from_persisted_seed,
+ )?;
+ match ok_type {
+ TestCaseOk::NewCaseSuccess | TestCaseOk::ReplayFromForkSuccess => {
+ self.successes += 1
+ }
+ TestCaseOk::PersistedCaseSuccess
+ | TestCaseOk::CacheHitSuccess
+ | TestCaseOk::Reject => (),
+ }
+
+ Ok(())
+ }
+
+ /// Run one specific test case against this runner.
+ ///
+ /// If the test fails, finds the minimal failing test case. If the test
+ /// does not fail, returns whether it succeeded or was filtered out.
+ ///
+ /// This does not honour the `fork` config, and will not be able to
+ /// terminate the run if it runs for longer than `timeout`. However, if the
+ /// test function returns but took longer than `timeout`, the test case
+ /// will fail.
+ pub fn run_one<V: ValueTree>(
+ &mut self,
+ case: V,
+ test: impl Fn(V::Value) -> TestCaseResult,
+ ) -> Result<bool, TestError<V::Value>> {
+ let mut result_cache = self.new_cache();
+ self.run_one_with_replay(
+ case,
+ test,
+ &mut iter::empty::<TestCaseResult>().fuse(),
+ &mut *result_cache,
+ &mut ForkOutput::empty(),
+ false,
+ )
+ .map(|ok_type| match ok_type {
+ TestCaseOk::Reject => false,
+ _ => true,
+ })
+ }
+
+ fn run_one_with_replay<V: ValueTree>(
+ &mut self,
+ mut case: V,
+ test: impl Fn(V::Value) -> TestCaseResult,
+ replay_from_fork: &mut impl Iterator<Item = TestCaseResult>,
+ result_cache: &mut dyn ResultCache,
+ fork_output: &mut ForkOutput,
+ is_from_persisted_seed: bool,
+ ) -> Result<TestCaseOk, TestError<V::Value>> {
+ let result = call_test(
+ self,
+ case.current(),
+ &test,
+ replay_from_fork,
+ result_cache,
+ fork_output,
+ is_from_persisted_seed,
+ );
+
+ match result {
+ Ok(success_type) => Ok(success_type),
+ Err(TestCaseError::Fail(why)) => {
+ let why = self
+ .shrink(
+ &mut case,
+ test,
+ replay_from_fork,
+ result_cache,
+ fork_output,
+ is_from_persisted_seed,
+ )
+ .unwrap_or(why);
+ Err(TestError::Fail(why, case.current()))
+ }
+ Err(TestCaseError::Reject(whence)) => {
+ self.reject_global(whence)?;
+ Ok(TestCaseOk::Reject)
+ }
+ }
+ }
+
+ fn shrink<V: ValueTree>(
+ &mut self,
+ case: &mut V,
+ test: impl Fn(V::Value) -> TestCaseResult,
+ replay_from_fork: &mut impl Iterator<Item = TestCaseResult>,
+ result_cache: &mut dyn ResultCache,
+ fork_output: &mut ForkOutput,
+ is_from_persisted_seed: bool,
+ ) -> Option<Reason> {
+ #[cfg(feature = "std")]
+ use std::time;
+
+ let mut last_failure = None;
+ let mut iterations = 0;
+ #[cfg(feature = "std")]
+ let start_time = time::Instant::now();
+
+ if case.simplify() {
+ loop {
+ #[cfg(feature = "std")]
+ let timed_out = if self.config.max_shrink_time > 0 {
+ let elapsed = start_time.elapsed();
+ let elapsed_ms = elapsed
+ .as_secs()
+ .saturating_mul(1000)
+ .saturating_add(elapsed.subsec_millis().into());
+ if elapsed_ms > self.config.max_shrink_time as u64 {
+ Some(elapsed_ms)
+ } else {
+ None
+ }
+ } else {
+ None
+ };
+ #[cfg(not(feature = "std"))]
+ let timed_out: Option<u64> = None;
+
+ let bail = if iterations >= self.config.max_shrink_iters() {
+ #[cfg(feature = "std")]
+ const CONTROLLER: &str =
+ "the PROPTEST_MAX_SHRINK_ITERS environment \
+ variable or ProptestConfig.max_shrink_iters";
+ #[cfg(not(feature = "std"))]
+ const CONTROLLER: &str = "ProptestConfig.max_shrink_iters";
+ verbose_message!(
+ self,
+ ALWAYS,
+ "Aborting shrinking after {} iterations (set {} \
+ to a large(r) value to shrink more; current \
+ configuration: {} iterations)",
+ CONTROLLER,
+ self.config.max_shrink_iters(),
+ iterations
+ );
+ true
+ } else if let Some(ms) = timed_out {
+ #[cfg(feature = "std")]
+ const CONTROLLER: &str =
+ "the PROPTEST_MAX_SHRINK_TIME environment \
+ variable or ProptestConfig.max_shrink_time";
+ #[cfg(feature = "std")]
+ let current = self.config.max_shrink_time;
+ #[cfg(not(feature = "std"))]
+ const CONTROLLER: &str = "(not configurable in no_std)";
+ #[cfg(not(feature = "std"))]
+ let current = 0;
+ verbose_message!(
+ self,
+ ALWAYS,
+ "Aborting shrinking after taking too long: {} ms \
+ (set {} to a large(r) value to shrink more; current \
+ configuration: {} ms)",
+ ms,
+ CONTROLLER,
+ current
+ );
+ true
+ } else {
+ false
+ };
+
+ if bail {
+ // Move back to the most recent failing case
+ while case.complicate() {
+ fork_output.append(&Ok(()));
+ }
+ break;
+ }
+
+ iterations += 1;
+
+ let result = call_test(
+ self,
+ case.current(),
+ &test,
+ replay_from_fork,
+ result_cache,
+ fork_output,
+ is_from_persisted_seed,
+ );
+
+ match result {
+ // Rejections are effectively a pass here,
+ // since they indicate that any behaviour of
+ // the function under test is acceptable.
+ Ok(_) | Err(TestCaseError::Reject(..)) => {
+ if !case.complicate() {
+ break;
+ }
+ }
+ Err(TestCaseError::Fail(why)) => {
+ last_failure = Some(why);
+ if !case.simplify() {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ last_failure
+ }
+
+ /// Update the state to account for a local rejection from `whence`, and
+ /// return `Ok` if the caller should keep going or `Err` to abort.
+ pub fn reject_local(
+ &mut self,
+ whence: impl Into<Reason>,
+ ) -> Result<(), Reason> {
+ if self.local_rejects >= self.config.max_local_rejects {
+ Err("Too many local rejects".into())
+ } else {
+ self.local_rejects += 1;
+ Self::insert_or_increment(
+ &mut self.local_reject_detail,
+ whence.into(),
+ );
+ Ok(())
+ }
+ }
+
+ /// Update the state to account for a global rejection from `whence`, and
+ /// return `Ok` if the caller should keep going or `Err` to abort.
+ fn reject_global<T>(&mut self, whence: Reason) -> Result<(), TestError<T>> {
+ if self.global_rejects >= self.config.max_global_rejects {
+ Err(TestError::Abort("Too many global rejects".into()))
+ } else {
+ self.global_rejects += 1;
+ Self::insert_or_increment(&mut self.global_reject_detail, whence);
+ Ok(())
+ }
+ }
+
+ /// Insert 1 or increment the rejection detail at key for whence.
+ fn insert_or_increment(into: &mut RejectionDetail, whence: Reason) {
+ into.entry(whence)
+ .and_modify(|count| *count += 1)
+ .or_insert(1);
+ }
+
+ /// Increment the counter of flat map regenerations and return whether it
+ /// is still under the configured limit.
+ pub fn flat_map_regen(&self) -> bool {
+ self.flat_map_regens.fetch_add(1, SeqCst)
+ < self.config.max_flat_map_regens as usize
+ }
+
+ fn new_cache(&self) -> Box<dyn ResultCache> {
+ (self.config.result_cache)()
+ }
+}
+
+#[cfg(feature = "fork")]
+fn init_replay(rng: &mut TestRng) -> (Vec<TestCaseResult>, ForkOutput) {
+ use crate::test_runner::replay::{open_file, Replay, ReplayFileStatus::*};
+
+ if let Some(path) = env::var_os(ENV_FORK_FILE) {
+ let mut file = open_file(&path).expect("Failed to open replay file");
+ let loaded =
+ Replay::parse_from(&mut file).expect("Failed to read replay file");
+ match loaded {
+ InProgress(replay) => {
+ rng.set_seed(replay.seed);
+ (replay.steps, ForkOutput { file: Some(file) })
+ }
+
+ Terminated(_) => {
+ panic!("Replay file for child process is terminated?")
+ }
+
+ Corrupt => panic!("Replay file for child process is corrupt"),
+ }
+ } else {
+ (vec![], ForkOutput::empty())
+ }
+}
+
+#[cfg(not(feature = "fork"))]
+fn init_replay(
+ _rng: &mut TestRng,
+) -> (iter::Empty<TestCaseResult>, ForkOutput) {
+ (iter::empty(), ForkOutput::empty())
+}
+
+#[cfg(feature = "fork")]
+fn await_child_without_timeout(
+ child: &mut rusty_fork::ChildWrapper,
+) -> (Option<TestCaseError>, Option<u64>) {
+ let status = child.wait().expect("Failed to wait for child process");
+
+ if status.success() {
+ (None, None)
+ } else {
+ (
+ Some(TestCaseError::fail(format!(
+ "Child process exited with {}",
+ status
+ ))),
+ None,
+ )
+ }
+}
+
+#[cfg(all(feature = "fork", not(feature = "timeout")))]
+fn await_child(
+ child: &mut rusty_fork::ChildWrapper,
+ _: &mut tempfile::NamedTempFile,
+ _timeout: u32,
+) -> (Option<TestCaseError>, Option<u64>) {
+ await_child_without_timeout(child)
+}
+
+#[cfg(all(feature = "fork", feature = "timeout"))]
+fn await_child(
+ child: &mut rusty_fork::ChildWrapper,
+ forkfile: &mut tempfile::NamedTempFile,
+ timeout: u32,
+) -> (Option<TestCaseError>, Option<u64>) {
+ use std::time::Duration;
+
+ if 0 == timeout {
+ return await_child_without_timeout(child);
+ }
+
+ // The child can run for longer than the timeout since it may run
+ // multiple tests. Each time the timeout expires, we check whether the
+ // file has grown larger. If it has, we allow the child to keep running
+ // until the next timeout.
+ let mut last_forkfile_len = forkfile
+ .as_file()
+ .metadata()
+ .map(|md| md.len())
+ .unwrap_or(0);
+
+ loop {
+ if let Some(status) = child
+ .wait_timeout(Duration::from_millis(timeout.into()))
+ .expect("Failed to wait for child process")
+ {
+ if status.success() {
+ return (None, None);
+ } else {
+ return (
+ Some(TestCaseError::fail(format!(
+ "Child process exited with {}",
+ status
+ ))),
+ None,
+ );
+ }
+ }
+
+ let current_len = forkfile
+ .as_file()
+ .metadata()
+ .map(|md| md.len())
+ .unwrap_or(0);
+ // If we've gone a full timeout period without the file growing,
+ // fail the test and kill the child.
+ if current_len <= last_forkfile_len {
+ return (
+ Some(TestCaseError::fail(format!(
+ "Timed out waiting for child process"
+ ))),
+ Some(current_len),
+ );
+ } else {
+ last_forkfile_len = current_len;
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use std::cell::Cell;
+ use std::fs;
+
+ use super::*;
+ use crate::strategy::Strategy;
+ use crate::test_runner::{FileFailurePersistence, RngAlgorithm, TestRng};
+
+ #[test]
+ fn gives_up_after_too_many_rejections() {
+ let config = Config::default();
+ let mut runner = TestRunner::new(config.clone());
+ let runs = Cell::new(0);
+ let result = runner.run(&(0u32..), |_| {
+ runs.set(runs.get() + 1);
+ Err(TestCaseError::reject("reject"))
+ });
+ match result {
+ Err(TestError::Abort(_)) => (),
+ e => panic!("Unexpected result: {:?}", e),
+ }
+ assert_eq!(config.max_global_rejects + 1, runs.get());
+ }
+
+ #[test]
+ fn test_pass() {
+ let mut runner = TestRunner::default();
+ let result = runner.run(&(1u32..), |v| {
+ assert!(v > 0);
+ Ok(())
+ });
+ assert_eq!(Ok(()), result);
+ }
+
+ #[test]
+ fn test_fail_via_result() {
+ let mut runner = TestRunner::new(Config {
+ failure_persistence: None,
+ ..Config::default()
+ });
+ let result = runner.run(&(0u32..10u32), |v| {
+ if v < 5 {
+ Ok(())
+ } else {
+ Err(TestCaseError::fail("not less than 5"))
+ }
+ });
+
+ assert_eq!(Err(TestError::Fail("not less than 5".into(), 5)), result);
+ }
+
+ #[test]
+ fn test_fail_via_panic() {
+ let mut runner = TestRunner::new(Config {
+ failure_persistence: None,
+ ..Config::default()
+ });
+ let result = runner.run(&(0u32..10u32), |v| {
+ assert!(v < 5, "not less than 5");
+ Ok(())
+ });
+ assert_eq!(Err(TestError::Fail("not less than 5".into(), 5)), result);
+ }
+
+ #[test]
+ fn persisted_cases_do_not_count_towards_total_cases() {
+ const FILE: &'static str = "persistence-test.txt";
+ let _ = fs::remove_file(FILE);
+
+ let config = Config {
+ failure_persistence: Some(Box::new(
+ FileFailurePersistence::Direct(FILE),
+ )),
+ cases: 1,
+ ..Config::default()
+ };
+
+ let max = 10_000_000i32;
+ {
+ TestRunner::new(config.clone())
+ .run(&(0i32..max), |_v| {
+ Err(TestCaseError::Fail("persist a failure".into()))
+ })
+ .expect_err("didn't fail?");
+ }
+
+ let run_count = RefCell::new(0);
+ TestRunner::new(config.clone())
+ .run(&(0i32..max), |_v| {
+ *run_count.borrow_mut() += 1;
+ Ok(())
+ })
+ .expect("should succeed");
+
+ // Persisted ran, and a new case ran, and only new case counts
+ // against `cases: 1`.
+ assert_eq!(run_count.into_inner(), 2);
+ }
+
+ #[derive(Clone, Copy, PartialEq)]
+ struct PoorlyBehavedDebug(i32);
+ impl fmt::Debug for PoorlyBehavedDebug {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "\r\n{:?}\r\n", self.0)
+ }
+ }
+
+ #[test]
+ fn failing_cases_persisted_and_reloaded() {
+ const FILE: &'static str = "persistence-test.txt";
+ let _ = fs::remove_file(FILE);
+
+ let max = 10_000_000i32;
+ let input = (0i32..max).prop_map(PoorlyBehavedDebug);
+ let config = Config {
+ failure_persistence: Some(Box::new(
+ FileFailurePersistence::Direct(FILE),
+ )),
+ ..Config::default()
+ };
+
+ // First test with cases that fail above half max, and then below half
+ // max, to ensure we can correctly parse both lines of the persistence
+ // file.
+ let first_sub_failure = {
+ TestRunner::new(config.clone())
+ .run(&input, |v| {
+ if v.0 < max / 2 {
+ Ok(())
+ } else {
+ Err(TestCaseError::Fail("too big".into()))
+ }
+ })
+ .expect_err("didn't fail?")
+ };
+ let first_super_failure = {
+ TestRunner::new(config.clone())
+ .run(&input, |v| {
+ if v.0 >= max / 2 {
+ Ok(())
+ } else {
+ Err(TestCaseError::Fail("too small".into()))
+ }
+ })
+ .expect_err("didn't fail?")
+ };
+ let second_sub_failure = {
+ TestRunner::new(config.clone())
+ .run(&input, |v| {
+ if v.0 < max / 2 {
+ Ok(())
+ } else {
+ Err(TestCaseError::Fail("too big".into()))
+ }
+ })
+ .expect_err("didn't fail?")
+ };
+ let second_super_failure = {
+ TestRunner::new(config.clone())
+ .run(&input, |v| {
+ if v.0 >= max / 2 {
+ Ok(())
+ } else {
+ Err(TestCaseError::Fail("too small".into()))
+ }
+ })
+ .expect_err("didn't fail?")
+ };
+
+ assert_eq!(first_sub_failure, second_sub_failure);
+ assert_eq!(first_super_failure, second_super_failure);
+ }
+
+ #[test]
+ fn new_rng_makes_separate_rng() {
+ use rand::Rng;
+ let mut runner = TestRunner::default();
+ let from_1 = runner.new_rng().gen::<[u8; 16]>();
+ let from_2 = runner.rng().gen::<[u8; 16]>();
+ assert_ne!(from_1, from_2);
+ }
+
+ #[test]
+ fn record_rng_use() {
+ use rand::Rng;
+
+ // create value with recorder rng
+ let default_config = Config::default();
+ let recorder_rng = TestRng::default_rng(RngAlgorithm::Recorder);
+ let mut runner =
+ TestRunner::new_with_rng(default_config.clone(), recorder_rng);
+ let random_byte_array1 = runner.rng().gen::<[u8; 16]>();
+ let bytes_used = runner.bytes_used();
+ assert!(bytes_used.len() >= 16); // could use more bytes for some reason
+
+ // re-create value with pass-through rng
+ let passthrough_rng =
+ TestRng::from_seed(RngAlgorithm::PassThrough, &bytes_used);
+ let mut runner =
+ TestRunner::new_with_rng(default_config, passthrough_rng);
+ let random_byte_array2 = runner.rng().gen::<[u8; 16]>();
+
+ // make sure the same value was created
+ assert_eq!(random_byte_array1, random_byte_array2);
+ }
+
+ #[cfg(feature = "fork")]
+ #[test]
+ fn run_successful_test_in_fork() {
+ let mut runner = TestRunner::new(Config {
+ fork: true,
+ test_name: Some(concat!(
+ module_path!(),
+ "::run_successful_test_in_fork"
+ )),
+ ..Config::default()
+ });
+
+ assert!(runner.run(&(0u32..1000), |_| Ok(())).is_ok());
+ }
+
+ #[cfg(feature = "fork")]
+ #[test]
+ fn normal_failure_in_fork_results_in_correct_failure() {
+ let mut runner = TestRunner::new(Config {
+ fork: true,
+ test_name: Some(concat!(
+ module_path!(),
+ "::normal_failure_in_fork_results_in_correct_failure"
+ )),
+ ..Config::default()
+ });
+
+ let failure = runner
+ .run(&(0u32..1000), |v| {
+ prop_assert!(v < 500);
+ Ok(())
+ })
+ .err()
+ .unwrap();
+
+ match failure {
+ TestError::Fail(_, value) => assert_eq!(500, value),
+ failure => panic!("Unexpected failure: {:?}", failure),
+ }
+ }
+
+ #[cfg(feature = "fork")]
+ #[test]
+ fn nonsuccessful_exit_finds_correct_failure() {
+ let mut runner = TestRunner::new(Config {
+ fork: true,
+ test_name: Some(concat!(
+ module_path!(),
+ "::nonsuccessful_exit_finds_correct_failure"
+ )),
+ ..Config::default()
+ });
+
+ let failure = runner
+ .run(&(0u32..1000), |v| {
+ if v >= 500 {
+ ::std::process::exit(1);
+ }
+ Ok(())
+ })
+ .err()
+ .unwrap();
+
+ match failure {
+ TestError::Fail(_, value) => assert_eq!(500, value),
+ failure => panic!("Unexpected failure: {:?}", failure),
+ }
+ }
+
+ #[cfg(feature = "fork")]
+ #[test]
+ fn spurious_exit_finds_correct_failure() {
+ let mut runner = TestRunner::new(Config {
+ fork: true,
+ test_name: Some(concat!(
+ module_path!(),
+ "::spurious_exit_finds_correct_failure"
+ )),
+ ..Config::default()
+ });
+
+ let failure = runner
+ .run(&(0u32..1000), |v| {
+ if v >= 500 {
+ ::std::process::exit(0);
+ }
+ Ok(())
+ })
+ .err()
+ .unwrap();
+
+ match failure {
+ TestError::Fail(_, value) => assert_eq!(500, value),
+ failure => panic!("Unexpected failure: {:?}", failure),
+ }
+ }
+
+ #[cfg(feature = "timeout")]
+ #[test]
+ fn long_sleep_timeout_finds_correct_failure() {
+ let mut runner = TestRunner::new(Config {
+ fork: true,
+ timeout: 500,
+ test_name: Some(concat!(
+ module_path!(),
+ "::long_sleep_timeout_finds_correct_failure"
+ )),
+ ..Config::default()
+ });
+
+ let failure = runner
+ .run(&(0u32..1000), |v| {
+ if v >= 500 {
+ ::std::thread::sleep(::std::time::Duration::from_millis(
+ 10_000,
+ ));
+ }
+ Ok(())
+ })
+ .err()
+ .unwrap();
+
+ match failure {
+ TestError::Fail(_, value) => assert_eq!(500, value),
+ failure => panic!("Unexpected failure: {:?}", failure),
+ }
+ }
+
+ #[cfg(feature = "timeout")]
+ #[test]
+ fn mid_sleep_timeout_finds_correct_failure() {
+ let mut runner = TestRunner::new(Config {
+ fork: true,
+ timeout: 500,
+ test_name: Some(concat!(
+ module_path!(),
+ "::mid_sleep_timeout_finds_correct_failure"
+ )),
+ ..Config::default()
+ });
+
+ let failure = runner
+ .run(&(0u32..1000), |v| {
+ if v >= 500 {
+ // Sleep a little longer than the timeout. This means that
+ // sometimes the test case itself will return before the parent
+ // process has noticed the child is timing out, so it's up to
+ // the child to mark it as a failure.
+ ::std::thread::sleep(::std::time::Duration::from_millis(
+ 600,
+ ));
+ } else {
+ // Sleep a bit so that the parent and child timing don't stay
+ // in sync.
+ ::std::thread::sleep(::std::time::Duration::from_millis(
+ 100,
+ ))
+ }
+ Ok(())
+ })
+ .err()
+ .unwrap();
+
+ match failure {
+ TestError::Fail(_, value) => assert_eq!(500, value),
+ failure => panic!("Unexpected failure: {:?}", failure),
+ }
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn duplicate_tests_not_run_with_basic_result_cache() {
+ use std::cell::{Cell, RefCell};
+ use std::collections::HashSet;
+ use std::rc::Rc;
+
+ for _ in 0..256 {
+ let mut runner = TestRunner::new(Config {
+ failure_persistence: None,
+ result_cache:
+ crate::test_runner::result_cache::basic_result_cache,
+ ..Config::default()
+ });
+ let pass = Rc::new(Cell::new(true));
+ let seen = Rc::new(RefCell::new(HashSet::new()));
+ let result =
+ runner.run(&(0u32..65536u32).prop_map(|v| v % 10), |val| {
+ if !seen.borrow_mut().insert(val) {
+ println!("Value {} seen more than once", val);
+ pass.set(false);
+ }
+
+ prop_assert!(val <= 5);
+ Ok(())
+ });
+
+ assert!(pass.get());
+ if let Err(TestError::Fail(_, val)) = result {
+ assert_eq!(6, val);
+ } else {
+ panic!("Incorrect result: {:?}", result);
+ }
+ }
+ }
+}
+
+#[cfg(all(feature = "fork", feature = "timeout", test))]
+mod timeout_tests {
+ use core::u32;
+ use std::thread;
+ use std::time::Duration;
+
+ use super::*;
+
+ rusty_fork_test! {
+ #![rusty_fork(timeout_ms = 4_000)]
+
+ #[test]
+ fn max_shrink_iters_works() {
+ test_shrink_bail(Config {
+ max_shrink_iters: 5,
+ .. Config::default()
+ });
+ }
+
+ #[test]
+ fn max_shrink_time_works() {
+ test_shrink_bail(Config {
+ max_shrink_time: 1000,
+ .. Config::default()
+ });
+ }
+
+ #[test]
+ fn max_shrink_iters_works_with_forking() {
+ test_shrink_bail(Config {
+ fork: true,
+ test_name: Some(
+ concat!(module_path!(),
+ "::max_shrink_iters_works_with_forking")),
+ max_shrink_time: 1000,
+ .. Config::default()
+ });
+ }
+
+ #[test]
+ fn detects_child_failure_to_start() {
+ let mut runner = TestRunner::new(Config {
+ timeout: 100,
+ test_name: Some(
+ concat!(module_path!(),
+ "::detects_child_failure_to_start")),
+ .. Config::default()
+ });
+ let result = runner.run(&Just(()).prop_map(|()| {
+ thread::sleep(Duration::from_millis(200))
+ }), Ok);
+
+ if let Err(TestError::Abort(_)) = result {
+ // OK
+ } else {
+ panic!("Unexpected result: {:?}", result);
+ }
+ }
+ }
+
+ fn test_shrink_bail(config: Config) {
+ let mut runner = TestRunner::new(config);
+ let result = runner.run(&crate::num::u64::ANY, |v| {
+ thread::sleep(Duration::from_millis(250));
+ prop_assert!(v <= u32::MAX as u64);
+ Ok(())
+ });
+
+ if let Err(TestError::Fail(_, value)) = result {
+ // Ensure the final value was in fact a failing case.
+ assert!(value > u32::MAX as u64);
+ } else {
+ panic!("Unexpected result: {:?}", result);
+ }
+ }
+}
diff --git a/vendor/proptest/src/tuple.rs b/vendor/proptest/src/tuple.rs
new file mode 100644
index 000000000..8230f59e4
--- /dev/null
+++ b/vendor/proptest/src/tuple.rs
@@ -0,0 +1,181 @@
+//-
+// Copyright 2017 Jason Lingle
+//
+// 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.
+
+//! Support for combining strategies into tuples.
+//!
+//! There is no explicit "tuple strategy"; simply make a tuple containing the
+//! strategy and that tuple is itself a strategy.
+
+use crate::strategy::*;
+use crate::test_runner::*;
+
+/// Common `ValueTree` implementation for all tuple strategies.
+#[derive(Clone, Copy, Debug)]
+pub struct TupleValueTree<T> {
+ tree: T,
+ shrinker: u32,
+ prev_shrinker: Option<u32>,
+}
+
+impl<T> TupleValueTree<T> {
+ /// Create a new `TupleValueTree` wrapping `inner`.
+ ///
+ /// It only makes sense for `inner` to be a tuple of an arity for which the
+ /// type implements `ValueTree`.
+ pub fn new(inner: T) -> Self {
+ TupleValueTree {
+ tree: inner,
+ shrinker: 0,
+ prev_shrinker: None,
+ }
+ }
+}
+
+macro_rules! tuple {
+ ($($fld:tt : $typ:ident),*) => {
+ impl<$($typ : Strategy),*> Strategy for ($($typ,)*) {
+ type Tree = TupleValueTree<($($typ::Tree,)*)>;
+ type Value = ($($typ::Value,)*);
+
+ fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+ let values = ($(self.$fld.new_tree(runner)?,)*);
+ Ok(TupleValueTree::new(values))
+ }
+ }
+
+ impl<$($typ : ValueTree),*> ValueTree
+ for TupleValueTree<($($typ,)*)> {
+ type Value = ($($typ::Value,)*);
+
+ fn current(&self) -> Self::Value {
+ ($(self.tree.$fld.current(),)*)
+ }
+
+ fn simplify(&mut self) -> bool {
+ $(
+ if $fld == self.shrinker {
+ if self.tree.$fld.simplify() {
+ self.prev_shrinker = Some(self.shrinker);
+ return true;
+ } else {
+ self.shrinker += 1;
+ }
+ }
+ )*
+ false
+ }
+
+ fn complicate(&mut self) -> bool {
+ if let Some(shrinker) = self.prev_shrinker {$(
+ if $fld == shrinker {
+ if self.tree.$fld.complicate() {
+ self.shrinker = shrinker;
+ return true;
+ } else {
+ self.prev_shrinker = None;
+ return false;
+ }
+ }
+ )*}
+ false
+ }
+ }
+ }
+}
+
+tuple!(0: A);
+tuple!(0: A, 1: B);
+tuple!(0: A, 1: B, 2: C);
+tuple!(0: A, 1: B, 2: C, 3: D);
+tuple!(0: A, 1: B, 2: C, 3: D, 4: E);
+tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F);
+tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G);
+tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H);
+tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I);
+tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J);
+tuple!(
+ 0: A,
+ 1: B,
+ 2: C,
+ 3: D,
+ 4: E,
+ 5: F,
+ 6: G,
+ 7: H,
+ 8: I,
+ 9: J,
+ 10: K
+);
+tuple!(
+ 0: A,
+ 1: B,
+ 2: C,
+ 3: D,
+ 4: E,
+ 5: F,
+ 6: G,
+ 7: H,
+ 8: I,
+ 9: J,
+ 10: K,
+ 11: L
+);
+
+#[cfg(test)]
+mod test {
+ use crate::strategy::*;
+
+ use super::*;
+
+ #[test]
+ fn shrinks_fully_ltr() {
+ fn pass(a: (i32, i32)) -> bool {
+ a.0 * a.1 <= 9
+ }
+
+ let input = (0..32, 0..32);
+ let mut runner = TestRunner::default();
+
+ let mut cases_tested = 0;
+ for _ in 0..256 {
+ // Find a failing test case
+ let mut case = input.new_tree(&mut runner).unwrap();
+ if pass(case.current()) {
+ continue;
+ }
+
+ loop {
+ if pass(case.current()) {
+ if !case.complicate() {
+ break;
+ }
+ } else {
+ if !case.simplify() {
+ break;
+ }
+ }
+ }
+
+ let last = case.current();
+ assert!(!pass(last));
+ // Maximally shrunken
+ assert!(pass((last.0 - 1, last.1)));
+ assert!(pass((last.0, last.1 - 1)));
+
+ cases_tested += 1;
+ }
+
+ assert!(cases_tested > 32, "Didn't find enough test cases");
+ }
+
+ #[test]
+ fn test_sanity() {
+ check_strategy_sanity((0i32..100, 0i32..1000, 0i32..10000), None);
+ }
+}