proptest/
sugar.rs

1//-
2// Copyright 2017, 2019 The proptest developers
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10use crate::std_facade::fmt;
11
12/// Easily define `proptest` tests.
13///
14/// Within `proptest!`, define one or more functions without return type
15/// normally, except instead of putting `: type` after each parameter, write
16/// `in strategy`, where `strategy` is an expression evaluating to some
17/// `Strategy`.
18///
19/// Each function will be wrapped in a function which sets up a `TestRunner`,
20/// and then invokes the function body with inputs generated according to the
21/// strategies.
22///
23/// ### Example
24///
25/// ```
26/// use proptest::prelude::*;
27///
28/// proptest! {
29///   # /*
30///   #[test]
31///   # */
32///   fn test_addition(a in 0..10, b in 0..10) {
33///     prop_assert!(a + b <= 18);
34///   }
35///
36///   # /*
37///   #[test]
38///   # */
39///   fn test_string_concat(a in ".*", b in ".*") {
40///     let cat = format!("{}{}", a, b);
41///     prop_assert_eq!(a.len() + b.len(), cat.len());
42///   }
43/// }
44/// #
45/// # fn main() { test_addition(); test_string_concat(); }
46/// ```
47///
48/// You can also use the normal argument syntax `pattern: type` as in:
49///
50/// ```rust
51/// use proptest::prelude::*;
52///
53/// proptest! {
54///   # /*
55///   #[test]
56///   # */
57///   fn addition_is_commutative(a: u8, b: u8) {
58///     prop_assert_eq!(a as u16 + b as u16, b as u16 + a as u16);
59///   }
60///
61///   # /*
62///   #[test]
63///   # */
64///   fn test_string_concat(a in ".*", b: String) {
65///     let cat = format!("{}{}", a, b);
66///     prop_assert_eq!(a.len() + b.len(), cat.len());
67///   }
68/// }
69/// #
70/// # fn main() { addition_is_commutative(); test_string_concat(); }
71/// ```
72///
73/// As you can see, you can mix `pattern: type` and `pattern in expr`.
74/// Due to limitations in `macro_rules!`, `pattern: type` does not work in
75/// all circumstances. In such a case, use `(pattern): type` instead.
76///
77/// To override the default configuration, you can start the `proptest!` block
78/// with `#![proptest_config(expr)]`, where `expr` is an expression that
79/// evaluates to a `proptest::test_runner::Config` (or a reference to one).
80///
81/// ```
82/// use proptest::prelude::*;
83///
84/// proptest! {
85///   #![proptest_config(ProptestConfig {
86///     cases: 99, .. ProptestConfig::default()
87///   })]
88///   # /*
89///   #[test]
90///   # */
91///   fn test_addition(a in 0..10, b in 0..10) {
92///     prop_assert!(a + b <= 18);
93///   }
94/// }
95/// #
96/// # fn main() { test_addition(); }
97/// ```
98///
99/// ## Closure-Style Invocation
100///
101/// As of proptest 0.8.1, an alternative, "closure-style" invocation is
102/// supported. In this form, `proptest!` is a function-like macro taking a
103/// closure-esque argument. This makes it possible to run multiple tests that
104/// require some expensive setup process. Note that the "fork" and "timeout"
105/// features are _not_ supported in closure style.
106///
107/// To use a custom configuration, pass the `Config` object as a first
108/// argument.
109///
110/// ### Example
111///
112/// ```
113/// use proptest::prelude::*;
114///
115/// #[derive(Debug)]
116/// struct BigStruct { /* Lots of fields ... */ }
117///
118/// fn very_expensive_function() -> BigStruct {
119///   // Lots of code...
120///   BigStruct { /* fields */ }
121/// }
122///
123/// # /*
124/// #[test]
125/// # */
126/// fn my_test() {
127///   // We create just one `BigStruct`
128///   let big_struct = very_expensive_function();
129///
130///   // But now can run multiple tests without needing to build it every time.
131///   // Note the extra parentheses around the arguments are currently
132///   // required.
133///   proptest!(|(x in 0u32..42u32, y in 1000u32..100000u32)| {
134///     // Test stuff
135///   });
136///
137///   // `move` closures are also supported
138///   proptest!(move |(x in 0u32..42u32)| {
139///     // Test other stuff
140///   });
141///
142///   // You can pass a custom configuration as the first argument
143///   proptest!(ProptestConfig::with_cases(1000), |(x: i32)| {
144///     // Test more stuff
145///   });
146/// }
147/// #
148/// # fn main() { my_test(); }
149/// ```
150#[macro_export]
151macro_rules! proptest {
152    (#![proptest_config($config:expr)]
153     $(
154        $(#[$meta:meta])*
155       fn $test_name:ident($($parm:pat in $strategy:expr),+ $(,)?) $body:block
156    )*) => {
157        $(
158            $(#[$meta])*
159            fn $test_name() {
160                let mut config = $crate::test_runner::contextualize_config($config.clone());
161                config.test_name = Some(
162                    concat!(module_path!(), "::", stringify!($test_name)));
163                $crate::proptest_helper!(@_BODY config ($($parm in $strategy),+) [] $body);
164            }
165        )*
166    };
167    (#![proptest_config($config:expr)]
168     $(
169        $(#[$meta:meta])*
170        fn $test_name:ident($($arg:tt)+) $body:block
171    )*) => {
172        $(
173            $(#[$meta])*
174            fn $test_name() {
175                let mut config = $crate::test_runner::contextualize_config($config.clone());
176                config.test_name = Some(
177                    concat!(module_path!(), "::", stringify!($test_name)));
178                $crate::proptest_helper!(@_BODY2 config ($($arg)+) [] $body);
179            }
180        )*
181    };
182
183    ($(
184        $(#[$meta:meta])*
185        fn $test_name:ident($($parm:pat in $strategy:expr),+ $(,)?) $body:block
186    )*) => { $crate::proptest! {
187        #![proptest_config($crate::test_runner::Config::default())]
188        $($(#[$meta])*
189          fn $test_name($($parm in $strategy),+) $body)*
190    } };
191
192    ($(
193        $(#[$meta:meta])*
194        fn $test_name:ident($($arg:tt)+) $body:block
195    )*) => { $crate::proptest! {
196        #![proptest_config($crate::test_runner::Config::default())]
197        $($(#[$meta])*
198          fn $test_name($($arg)+) $body)*
199    } };
200
201    (|($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => {
202        $crate::proptest!(
203            $crate::test_runner::Config::default(),
204            |($($parm in $strategy),+)| $body)
205    };
206
207    (move |($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => {
208        $crate::proptest!(
209            $crate::test_runner::Config::default(),
210            move |($($parm in $strategy),+)| $body)
211    };
212
213    (|($($arg:tt)+)| $body:expr) => {
214        $crate::proptest!(
215            $crate::test_runner::Config::default(),
216            |($($arg)+)| $body)
217    };
218
219    (move |($($arg:tt)+)| $body:expr) => {
220        $crate::proptest!(
221            $crate::test_runner::Config::default(),
222            move |($($arg)+)| $body)
223    };
224
225    ($config:expr, |($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => { {
226        let mut config = $crate::test_runner::contextualize_config($config.__sugar_to_owned());
227        $crate::sugar::force_no_fork(&mut config);
228        $crate::proptest_helper!(@_BODY config ($($parm in $strategy),+) [] $body)
229    } };
230
231    ($config:expr, move |($($parm:pat in $strategy:expr),+ $(,)?)| $body:expr) => { {
232        let mut config = $crate::test_runner::contextualize_config($config.__sugar_to_owned());
233        $crate::sugar::force_no_fork(&mut config);
234        $crate::proptest_helper!(@_BODY config ($($parm in $strategy),+) [move] $body)
235    } };
236
237    ($config:expr, |($($arg:tt)+)| $body:expr) => { {
238        let mut config = $crate::test_runner::contextualize_config($config.__sugar_to_owned());
239        $crate::sugar::force_no_fork(&mut config);
240        $crate::proptest_helper!(@_BODY2 config ($($arg)+) [] $body);
241    } };
242
243    ($config:expr, move |($($arg:tt)+)| $body:expr) => { {
244        let mut config = $crate::test_runner::contextualize_config($config.__sugar_to_owned());
245        $crate::sugar::force_no_fork(&mut config);
246        $crate::proptest_helper!(@_BODY2 config ($($arg)+) [move] $body);
247    } };
248}
249
250/// Rejects the test input if assumptions are not met.
251///
252/// Used directly within a function defined with `proptest!` or in any function
253/// returning `Result<_, TestCaseError>`.
254///
255/// This is invoked as `prop_assume!(condition, format, args...)`. `condition`
256/// is evaluated; if it is false, `Err(TestCaseError::Reject)` is returned. The
257/// message includes the point of invocation and the format message. `format`
258/// and `args` may be omitted to simply use the condition itself as the
259/// message.
260#[macro_export]
261macro_rules! prop_assume {
262    ($expr:expr) => {
263        $crate::prop_assume!($expr, "{}", stringify!($expr))
264    };
265
266    ($expr:expr, $fmt:tt $(, $fmt_arg:expr),* $(,)?) => {
267        if !$expr {
268            return ::core::result::Result::Err(
269                $crate::test_runner::TestCaseError::reject(
270                    format!(concat!("{}:{}:{}: ", $fmt),
271                            file!(), line!(), column!()
272                            $(, $fmt_arg)*)));
273        }
274    };
275}
276
277/// Produce a strategy which picks one of the listed choices.
278///
279/// This is conceptually equivalent to calling `prop_union` on the first two
280/// elements and then chaining `.or()` onto the rest after implicitly boxing
281/// all of them. As with `Union`, values shrink across elements on the
282/// assumption that earlier ones are "simpler", so they should be listed in
283/// order of ascending complexity when possible.
284///
285/// The macro invocation has two forms. The first is to simply list the
286/// strategies separated by commas; this will cause value generation to pick
287/// from the strategies uniformly. The other form is to provide a weight in the
288/// form of a `u32` before each strategy, separated from the strategy with
289/// `=>`.
290///
291/// Note that the exact type returned by the macro varies depending on how many
292/// inputs there are. In particular, if given exactly one option, it will
293/// return it unmodified. It is not recommended to depend on the particular
294/// type produced by this macro.
295///
296/// ## Example
297///
298/// ```rust,no_run
299/// use proptest::prelude::*;
300///
301/// #[derive(Clone, Copy, Debug)]
302/// enum MyEnum {
303///   Big(u64),
304///   Medium(u32),
305///   Little(i16),
306/// }
307///
308/// # #[allow(unused_variables)]
309/// # fn main() {
310/// let my_enum_strategy = prop_oneof![
311///   prop::num::i16::ANY.prop_map(MyEnum::Little),
312///   prop::num::u32::ANY.prop_map(MyEnum::Medium),
313///   prop::num::u64::ANY.prop_map(MyEnum::Big),
314/// ];
315///
316/// let my_weighted_strategy = prop_oneof![
317///   1 => prop::num::i16::ANY.prop_map(MyEnum::Little),
318///   // Chose `Medium` twice as frequently as either `Little` or `Big`; i.e.,
319///   // around 50% of values will be `Medium`, and 25% for each of `Little`
320///   // and `Big`.
321///   2 => prop::num::u32::ANY.prop_map(MyEnum::Medium),
322///   1 => prop::num::u64::ANY.prop_map(MyEnum::Big),
323/// ];
324/// # }
325/// ```
326#[macro_export]
327macro_rules! prop_oneof {
328    ($($item:expr),+ $(,)?) => {
329        $crate::prop_oneof![
330            $(1 => $item),*
331        ]
332    };
333
334    ($_weight0:expr => $item0:expr $(,)?) => { $item0 };
335
336    // NOTE: The clippy::arc_with_non_send_sync lint is disabled here because
337    // the strategies passed into prop_oneof! are often not Send or Sync, such
338    // as BoxedStrategy.
339    //
340    // The double-curly-braces are not strictly required, but allow the expression
341    // to be annotated with an attribute.
342
343    ($weight0:expr => $item0:expr,
344     $weight1:expr => $item1:expr $(,)?) => {{
345        #[allow(clippy::arc_with_non_send_sync)]
346        $crate::strategy::TupleUnion::new(
347            (($weight0, $crate::std_facade::Arc::new($item0)),
348             ($weight1, $crate::std_facade::Arc::new($item1))))
349    }};
350
351    ($weight0:expr => $item0:expr,
352     $weight1:expr => $item1:expr,
353     $weight2:expr => $item2:expr $(,)?) => {{
354        #[allow(clippy::arc_with_non_send_sync)]
355        $crate::strategy::TupleUnion::new(
356            (($weight0, $crate::std_facade::Arc::new($item0)),
357             ($weight1, $crate::std_facade::Arc::new($item1)),
358             ($weight2, $crate::std_facade::Arc::new($item2))))
359    }};
360
361    ($weight0:expr => $item0:expr,
362     $weight1:expr => $item1:expr,
363     $weight2:expr => $item2:expr,
364     $weight3:expr => $item3:expr $(,)?) => {{
365        #[allow(clippy::arc_with_non_send_sync)]
366        $crate::strategy::TupleUnion::new(
367            (($weight0, $crate::std_facade::Arc::new($item0)),
368             ($weight1, $crate::std_facade::Arc::new($item1)),
369             ($weight2, $crate::std_facade::Arc::new($item2)),
370             ($weight3, $crate::std_facade::Arc::new($item3))))
371    }};
372
373    ($weight0:expr => $item0:expr,
374     $weight1:expr => $item1:expr,
375     $weight2:expr => $item2:expr,
376     $weight3:expr => $item3:expr,
377     $weight4:expr => $item4:expr $(,)?) => {{
378        #[allow(clippy::arc_with_non_send_sync)]
379        $crate::strategy::TupleUnion::new(
380            (($weight0, $crate::std_facade::Arc::new($item0)),
381             ($weight1, $crate::std_facade::Arc::new($item1)),
382             ($weight2, $crate::std_facade::Arc::new($item2)),
383             ($weight3, $crate::std_facade::Arc::new($item3)),
384             ($weight4, $crate::std_facade::Arc::new($item4))))
385    }};
386
387    ($weight0:expr => $item0:expr,
388     $weight1:expr => $item1:expr,
389     $weight2:expr => $item2:expr,
390     $weight3:expr => $item3:expr,
391     $weight4:expr => $item4:expr,
392     $weight5:expr => $item5:expr $(,)?) => {{
393        #[allow(clippy::arc_with_non_send_sync)]
394        $crate::strategy::TupleUnion::new(
395            (($weight0, $crate::std_facade::Arc::new($item0)),
396             ($weight1, $crate::std_facade::Arc::new($item1)),
397             ($weight2, $crate::std_facade::Arc::new($item2)),
398             ($weight3, $crate::std_facade::Arc::new($item3)),
399             ($weight4, $crate::std_facade::Arc::new($item4)),
400             ($weight5, $crate::std_facade::Arc::new($item5))))
401    }};
402
403    ($weight0:expr => $item0:expr,
404     $weight1:expr => $item1:expr,
405     $weight2:expr => $item2:expr,
406     $weight3:expr => $item3:expr,
407     $weight4:expr => $item4:expr,
408     $weight5:expr => $item5:expr,
409     $weight6:expr => $item6:expr $(,)?) => {{
410        #[allow(clippy::arc_with_non_send_sync)]
411        $crate::strategy::TupleUnion::new(
412            (($weight0, $crate::std_facade::Arc::new($item0)),
413             ($weight1, $crate::std_facade::Arc::new($item1)),
414             ($weight2, $crate::std_facade::Arc::new($item2)),
415             ($weight3, $crate::std_facade::Arc::new($item3)),
416             ($weight4, $crate::std_facade::Arc::new($item4)),
417             ($weight5, $crate::std_facade::Arc::new($item5)),
418             ($weight6, $crate::std_facade::Arc::new($item6))))
419    }};
420
421    ($weight0:expr => $item0:expr,
422     $weight1:expr => $item1:expr,
423     $weight2:expr => $item2:expr,
424     $weight3:expr => $item3:expr,
425     $weight4:expr => $item4:expr,
426     $weight5:expr => $item5:expr,
427     $weight6:expr => $item6:expr,
428     $weight7:expr => $item7:expr $(,)?) => {{
429        #[allow(clippy::arc_with_non_send_sync)]
430        $crate::strategy::TupleUnion::new(
431            (($weight0, $crate::std_facade::Arc::new($item0)),
432             ($weight1, $crate::std_facade::Arc::new($item1)),
433             ($weight2, $crate::std_facade::Arc::new($item2)),
434             ($weight3, $crate::std_facade::Arc::new($item3)),
435             ($weight4, $crate::std_facade::Arc::new($item4)),
436             ($weight5, $crate::std_facade::Arc::new($item5)),
437             ($weight6, $crate::std_facade::Arc::new($item6)),
438             ($weight7, $crate::std_facade::Arc::new($item7))))
439    }};
440
441    ($weight0:expr => $item0:expr,
442     $weight1:expr => $item1:expr,
443     $weight2:expr => $item2:expr,
444     $weight3:expr => $item3:expr,
445     $weight4:expr => $item4:expr,
446     $weight5:expr => $item5:expr,
447     $weight6:expr => $item6:expr,
448     $weight7:expr => $item7:expr,
449     $weight8:expr => $item8:expr $(,)?) => {{
450        #[allow(clippy::arc_with_non_send_sync)]
451        $crate::strategy::TupleUnion::new(
452            (($weight0, $crate::std_facade::Arc::new($item0)),
453             ($weight1, $crate::std_facade::Arc::new($item1)),
454             ($weight2, $crate::std_facade::Arc::new($item2)),
455             ($weight3, $crate::std_facade::Arc::new($item3)),
456             ($weight4, $crate::std_facade::Arc::new($item4)),
457             ($weight5, $crate::std_facade::Arc::new($item5)),
458             ($weight6, $crate::std_facade::Arc::new($item6)),
459             ($weight7, $crate::std_facade::Arc::new($item7)),
460             ($weight8, $crate::std_facade::Arc::new($item8))))
461    }};
462
463    ($weight0:expr => $item0:expr,
464     $weight1:expr => $item1:expr,
465     $weight2:expr => $item2:expr,
466     $weight3:expr => $item3:expr,
467     $weight4:expr => $item4:expr,
468     $weight5:expr => $item5:expr,
469     $weight6:expr => $item6:expr,
470     $weight7:expr => $item7:expr,
471     $weight8:expr => $item8:expr,
472     $weight9:expr => $item9:expr $(,)?) => {{
473        #[allow(clippy::arc_with_non_send_sync)]
474        $crate::strategy::TupleUnion::new(
475            (($weight0, $crate::std_facade::Arc::new($item0)),
476             ($weight1, $crate::std_facade::Arc::new($item1)),
477             ($weight2, $crate::std_facade::Arc::new($item2)),
478             ($weight3, $crate::std_facade::Arc::new($item3)),
479             ($weight4, $crate::std_facade::Arc::new($item4)),
480             ($weight5, $crate::std_facade::Arc::new($item5)),
481             ($weight6, $crate::std_facade::Arc::new($item6)),
482             ($weight7, $crate::std_facade::Arc::new($item7)),
483             ($weight8, $crate::std_facade::Arc::new($item8)),
484             ($weight9, $crate::std_facade::Arc::new($item9))))
485    }};
486
487    ($($weight:expr => $item:expr),+ $(,)?) => {
488        $crate::strategy::Union::new_weighted(vec![
489            $(($weight, $crate::strategy::Strategy::boxed($item))),*
490        ])
491    };
492}
493
494/// Convenience to define functions which produce new strategies.
495///
496/// The macro has two general forms. In the first, you define a function with
497/// two argument lists. The first argument list uses the usual syntax and
498/// becomes exactly the argument list of the defined function. The second
499/// argument list uses the `in strategy` syntax as with `proptest!`, and is
500/// used to generate the other inputs for the function. The second argument
501/// list has access to all arguments in the first. The return type indicates
502/// the type of value being generated; the final return type of the function is
503/// `impl Strategy<Value = $type>`.
504///
505/// ```rust,no_run
506/// # #![allow(dead_code)]
507/// use proptest::prelude::*;
508///
509/// #[derive(Clone, Debug)]
510/// struct MyStruct {
511///   integer: u32,
512///   string: String,
513/// }
514///
515/// prop_compose! {
516///   fn my_struct_strategy(max_integer: u32)
517///                        (integer in 0..max_integer, string in ".*")
518///                        -> MyStruct {
519///     MyStruct { integer, string }
520///   }
521/// }
522/// #
523/// # fn main() { }
524/// ```
525///
526/// This form is simply sugar around making a tuple and then calling `prop_map`
527/// on it. You can also use `arg: type` as in `proptest! { .. }`:
528///
529/// ```rust,no_run
530/// # #![allow(dead_code)]
531/// # use proptest::prelude::*;
532/// #
533/// # #[derive(Clone, Debug)]
534/// # struct MyStruct {
535/// #  integer: u32,
536/// #  string: String,
537/// # }
538///
539/// prop_compose! {
540///   fn my_struct_strategy(max_integer: u32)
541///                        (integer in 0..max_integer, string: String)
542///                        -> MyStruct {
543///     MyStruct { integer, string }
544///   }
545/// }
546/// #
547/// # fn main() { }
548/// ```
549///
550/// The second form is mostly the same, except that it takes _three_ argument
551/// lists. The third argument list can see all values in both prior, which
552/// permits producing strategies based on other strategies.
553///
554/// ```rust,no_run
555/// # #![allow(dead_code)]
556/// use proptest::prelude::*;
557///
558/// prop_compose! {
559///   fn nearby_numbers()(centre in -1000..1000)
560///                    (a in centre-10..centre+10,
561///                     b in centre-10..centre+10)
562///                    -> (i32, i32) {
563///     (a, b)
564///   }
565/// }
566/// #
567/// # fn main() { }
568/// ```
569///
570/// However, the body of the function does _not_ have access to the second
571/// argument list. If the body needs access to those values, they must be
572/// passed through explicitly.
573///
574/// ```rust,no_run
575/// # #![allow(dead_code)]
576/// use proptest::prelude::*;
577///
578/// prop_compose! {
579///   fn vec_and_index
580///     (max_length: usize)
581///     (vec in prop::collection::vec(1..10, 1..max_length))
582///     (index in 0..vec.len(), vec in Just(vec))
583///     -> (Vec<i32>, usize)
584///   {
585///     (vec, index)
586///   }
587/// }
588/// # fn main() { }
589/// ```
590///
591/// The second form is sugar around making a strategy tuple, calling
592/// `prop_flat_map()`, then `prop_map()`.
593///
594/// To give the function any modifier which isn't a visibility modifier, put it
595/// in brackets before the `fn` token but after any visibility modifier.
596///
597/// ```rust,no_run
598/// # #![allow(dead_code)]
599/// use proptest::prelude::*;
600///
601/// prop_compose! {
602///   pub(crate) [unsafe] fn pointer()(v in prop::num::usize::ANY)
603///                                 -> *const () {
604///     v as *const ()
605///   }
606/// }
607/// # fn main() { }
608/// ```
609///
610/// ## Comparison with Hypothesis' `@composite`
611///
612/// `prop_compose!` makes it easy to do a lot of things you can do with
613/// [Hypothesis' `@composite`](https://hypothesis.readthedocs.io/en/latest/data.html#composite-strategies),
614/// but not everything.
615///
616/// - You can't filter via this macro. For filtering, you need to make the
617/// strategy the "normal" way and use `prop_filter()`.
618///
619/// - More than two layers of strategies or arbitrary logic between the two
620/// layers. If you need either of these, you can achieve them by calling
621/// `prop_flat_map()` by hand.
622#[macro_export]
623macro_rules! prop_compose {
624    ($(#[$meta:meta])*
625     $vis:vis
626     $([$($modi:tt)*])? fn $name:ident $params:tt
627     ($($var:pat in $strategy:expr),+ $(,)?)
628       -> $return_type:ty $body:block) =>
629    {
630        #[must_use = "strategies do nothing unless used"]
631        $(#[$meta])*
632        $vis
633        $($($modi)*)? fn $name $params
634                 -> impl $crate::strategy::Strategy<Value = $return_type> {
635            let strat = $crate::proptest_helper!(@_WRAP ($($strategy)*));
636            $crate::strategy::Strategy::prop_map(strat,
637                move |$crate::proptest_helper!(@_WRAPPAT ($($var),*))| $body)
638        }
639    };
640
641    ($(#[$meta:meta])*
642     $vis:vis
643     $([$($modi:tt)*])? fn $name:ident $params:tt
644     ($($var:pat in $strategy:expr),+ $(,)?)
645     ($($var2:pat in $strategy2:expr),+ $(,)?)
646       -> $return_type:ty $body:block) =>
647    {
648        #[must_use = "strategies do nothing unless used"]
649        $(#[$meta])*
650        $vis
651        $($($modi)*)? fn $name $params
652                 -> impl $crate::strategy::Strategy<Value = $return_type> {
653            let strat = $crate::proptest_helper!(@_WRAP ($($strategy)*));
654            let strat = $crate::strategy::Strategy::prop_flat_map(
655                strat,
656                move |$crate::proptest_helper!(@_WRAPPAT ($($var),*))|
657                $crate::proptest_helper!(@_WRAP ($($strategy2)*)));
658            $crate::strategy::Strategy::prop_map(strat,
659                move |$crate::proptest_helper!(@_WRAPPAT ($($var2),*))| $body)
660        }
661    };
662
663    ($(#[$meta:meta])*
664     $vis:vis
665     $([$($modi:tt)*])? fn $name:ident $params:tt
666     ($($arg:tt)+)
667       -> $return_type:ty $body:block) =>
668    {
669        #[must_use = "strategies do nothing unless used"]
670        $(#[$meta])*
671        $vis
672        $($($modi)*)? fn $name $params
673                 -> impl $crate::strategy::Strategy<Value = $return_type> {
674            let strat = $crate::proptest_helper!(@_EXT _STRAT ($($arg)+));
675            $crate::strategy::Strategy::prop_map(strat,
676                move |$crate::proptest_helper!(@_EXT _PAT ($($arg)+))| $body)
677        }
678    };
679
680    ($(#[$meta:meta])*
681     $vis:vis
682     $([$($modi:tt)*])? fn $name:ident $params:tt
683     ($($arg:tt)+ $(,)?)
684     ($($arg2:tt)+ $(,)?)
685       -> $return_type:ty $body:block) =>
686    {
687        #[must_use = "strategies do nothing unless used"]
688        $(#[$meta])*
689        $vis
690        $($($modi)*)? fn $name $params
691                 -> impl $crate::strategy::Strategy<Value = $return_type> {
692            let strat = $crate::proptest_helper!(@_WRAP ($($strategy)*));
693            let strat = $crate::strategy::Strategy::prop_flat_map(
694                strat,
695                move |$crate::proptest_helper!(@_EXT _PAT ($($arg)+))|
696                $crate::proptest_helper!(@_EXT _STRAT ($($arg2)*)));
697            $crate::strategy::Strategy::prop_map(strat,
698                move |$crate::proptest_helper!(@_EXT _PAT ($($arg2)*))| $body)
699        }
700    };
701}
702
703/// Similar to `assert!` from std, but returns a test failure instead of
704/// panicking if the condition fails.
705///
706/// This can be used in any function that returns a `Result<_, TestCaseError>`,
707/// including the top-level function inside `proptest!`.
708///
709/// Both panicking via `assert!` and returning a test case failure have the
710/// same effect as far as proptest is concerned; however, the Rust runtime
711/// implicitly prints every panic to stderr by default (including a backtrace
712/// if enabled), which can make test failures unnecessarily noisy. By using
713/// `prop_assert!` instead, the only output on a failing test case is the final
714/// panic including the minimal test case.
715///
716/// ## Example
717///
718/// ```
719/// use proptest::prelude::*;
720///
721/// proptest! {
722///   # /*
723///   #[test]
724///   # */
725///   fn triangle_inequality(a in 0.0f64..10.0, b in 0.0f64..10.0) {
726///     // Called with just a condition will print the condition on failure
727///     prop_assert!((a*a + b*b).sqrt() <= a + b);
728///     // You can also provide a custom failure message
729///     prop_assert!((a*a + b*b).sqrt() <= a + b,
730///                  "Triangle inequality didn't hold for ({}, {})", a, b);
731///     // If calling another function that can return failure, don't forget
732///     // the `?` to propagate the failure.
733///     assert_from_other_function(a, b)?;
734///   }
735/// }
736///
737/// // The macro can be used from another function provided it has a compatible
738/// // return type.
739/// fn assert_from_other_function(a: f64, b: f64) -> Result<(), TestCaseError> {
740///   prop_assert!((a*a + b*b).sqrt() <= a + b);
741///   Ok(())
742/// }
743/// #
744/// # fn main() { triangle_inequality(); }
745/// ```
746#[macro_export]
747macro_rules! prop_assert {
748    ($cond:expr) => {
749        $crate::prop_assert!($cond, concat!("assertion failed: ", stringify!($cond)))
750    };
751
752    ($cond:expr, $($fmt:tt)*) => {
753        if !$cond {
754            let message = format!($($fmt)*);
755            let message = format!("{} at {}:{}", message, file!(), line!());
756            return ::core::result::Result::Err(
757                $crate::test_runner::TestCaseError::fail(message));
758        }
759    };
760}
761
762/// Similar to `assert_eq!` from std, but returns a test failure instead of
763/// panicking if the condition fails.
764///
765/// See `prop_assert!` for a more in-depth discussion.
766///
767/// ## Example
768///
769/// ```
770/// use proptest::prelude::*;
771///
772/// proptest! {
773///   # /*
774///   #[test]
775///   # */
776///   fn concat_string_length(ref a in ".*", ref b in ".*") {
777///     let cat = format!("{}{}", a, b);
778///     // Use with default message
779///     prop_assert_eq!(a.len() + b.len(), cat.len());
780///     // Can also provide custom message (added after the normal
781///     // assertion message)
782///     prop_assert_eq!(a.len() + b.len(), cat.len(),
783///                     "a = {:?}, b = {:?}", a, b);
784///   }
785/// }
786/// #
787/// # fn main() { concat_string_length(); }
788/// ```
789#[macro_export]
790macro_rules! prop_assert_eq {
791    ($left:expr, $right:expr $(,) ?) => {{
792        let left = $left;
793        let right = $right;
794        $crate::prop_assert!(
795            left == right,
796            "assertion failed: `(left == right)` \
797             \n  left: `{:?}`,\n right: `{:?}`",
798            left, right);
799    }};
800
801    ($left:expr, $right:expr, $fmt:tt $($args:tt)*) => {{
802        let left = $left;
803        let right = $right;
804        $crate::prop_assert!(
805            left == right,
806            concat!(
807                "assertion failed: `(left == right)` \
808                 \n  left: `{:?}`, \n right: `{:?}`: ", $fmt),
809            left, right $($args)*);
810    }};
811}
812
813/// Similar to `assert_ne!` from std, but returns a test failure instead of
814/// panicking if the condition fails.
815///
816/// See `prop_assert!` for a more in-depth discussion.
817///
818/// ## Example
819///
820/// ```
821/// use proptest::prelude::*;
822///
823/// proptest! {
824///   # /*
825///   #[test]
826///   # */
827///   fn test_addition(a in 0i32..100i32, b in 1i32..100i32) {
828///     // Use with default message
829///     prop_assert_ne!(a, a + b);
830///     // Can also provide custom message added after the common message
831///     prop_assert_ne!(a, a + b, "a = {}, b = {}", a, b);
832///   }
833/// }
834/// #
835/// # fn main() { test_addition(); }
836/// ```
837#[macro_export]
838macro_rules! prop_assert_ne {
839    ($left:expr, $right:expr $(,) ?) => {{
840        let left = $left;
841        let right = $right;
842        $crate::prop_assert!(
843            left != right,
844            "assertion failed: `(left != right)`\
845             \n  left: `{:?}`,\n right: `{:?}`",
846            left, right);
847    }};
848
849    ($left:expr, $right:expr, $fmt:tt $($args:tt)*) => {{
850        let left = $left;
851        let right = $right;
852        $crate::prop_assert!(left != right, concat!(
853                "assertion failed: `(left != right)`\
854                 \n  left: `{:?}`,\n right: `{:?}`: ", $fmt),
855            left, right $($args)*);
856    }};
857}
858
859#[doc(hidden)]
860#[macro_export]
861macro_rules! proptest_helper {
862    (@_WRAP ($a:tt)) => { $a };
863    (@_WRAP ($a0:tt $a1:tt)) => { ($a0, $a1) };
864    (@_WRAP ($a0:tt $a1:tt $a2:tt)) => { ($a0, $a1, $a2) };
865    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt)) => { ($a0, $a1, $a2, $a3) };
866    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt)) => {
867        ($a0, $a1, $a2, $a3, $a4)
868    };
869    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt $a5:tt)) => {
870        ($a0, $a1, $a2, $a3, $a4, $a5)
871    };
872    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt $a5:tt $a6:tt)) => {
873        ($a0, $a1, $a2, $a3, $a4, $a5, $a6)
874    };
875    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt
876             $a4:tt $a5:tt $a6:tt $a7:tt)) => {
877        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7)
878    };
879    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt
880             $a5:tt $a6:tt $a7:tt $a8:tt)) => {
881        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8)
882    };
883    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt
884             $a5:tt $a6:tt $a7:tt $a8:tt $a9:tt)) => {
885        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9)
886    };
887    (@_WRAP ($a:tt $($rest:tt)*)) => {
888        ($a, $crate::proptest_helper!(@_WRAP ($($rest)*)))
889    };
890    (@_WRAPPAT ($item:pat)) => { $item };
891    (@_WRAPPAT ($a0:pat, $a1:pat)) => { ($a0, $a1) };
892    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat)) => { ($a0, $a1, $a2) };
893    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat)) => {
894        ($a0, $a1, $a2, $a3)
895    };
896    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat)) => {
897        ($a0, $a1, $a2, $a3, $a4)
898    };
899    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat, $a5:pat)) => {
900        ($a0, $a1, $a2, $a3, $a4, $a5)
901    };
902    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
903                $a4:pat, $a5:pat, $a6:pat)) => {
904        ($a0, $a1, $a2, $a3, $a4, $a5, $a6)
905    };
906    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
907                $a4:pat, $a5:pat, $a6:pat, $a7:pat)) => {
908        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7)
909    };
910    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
911                $a5:pat, $a6:pat, $a7:pat, $a8:pat)) => {
912        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8)
913    };
914    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
915                $a5:pat, $a6:pat, $a7:pat, $a8:pat, $a9:pat)) => {
916        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9)
917    };
918    (@_WRAPPAT ($a:pat, $($rest:pat),*)) => {
919        ($a, $crate::proptest_helper!(@_WRAPPAT ($($rest),*)))
920    };
921    (@_WRAPSTR ($item:pat)) => { stringify!($item) };
922    (@_WRAPSTR ($a0:pat, $a1:pat)) => { (stringify!($a0), stringify!($a1)) };
923    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat)) => {
924        (stringify!($a0), stringify!($a1), stringify!($a2))
925    };
926    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat)) => {
927        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3))
928    };
929    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat)) => {
930        (stringify!($a0), stringify!($a1), stringify!($a2),
931         stringify!($a3), stringify!($a4))
932    };
933    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat, $a5:pat)) => {
934        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
935         stringify!($a4), stringify!($a5))
936    };
937    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
938                $a4:pat, $a5:pat, $a6:pat)) => {
939        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
940         stringify!($a4), stringify!($a5), stringify!($a6))
941    };
942    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
943                $a4:pat, $a5:pat, $a6:pat, $a7:pat)) => {
944        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
945         stringify!($a4), stringify!($a5), stringify!($a6), stringify!($a7))
946    };
947    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
948                $a5:pat, $a6:pat, $a7:pat, $a8:pat)) => {
949        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
950         stringify!($a4), stringify!($a5), stringify!($a6), stringify!($a7),
951         stringify!($a8))
952    };
953    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
954                $a5:pat, $a6:pat, $a7:pat, $a8:pat, $a9:pat)) => {
955        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
956         stringify!($a4), stringify!($a5), stringify!($a6), stringify!($a7),
957         stringify!($a8), stringify!($a9))
958    };
959    (@_WRAPSTR ($a:pat, $($rest:pat),*)) => {
960        (stringify!($a), $crate::proptest_helper!(@_WRAPSTR ($($rest),*)))
961    };
962    // build a property testing block that when executed, executes the full property test.
963    (@_BODY $config:ident ($($parm:pat in $strategy:expr),+) [$($mod:tt)*] $body:expr) => {{
964        $config.source_file = Some(file!());
965        let mut runner = $crate::test_runner::TestRunner::new($config);
966        let names = $crate::proptest_helper!(@_WRAPSTR ($($parm),*));
967        match runner.run(
968            &$crate::strategy::Strategy::prop_map(
969                $crate::proptest_helper!(@_WRAP ($($strategy)*)),
970                |values| $crate::sugar::NamedArguments(names, values)),
971            $($mod)* |$crate::sugar::NamedArguments(
972                _, $crate::proptest_helper!(@_WRAPPAT ($($parm),*)))|
973            {
974                let (): () = $body;
975                Ok(())
976            })
977        {
978            Ok(()) => (),
979            Err(e) => panic!("{}\n{}", e, runner),
980        }
981    }};
982    // build a property testing block that when executed, executes the full property test.
983    (@_BODY2 $config:ident ($($arg:tt)+) [$($mod:tt)*] $body:expr) => {{
984        $config.source_file = Some(file!());
985        let mut runner = $crate::test_runner::TestRunner::new($config);
986        let names = $crate::proptest_helper!(@_EXT _STR ($($arg)*));
987        match runner.run(
988            &$crate::strategy::Strategy::prop_map(
989                $crate::proptest_helper!(@_EXT _STRAT ($($arg)*)),
990                |values| $crate::sugar::NamedArguments(names, values)),
991            $($mod)* |$crate::sugar::NamedArguments(
992                _, $crate::proptest_helper!(@_EXT _PAT ($($arg)*)))|
993            {
994                let (): () = $body;
995                Ok(())
996            })
997        {
998            Ok(()) => (),
999            Err(e) => panic!("{}\n{}", e, runner),
1000        }
1001    }};
1002
1003    // The logic below helps support `pat: type` in the proptest! macro.
1004
1005    // These matchers define the actual logic:
1006    (@_STRAT [$s:ty] [$p:pat]) => { $crate::arbitrary::any::<$s>()  };
1007    (@_PAT [$s:ty] [$p:pat]) => { $p };
1008    (@_STR [$s:ty] [$p:pat]) => { stringify!($p) };
1009    (@_STRAT in [$s:expr] [$p:pat]) => { $s };
1010    (@_PAT in [$s:expr] [$p:pat]) => { $p };
1011    (@_STR in [$s:expr] [$p:pat]) => { stringify!($p) };
1012
1013    // These matchers rewrite into the above extractors.
1014    // We have to do this because `:` can't FOLLOW(pat).
1015    // Note that this is not the full `pat` grammar...
1016    // See https://docs.rs/syn/0.14.2/syn/enum.Pat.html for that.
1017    (@_EXT $cmd:ident ($p:pat in $s:expr $(,)?)) => {
1018        $crate::proptest_helper!(@$cmd in [$s] [$p])
1019    };
1020    (@_EXT $cmd:ident (($p:pat) : $s:ty $(,)?)) => {
1021        // Users can wrap in parens as a last resort.
1022        $crate::proptest_helper!(@$cmd [$s] [$p])
1023    };
1024    (@_EXT $cmd:ident (_ : $s:ty $(,)?)) => {
1025        $crate::proptest_helper!(@$cmd [$s] [_])
1026    };
1027    (@_EXT $cmd:ident (ref mut $p:ident : $s:ty $(,)?)) => {
1028        $crate::proptest_helper!(@$cmd [$s] [ref mut $p])
1029    };
1030    (@_EXT $cmd:ident (ref $p:ident : $s:ty $(,)?)) => {
1031        $crate::proptest_helper!(@$cmd [$s] [ref $p])
1032    };
1033    (@_EXT $cmd:ident (mut $p:ident : $s:ty $(,)?)) => {
1034        $crate::proptest_helper!(@$cmd [$s] [mut $p])
1035    };
1036    (@_EXT $cmd:ident ($p:ident : $s:ty $(,)?)) => {
1037        $crate::proptest_helper!(@$cmd [$s] [$p])
1038    };
1039    (@_EXT $cmd:ident ([$($p:tt)*] : $s:ty $(,)?)) => {
1040        $crate::proptest_helper!(@$cmd [$s] [[$($p)*]])
1041    };
1042
1043    // Rewrite, Inductive case:
1044    (@_EXT $cmd:ident ($p:pat in $s:expr, $($r:tt)*)) => {
1045        ($crate::proptest_helper!(@$cmd in [$s] [$p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1046    };
1047    (@_EXT $cmd:ident (($p:pat) : $s:ty, $($r:tt)*)) => {
1048        ($crate::proptest_helper!(@$cmd [$s] [$p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1049    };
1050    (@_EXT $cmd:ident (_ : $s:ty, $($r:tt)*)) => {
1051        ($crate::proptest_helper!(@$cmd [$s] [_]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1052    };
1053    (@_EXT $cmd:ident (ref mut $p:ident : $s:ty, $($r:tt)*)) => {
1054        ($crate::proptest_helper!(@$cmd [$s] [ref mut $p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1055    };
1056    (@_EXT $cmd:ident (ref $p:ident : $s:ty, $($r:tt)*)) => {
1057        ($crate::proptest_helper!(@$cmd [$s] [ref $p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1058    };
1059    (@_EXT $cmd:ident (mut $p:ident : $s:ty, $($r:tt)*)) => {
1060        ($crate::proptest_helper!(@$cmd [$s] [mut $p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1061    };
1062    (@_EXT $cmd:ident ($p:ident : $s:ty, $($r:tt)*)) => {
1063        ($crate::proptest_helper!(@$cmd [$s] [$p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1064    };
1065    (@_EXT $cmd:ident ([$($p:tt)*] : $s:ty, $($r:tt)*)) => {
1066        ($crate::proptest_helper!(@$cmd [$s] [[$($p)*]]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1067    };
1068}
1069
1070#[doc(hidden)]
1071#[derive(Clone, Copy)]
1072pub struct NamedArguments<N, V>(#[doc(hidden)] pub N, #[doc(hidden)] pub V);
1073
1074impl<V: fmt::Debug> fmt::Debug for NamedArguments<&'static str, V> {
1075    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1076        write!(f, "{} = ", self.0)?;
1077        self.1.fmt(f)
1078    }
1079}
1080
1081macro_rules! named_arguments_tuple {
1082    ($($ix:tt $argn:ident $argv:ident)*) => {
1083        impl<'a, $($argn : Copy),*, $($argv),*> fmt::Debug
1084        for NamedArguments<($($argn,)*),&'a ($($argv,)*)>
1085        where $(NamedArguments<$argn, &'a $argv> : fmt::Debug),*,
1086              $($argv : 'a),*
1087        {
1088            #[allow(unused_assignments)]
1089            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1090                let mut first = true;
1091                $(
1092                    if !first {
1093                        write!(f, ", ")?;
1094                    }
1095                    first = false;
1096                    fmt::Debug::fmt(
1097                        &NamedArguments((self.0).$ix, &(self.1).$ix), f)?;
1098                )*
1099                Ok(())
1100            }
1101        }
1102
1103        impl<$($argn : Copy),*, $($argv),*> fmt::Debug
1104        for NamedArguments<($($argn,)*), ($($argv,)*)>
1105        where $(for<'a> NamedArguments<$argn, &'a $argv> : fmt::Debug),*
1106        {
1107            #[allow(unused_assignments)]
1108            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1109                let mut first = true;
1110                $(
1111                    if !first {
1112                        write!(f, ", ")?;
1113                    }
1114                    first = false;
1115                    fmt::Debug::fmt(
1116                        &NamedArguments((self.0).$ix, &(self.1).$ix), f)?;
1117                )*
1118                Ok(())
1119            }
1120        }
1121    }
1122}
1123
1124named_arguments_tuple!(0 AN AV);
1125named_arguments_tuple!(0 AN AV 1 BN BV);
1126named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV);
1127named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV);
1128named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV);
1129named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1130                       5 FN FV);
1131named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1132                       5 FN FV 6 GN GV);
1133named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1134                       5 FN FV 6 GN GV 7 HN HV);
1135named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1136                       5 FN FV 6 GN GV 7 HN HV 8 IN IV);
1137named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1138                       5 FN FV 6 GN GV 7 HN HV 8 IN IV 9 JN JV);
1139
1140#[cfg(feature = "std")]
1141#[doc(hidden)]
1142pub fn force_no_fork(config: &mut crate::test_runner::Config) {
1143    if config.fork() {
1144        eprintln!(
1145            "proptest: Forking/timeout not supported in closure-style \
1146             invocations; ignoring"
1147        );
1148
1149        #[cfg(feature = "fork")]
1150        {
1151            config.fork = false;
1152        }
1153        #[cfg(feature = "timeout")]
1154        {
1155            config.timeout = 0;
1156        }
1157        assert!(!config.fork());
1158    }
1159}
1160
1161#[cfg(not(feature = "std"))]
1162pub fn force_no_fork(_: &mut crate::test_runner::Config) {}
1163
1164#[cfg(test)]
1165mod test {
1166    use crate::strategy::Just;
1167
1168    prop_compose! {
1169        /// These are docs!
1170        #[allow(dead_code)]
1171        fn two_ints(relative: i32)(a in 0..relative, b in relative..)
1172                   -> (i32, i32) {
1173            (a, b)
1174        }
1175    }
1176
1177    prop_compose! {
1178        /// These are docs!
1179        #[allow(dead_code)]
1180        pub fn two_ints_pub(relative: i32)(a in 0..relative, b in relative..)
1181                           -> (i32, i32) {
1182            (a, b)
1183        }
1184    }
1185
1186    prop_compose! {
1187        /// These are docs!
1188        #[allow(dead_code, improper_ctypes_definitions)]
1189        pub [extern "C"] fn two_ints_pub_with_attrs
1190            (relative: i32)(a in 0..relative, b in relative..)
1191            -> (i32, i32)
1192        {
1193            (a, b)
1194        }
1195    }
1196
1197    prop_compose! {
1198        // The only modifier we can usefully put here is "unsafe", but we want
1199        // to keep this crate unsafe-free, even nominally. "const" may
1200        // eventually work, but is not allowed right now since the generated
1201        // code contains local variables. `extern "C"` is accepted, even though
1202        // the result is useless since the return type isn't C-compatible.
1203        #[allow(dead_code, improper_ctypes_definitions)]
1204        [extern "C"] fn with_modifier(relative: i32)(a in 0..relative) -> i32 {
1205            a
1206        }
1207    }
1208
1209    prop_compose! {
1210        #[allow(dead_code)]
1211        fn a_less_than_b()(b in 0..1000)(a in 0..b, b in Just(b))
1212                        -> (i32, i32) {
1213            (a, b)
1214        }
1215    }
1216
1217    proptest! {
1218        #[test]
1219        fn test_something(a in 0u32..42u32, b in 1u32..10u32) {
1220            prop_assume!(a != 41 || b != 9);
1221            assert!(a + b < 50);
1222        }
1223    }
1224
1225    prop_compose! {
1226        #[allow(dead_code)]
1227        fn single_closure_is_move(base: u64)(off in 0..10u64) -> u64 {
1228            base + off
1229        }
1230    }
1231
1232    prop_compose! {
1233        #[allow(dead_code)]
1234        fn double_closure_is_move
1235            (base: u64)
1236            (off1 in 0..10u64)
1237            (off2 in off1..off1+10)
1238            -> u64
1239        {
1240            base + off2
1241        }
1242    }
1243
1244    #[allow(unused_variables)]
1245    mod test_arg_counts {
1246        use crate::strategy::Just;
1247
1248        proptest! {
1249            #[test]
1250            fn test_1_arg(a in Just(0)) { }
1251            #[test]
1252            fn test_2_arg(a in Just(0), b in Just(0)) { }
1253            #[test]
1254            fn test_3_arg(a in Just(0), b in Just(0), c in Just(0)) { }
1255            #[test]
1256            fn test_4_arg(a in Just(0), b in Just(0), c in Just(0),
1257                          d in Just(0)) { }
1258            #[test]
1259            fn test_5_arg(a in Just(0), b in Just(0), c in Just(0),
1260                          d in Just(0), e in Just(0)) { }
1261            #[test]
1262            fn test_6_arg(a in Just(0), b in Just(0), c in Just(0),
1263                          d in Just(0), e in Just(0), f in Just(0)) { }
1264            #[test]
1265            fn test_7_arg(a in Just(0), b in Just(0), c in Just(0),
1266                          d in Just(0), e in Just(0), f in Just(0),
1267                          g in Just(0)) { }
1268            #[test]
1269            fn test_8_arg(a in Just(0), b in Just(0), c in Just(0),
1270                          d in Just(0), e in Just(0), f in Just(0),
1271                          g in Just(0), h in Just(0)) { }
1272            #[test]
1273            fn test_9_arg(a in Just(0), b in Just(0), c in Just(0),
1274                          d in Just(0), e in Just(0), f in Just(0),
1275                          g in Just(0), h in Just(0), i in Just(0)) { }
1276            #[test]
1277            fn test_a_arg(a in Just(0), b in Just(0), c in Just(0),
1278                          d in Just(0), e in Just(0), f in Just(0),
1279                          g in Just(0), h in Just(0), i in Just(0),
1280                          j in Just(0)) { }
1281            #[test]
1282            fn test_b_arg(a in Just(0), b in Just(0), c in Just(0),
1283                          d in Just(0), e in Just(0), f in Just(0),
1284                          g in Just(0), h in Just(0), i in Just(0),
1285                          j in Just(0), k in Just(0)) { }
1286            #[test]
1287            fn test_c_arg(a in Just(0), b in Just(0), c in Just(0),
1288                          d in Just(0), e in Just(0), f in Just(0),
1289                          g in Just(0), h in Just(0), i in Just(0),
1290                          j in Just(0), k in Just(0), l in Just(0)) { }
1291        }
1292    }
1293
1294    #[test]
1295    fn named_arguments_is_debug_for_needed_cases() {
1296        use super::NamedArguments;
1297
1298        println!("{:?}", NamedArguments("foo", &"bar"));
1299        println!("{:?}", NamedArguments(("foo",), &(1,)));
1300        println!("{:?}", NamedArguments(("foo", "bar"), &(1, 2)));
1301        println!("{:?}", NamedArguments(("a", "b", "c"), &(1, 2, 3)));
1302        println!("{:?}", NamedArguments(("a", "b", "c", "d"), &(1, 2, 3, 4)));
1303        println!(
1304            "{:?}",
1305            NamedArguments(("a", "b", "c", "d", "e"), &(1, 2, 3, 4, 5))
1306        );
1307        println!(
1308            "{:?}",
1309            NamedArguments(("a", "b", "c", "d", "e", "f"), &(1, 2, 3, 4, 5, 6))
1310        );
1311        println!(
1312            "{:?}",
1313            NamedArguments(
1314                ("a", "b", "c", "d", "e", "f", "g"),
1315                &(1, 2, 3, 4, 5, 6, 7)
1316            )
1317        );
1318        println!(
1319            "{:?}",
1320            NamedArguments(
1321                ("a", "b", "c", "d", "e", "f", "g", "h"),
1322                &(1, 2, 3, 4, 5, 6, 7, 8)
1323            )
1324        );
1325        println!(
1326            "{:?}",
1327            NamedArguments(
1328                ("a", "b", "c", "d", "e", "f", "g", "h", "i"),
1329                &(1, 2, 3, 4, 5, 6, 7, 8, 9)
1330            )
1331        );
1332        println!(
1333            "{:?}",
1334            NamedArguments(
1335                ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
1336                &(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
1337            )
1338        );
1339        println!(
1340            "{:?}",
1341            NamedArguments((("a", "b"), "c", "d"), &((1, 2), 3, 4))
1342        );
1343    }
1344
1345    #[test]
1346    fn oneof_all_counts() {
1347        use crate::strategy::{Just as J, Strategy, TupleUnion, Union};
1348
1349        fn expect_count(n: usize, s: impl Strategy<Value = i32>) {
1350            use crate::strategy::*;
1351            use crate::test_runner::*;
1352            use std::collections::HashSet;
1353
1354            let mut runner = TestRunner::default();
1355            let mut seen = HashSet::new();
1356            for _ in 0..1024 {
1357                seen.insert(s.new_tree(&mut runner).unwrap().current());
1358            }
1359
1360            assert_eq!(n, seen.len());
1361        }
1362
1363        fn assert_static<T>(v: TupleUnion<T>) -> TupleUnion<T> {
1364            v
1365        }
1366        fn assert_dynamic<T: Strategy>(v: Union<T>) -> Union<T> {
1367            v
1368        }
1369
1370        expect_count(1, prop_oneof![J(0i32)]);
1371        expect_count(2, assert_static(prop_oneof![J(0i32), J(1i32),]));
1372        expect_count(3, assert_static(prop_oneof![J(0i32), J(1i32), J(2i32),]));
1373        expect_count(
1374            4,
1375            assert_static(prop_oneof![J(0i32), J(1i32), J(2i32), J(3i32),]),
1376        );
1377        expect_count(
1378            5,
1379            assert_static(prop_oneof![
1380                J(0i32),
1381                J(1i32),
1382                J(2i32),
1383                J(3i32),
1384                J(4i32),
1385            ]),
1386        );
1387        expect_count(
1388            6,
1389            assert_static(prop_oneof![
1390                J(0i32),
1391                J(1i32),
1392                J(2i32),
1393                J(3i32),
1394                J(4i32),
1395                J(5i32),
1396            ]),
1397        );
1398        expect_count(
1399            7,
1400            assert_static(prop_oneof![
1401                J(0i32),
1402                J(1i32),
1403                J(2i32),
1404                J(3i32),
1405                J(4i32),
1406                J(5i32),
1407                J(6i32),
1408            ]),
1409        );
1410        expect_count(
1411            8,
1412            assert_static(prop_oneof![
1413                J(0i32),
1414                J(1i32),
1415                J(2i32),
1416                J(3i32),
1417                J(4i32),
1418                J(5i32),
1419                J(6i32),
1420                J(7i32),
1421            ]),
1422        );
1423        expect_count(
1424            9,
1425            assert_static(prop_oneof![
1426                J(0i32),
1427                J(1i32),
1428                J(2i32),
1429                J(3i32),
1430                J(4i32),
1431                J(5i32),
1432                J(6i32),
1433                J(7i32),
1434                J(8i32),
1435            ]),
1436        );
1437        expect_count(
1438            10,
1439            assert_static(prop_oneof![
1440                J(0i32),
1441                J(1i32),
1442                J(2i32),
1443                J(3i32),
1444                J(4i32),
1445                J(5i32),
1446                J(6i32),
1447                J(7i32),
1448                J(8i32),
1449                J(9i32),
1450            ]),
1451        );
1452        expect_count(
1453            11,
1454            assert_dynamic(prop_oneof![
1455                J(0i32),
1456                J(1i32),
1457                J(2i32),
1458                J(3i32),
1459                J(4i32),
1460                J(5i32),
1461                J(6i32),
1462                J(7i32),
1463                J(8i32),
1464                J(9i32),
1465                J(10i32),
1466            ]),
1467        );
1468    }
1469}
1470
1471#[cfg(all(test, feature = "timeout"))]
1472mod test_timeout {
1473    proptest! {
1474        #![proptest_config(crate::test_runner::Config {
1475            fork: true,
1476            .. crate::test_runner::Config::default()
1477        })]
1478
1479        // Ensure that the macro sets the test name properly. If it doesn't,
1480        // this test will fail to run correctly.
1481        #[test]
1482        fn test_name_set_correctly_for_fork(_ in 0u32..1u32) { }
1483    }
1484}
1485
1486#[cfg(test)]
1487mod another_test {
1488    use crate::sugar;
1489
1490    // Ensure that we can access the `[pub]` composed function above.
1491    #[allow(dead_code)]
1492    fn can_access_pub_compose() {
1493        let _ = sugar::test::two_ints_pub(42);
1494        let _ = sugar::test::two_ints_pub_with_attrs(42);
1495    }
1496}
1497
1498#[cfg(test)]
1499mod ownership_tests {
1500    #[cfg(feature = "std")]
1501    proptest! {
1502        #[test]
1503        fn accept_ref_arg(ref s in "[0-9]") {
1504            use crate::std_facade::String;
1505            fn assert_string(_s: &String) {}
1506            assert_string(s);
1507        }
1508
1509        #[test]
1510        fn accept_move_arg(s in "[0-9]") {
1511            use crate::std_facade::String;
1512            fn assert_string(_s: String) {}
1513            assert_string(s);
1514        }
1515    }
1516
1517    #[derive(Debug)]
1518    struct NotClone();
1519    const MK: fn() -> NotClone = NotClone;
1520
1521    proptest! {
1522        #[test]
1523        fn accept_noclone_arg(nc in MK) {
1524            let _nc2: NotClone = nc;
1525        }
1526
1527        #[test]
1528        fn accept_noclone_ref_arg(ref nc in MK) {
1529            let _nc2: &NotClone = nc;
1530        }
1531    }
1532}
1533
1534#[cfg(test)]
1535mod closure_tests {
1536    #[test]
1537    fn test_simple() {
1538        let x = 420;
1539
1540        proptest!(|(y: i32)| {
1541            assert!(x != y);
1542        });
1543
1544        proptest!(|(y in 0..100)| {
1545            println!("{}", y);
1546            assert!(x != y);
1547        });
1548
1549        proptest!(|(y: i32,)| {
1550            assert!(x != y);
1551        });
1552
1553        proptest!(|(y in 0..100,)| {
1554            println!("{}", y);
1555            assert!(x != y);
1556        });
1557    }
1558
1559    #[test]
1560    fn test_move() {
1561        let foo = Foo;
1562
1563        proptest!(move |(x in 1..100, y in 0..100)| {
1564            assert!(x + y > 0, "foo: {:?}", foo);
1565        });
1566
1567        let foo = Foo;
1568        proptest!(move |(x: (), y: ())| {
1569            assert!(x == y, "foo: {:?}", foo);
1570        });
1571
1572        #[derive(Debug)]
1573        struct Foo;
1574    }
1575
1576    #[test]
1577    #[should_panic]
1578    #[allow(unreachable_code)]
1579    fn fails_if_closure_panics() {
1580        proptest!(|(_ in 0..1)| {
1581            panic!()
1582        });
1583    }
1584
1585    #[test]
1586    fn accepts_unblocked_syntax() {
1587        proptest!(|(x in 0u32..10, y in 10u32..20)| assert!(x < y));
1588        proptest!(|(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
1589    }
1590
1591    #[test]
1592    fn accepts_custom_config() {
1593        let conf = crate::test_runner::Config::default();
1594
1595        proptest!(conf, |(x in 0u32..10, y in 10u32..20)| assert!(x < y));
1596        proptest!(&conf, |(x in 0u32..10, y in 10u32..20)| assert!(x < y));
1597        proptest!(conf, move |(x in 0u32..10, y in 10u32..20)| assert!(x < y));
1598        proptest!(conf, |(_x: u32, _y: u32)| { });
1599        proptest!(conf, move |(_x: u32, _y: u32)| { });
1600
1601        // Same as above, but with extra trailing comma
1602        proptest!(conf, |(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
1603        proptest!(&conf, |(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
1604        proptest!(conf, move |(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
1605        proptest!(conf, |(_x: u32, _y: u32,)| { });
1606        proptest!(conf, move |(_x: u32, _y: u32,)| { });
1607    }
1608}
1609
1610#[cfg(test)]
1611mod any_tests {
1612    proptest! {
1613        #[test]
1614        fn test_something
1615            (
1616                a: bool,
1617                b in 25u8..,
1618                c in 25u8..,
1619                _d: (),
1620                mut _e: (),
1621                ref _f: (),
1622                ref mut _g: (),
1623                [_, _]: [(); 2],
1624            ) {
1625            if a {} // Assert bool.
1626            assert!(b as usize + c as usize >= 50);
1627        }
1628    }
1629
1630    // Test that the macro accepts some of the inputs we expect it to:
1631    #[test]
1632    fn proptest_ext_test() {
1633        struct Y(pub u8);
1634
1635        let _ = proptest_helper!(@_EXT _STRAT( _ : u8 ));
1636        let _ = proptest_helper!(@_EXT _STRAT( x : u8 ));
1637        let _ = proptest_helper!(@_EXT _STRAT( ref x : u8 ));
1638        let _ = proptest_helper!(@_EXT _STRAT( mut x : u8 ));
1639        let _ = proptest_helper!(@_EXT _STRAT( ref mut x : u8 ));
1640        let _ = proptest_helper!(@_EXT _STRAT( [_, _] : u8 ));
1641        let _ = proptest_helper!(@_EXT _STRAT( (&mut &Y(ref x)) : u8 ));
1642        let _ = proptest_helper!(@_EXT _STRAT( x in 1..2 ));
1643
1644        let proptest_helper!(@_EXT _PAT( _ : u8 )) = 1;
1645        let proptest_helper!(@_EXT _PAT( _x : u8 )) = 1;
1646        let proptest_helper!(@_EXT _PAT( mut _x : u8 )) = 1;
1647        let proptest_helper!(@_EXT _PAT( ref _x : u8 )) = 1;
1648        let proptest_helper!(@_EXT _PAT( ref mut _x : u8 )) = 1;
1649        let proptest_helper!(@_EXT _PAT( [_, _] : u8 )) = [1, 2];
1650        let proptest_helper!(@_EXT _PAT( (&mut &Y(ref _x)) : u8 )) = &mut &Y(1);
1651        let proptest_helper!(@_EXT _PAT( _x in 1..2 )) = 1;
1652    }
1653}