diff options
Diffstat (limited to 'vendor/proptest/src/sugar.rs')
-rw-r--r-- | vendor/proptest/src/sugar.rs | 1637 |
1 files changed, 1637 insertions, 0 deletions
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; + } +} |