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 = $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 = $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 = $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 = $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 = $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 = $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    ($weight0:expr => $item0:expr,
337     $weight1:expr => $item1:expr $(,)?) => {
338        $crate::strategy::TupleUnion::new(
339            (($weight0, $crate::std_facade::Arc::new($item0)),
340             ($weight1, $crate::std_facade::Arc::new($item1))))
341    };
342
343    ($weight0:expr => $item0:expr,
344     $weight1:expr => $item1:expr,
345     $weight2:expr => $item2:expr $(,)?) => {
346        $crate::strategy::TupleUnion::new(
347            (($weight0, $crate::std_facade::Arc::new($item0)),
348             ($weight1, $crate::std_facade::Arc::new($item1)),
349             ($weight2, $crate::std_facade::Arc::new($item2))))
350    };
351
352    ($weight0:expr => $item0:expr,
353     $weight1:expr => $item1:expr,
354     $weight2:expr => $item2:expr,
355     $weight3:expr => $item3:expr $(,)?) => {
356        $crate::strategy::TupleUnion::new(
357            (($weight0, $crate::std_facade::Arc::new($item0)),
358             ($weight1, $crate::std_facade::Arc::new($item1)),
359             ($weight2, $crate::std_facade::Arc::new($item2)),
360             ($weight3, $crate::std_facade::Arc::new($item3))))
361    };
362
363    ($weight0:expr => $item0:expr,
364     $weight1:expr => $item1:expr,
365     $weight2:expr => $item2:expr,
366     $weight3:expr => $item3:expr,
367     $weight4:expr => $item4:expr $(,)?) => {
368        $crate::strategy::TupleUnion::new(
369            (($weight0, $crate::std_facade::Arc::new($item0)),
370             ($weight1, $crate::std_facade::Arc::new($item1)),
371             ($weight2, $crate::std_facade::Arc::new($item2)),
372             ($weight3, $crate::std_facade::Arc::new($item3)),
373             ($weight4, $crate::std_facade::Arc::new($item4))))
374    };
375
376    ($weight0:expr => $item0:expr,
377     $weight1:expr => $item1:expr,
378     $weight2:expr => $item2:expr,
379     $weight3:expr => $item3:expr,
380     $weight4:expr => $item4:expr,
381     $weight5:expr => $item5:expr $(,)?) => {
382        $crate::strategy::TupleUnion::new(
383            (($weight0, $crate::std_facade::Arc::new($item0)),
384             ($weight1, $crate::std_facade::Arc::new($item1)),
385             ($weight2, $crate::std_facade::Arc::new($item2)),
386             ($weight3, $crate::std_facade::Arc::new($item3)),
387             ($weight4, $crate::std_facade::Arc::new($item4)),
388             ($weight5, $crate::std_facade::Arc::new($item5))))
389    };
390
391    ($weight0:expr => $item0:expr,
392     $weight1:expr => $item1:expr,
393     $weight2:expr => $item2:expr,
394     $weight3:expr => $item3:expr,
395     $weight4:expr => $item4:expr,
396     $weight5:expr => $item5:expr,
397     $weight6:expr => $item6:expr $(,)?) => {
398        $crate::strategy::TupleUnion::new(
399            (($weight0, $crate::std_facade::Arc::new($item0)),
400             ($weight1, $crate::std_facade::Arc::new($item1)),
401             ($weight2, $crate::std_facade::Arc::new($item2)),
402             ($weight3, $crate::std_facade::Arc::new($item3)),
403             ($weight4, $crate::std_facade::Arc::new($item4)),
404             ($weight5, $crate::std_facade::Arc::new($item5)),
405             ($weight6, $crate::std_facade::Arc::new($item6))))
406    };
407
408    ($weight0:expr => $item0:expr,
409     $weight1:expr => $item1:expr,
410     $weight2:expr => $item2:expr,
411     $weight3:expr => $item3:expr,
412     $weight4:expr => $item4:expr,
413     $weight5:expr => $item5:expr,
414     $weight6:expr => $item6:expr,
415     $weight7:expr => $item7:expr $(,)?) => {
416        $crate::strategy::TupleUnion::new(
417            (($weight0, $crate::std_facade::Arc::new($item0)),
418             ($weight1, $crate::std_facade::Arc::new($item1)),
419             ($weight2, $crate::std_facade::Arc::new($item2)),
420             ($weight3, $crate::std_facade::Arc::new($item3)),
421             ($weight4, $crate::std_facade::Arc::new($item4)),
422             ($weight5, $crate::std_facade::Arc::new($item5)),
423             ($weight6, $crate::std_facade::Arc::new($item6)),
424             ($weight7, $crate::std_facade::Arc::new($item7))))
425    };
426
427    ($weight0:expr => $item0:expr,
428     $weight1:expr => $item1:expr,
429     $weight2:expr => $item2:expr,
430     $weight3:expr => $item3:expr,
431     $weight4:expr => $item4:expr,
432     $weight5:expr => $item5:expr,
433     $weight6:expr => $item6:expr,
434     $weight7:expr => $item7:expr,
435     $weight8:expr => $item8:expr $(,)?) => {
436        $crate::strategy::TupleUnion::new(
437            (($weight0, $crate::std_facade::Arc::new($item0)),
438             ($weight1, $crate::std_facade::Arc::new($item1)),
439             ($weight2, $crate::std_facade::Arc::new($item2)),
440             ($weight3, $crate::std_facade::Arc::new($item3)),
441             ($weight4, $crate::std_facade::Arc::new($item4)),
442             ($weight5, $crate::std_facade::Arc::new($item5)),
443             ($weight6, $crate::std_facade::Arc::new($item6)),
444             ($weight7, $crate::std_facade::Arc::new($item7)),
445             ($weight8, $crate::std_facade::Arc::new($item8))))
446    };
447
448    ($weight0:expr => $item0:expr,
449     $weight1:expr => $item1:expr,
450     $weight2:expr => $item2:expr,
451     $weight3:expr => $item3:expr,
452     $weight4:expr => $item4:expr,
453     $weight5:expr => $item5:expr,
454     $weight6:expr => $item6:expr,
455     $weight7:expr => $item7:expr,
456     $weight8:expr => $item8:expr,
457     $weight9:expr => $item9:expr $(,)?) => {
458        $crate::strategy::TupleUnion::new(
459            (($weight0, $crate::std_facade::Arc::new($item0)),
460             ($weight1, $crate::std_facade::Arc::new($item1)),
461             ($weight2, $crate::std_facade::Arc::new($item2)),
462             ($weight3, $crate::std_facade::Arc::new($item3)),
463             ($weight4, $crate::std_facade::Arc::new($item4)),
464             ($weight5, $crate::std_facade::Arc::new($item5)),
465             ($weight6, $crate::std_facade::Arc::new($item6)),
466             ($weight7, $crate::std_facade::Arc::new($item7)),
467             ($weight8, $crate::std_facade::Arc::new($item8)),
468             ($weight9, $crate::std_facade::Arc::new($item9))))
469    };
470
471    ($($weight:expr => $item:expr),+ $(,)?) => {
472        $crate::strategy::Union::new_weighted(vec![
473            $(($weight, $crate::strategy::Strategy::boxed($item))),*
474        ])
475    };
476}
477
478/// Convenience to define functions which produce new strategies.
479///
480/// The macro has two general forms. In the first, you define a function with
481/// two argument lists. The first argument list uses the usual syntax and
482/// becomes exactly the argument list of the defined function. The second
483/// argument list uses the `in strategy` syntax as with `proptest!`, and is
484/// used to generate the other inputs for the function. The second argument
485/// list has access to all arguments in the first. The return type indicates
486/// the type of value being generated; the final return type of the function is
487/// `impl Strategy<Value = $type>`.
488///
489/// ```rust,no_run
490/// # #![allow(dead_code)]
491/// use proptest::prelude::*;
492///
493/// #[derive(Clone, Debug)]
494/// struct MyStruct {
495///   integer: u32,
496///   string: String,
497/// }
498///
499/// prop_compose! {
500///   fn my_struct_strategy(max_integer: u32)
501///                        (integer in 0..max_integer, string in ".*")
502///                        -> MyStruct {
503///     MyStruct { integer, string }
504///   }
505/// }
506/// #
507/// # fn main() { }
508/// ```
509///
510/// This form is simply sugar around making a tuple and then calling `prop_map`
511/// on it. You can also use `arg: type` as in `proptest! { .. }`:
512///
513/// ```rust,no_run
514/// # #![allow(dead_code)]
515/// # use proptest::prelude::*;
516/// #
517/// # #[derive(Clone, Debug)]
518/// # struct MyStruct {
519/// #  integer: u32,
520/// #  string: String,
521/// # }
522///
523/// prop_compose! {
524///   fn my_struct_strategy(max_integer: u32)
525///                        (integer in 0..max_integer, string: String)
526///                        -> MyStruct {
527///     MyStruct { integer, string }
528///   }
529/// }
530/// #
531/// # fn main() { }
532/// ```
533///
534/// The second form is mostly the same, except that it takes _three_ argument
535/// lists. The third argument list can see all values in both prior, which
536/// permits producing strategies based on other strategies.
537///
538/// ```rust,no_run
539/// # #![allow(dead_code)]
540/// use proptest::prelude::*;
541///
542/// prop_compose! {
543///   fn nearby_numbers()(centre in -1000..1000)
544///                    (a in centre-10..centre+10,
545///                     b in centre-10..centre+10)
546///                    -> (i32, i32) {
547///     (a, b)
548///   }
549/// }
550/// #
551/// # fn main() { }
552/// ```
553///
554/// However, the body of the function does _not_ have access to the second
555/// argument list. If the body needs access to those values, they must be
556/// passed through explicitly.
557///
558/// ```rust,no_run
559/// # #![allow(dead_code)]
560/// use proptest::prelude::*;
561///
562/// prop_compose! {
563///   fn vec_and_index
564///     (max_length: usize)
565///     (vec in prop::collection::vec(1..10, 1..max_length))
566///     (index in 0..vec.len(), vec in Just(vec))
567///     -> (Vec<i32>, usize)
568///   {
569///     (vec, index)
570///   }
571/// }
572/// # fn main() { }
573/// ```
574///
575/// The second form is sugar around making a strategy tuple, calling
576/// `prop_flat_map()`, then `prop_map()`.
577///
578/// To give the function any modifier which isn't a visibility modifier, put it
579/// in brackets before the `fn` token but after any visibility modifier.
580///
581/// ```rust,no_run
582/// # #![allow(dead_code)]
583/// use proptest::prelude::*;
584///
585/// prop_compose! {
586///   pub(crate) [unsafe] fn pointer()(v in prop::num::usize::ANY)
587///                                 -> *const () {
588///     v as *const ()
589///   }
590/// }
591/// # fn main() { }
592/// ```
593///
594/// ## Comparison with Hypothesis' `@composite`
595///
596/// `prop_compose!` makes it easy to do a lot of things you can do with
597/// [Hypothesis' `@composite`](https://hypothesis.readthedocs.io/en/latest/data.html#composite-strategies),
598/// but not everything.
599///
600/// - You can't filter via this macro. For filtering, you need to make the
601/// strategy the "normal" way and use `prop_filter()`.
602///
603/// - More than two layers of strategies or arbitrary logic between the two
604/// layers. If you need either of these, you can achieve them by calling
605/// `prop_flat_map()` by hand.
606#[macro_export]
607macro_rules! prop_compose {
608    ($(#[$meta:meta])*
609     $vis:vis
610     $([$($modi:tt)*])? fn $name:ident $params:tt
611     ($($var:pat in $strategy:expr),+ $(,)?)
612       -> $return_type:ty $body:block) =>
613    {
614        #[must_use = "strategies do nothing unless used"]
615        $(#[$meta])*
616        $vis
617        $($($modi)*)? fn $name $params
618                 -> impl $crate::strategy::Strategy<Value = $return_type> {
619            let strat = $crate::proptest_helper!(@_WRAP ($($strategy)*));
620            $crate::strategy::Strategy::prop_map(strat,
621                move |$crate::proptest_helper!(@_WRAPPAT ($($var),*))| $body)
622        }
623    };
624
625    ($(#[$meta:meta])*
626     $vis:vis
627     $([$($modi:tt)*])? fn $name:ident $params:tt
628     ($($var:pat in $strategy:expr),+ $(,)?)
629     ($($var2:pat in $strategy2:expr),+ $(,)?)
630       -> $return_type:ty $body:block) =>
631    {
632        #[must_use = "strategies do nothing unless used"]
633        $(#[$meta])*
634        $vis
635        $($($modi)*)? fn $name $params
636                 -> impl $crate::strategy::Strategy<Value = $return_type> {
637            let strat = $crate::proptest_helper!(@_WRAP ($($strategy)*));
638            let strat = $crate::strategy::Strategy::prop_flat_map(
639                strat,
640                move |$crate::proptest_helper!(@_WRAPPAT ($($var),*))|
641                $crate::proptest_helper!(@_WRAP ($($strategy2)*)));
642            $crate::strategy::Strategy::prop_map(strat,
643                move |$crate::proptest_helper!(@_WRAPPAT ($($var2),*))| $body)
644        }
645    };
646
647    ($(#[$meta:meta])*
648     $vis:vis
649     $([$($modi:tt)*])? fn $name:ident $params:tt
650     ($($arg:tt)+)
651       -> $return_type:ty $body:block) =>
652    {
653        #[must_use = "strategies do nothing unless used"]
654        $(#[$meta])*
655        $vis
656        $($($modi)*)? fn $name $params
657                 -> impl $crate::strategy::Strategy<Value = $return_type> {
658            let strat = $crate::proptest_helper!(@_EXT _STRAT ($($arg)+));
659            $crate::strategy::Strategy::prop_map(strat,
660                move |$crate::proptest_helper!(@_EXT _PAT ($($arg)+))| $body)
661        }
662    };
663
664    ($(#[$meta:meta])*
665     $vis:vis
666     $([$($modi:tt)*])? fn $name:ident $params:tt
667     ($($arg:tt)+ $(,)?)
668     ($($arg2:tt)+ $(,)?)
669       -> $return_type:ty $body:block) =>
670    {
671        #[must_use = "strategies do nothing unless used"]
672        $(#[$meta])*
673        $vis
674        $($($modi)*)? fn $name $params
675                 -> impl $crate::strategy::Strategy<Value = $return_type> {
676            let strat = $crate::proptest_helper!(@_WRAP ($($strategy)*));
677            let strat = $crate::strategy::Strategy::prop_flat_map(
678                strat,
679                move |$crate::proptest_helper!(@_EXT _PAT ($($arg)+))|
680                $crate::proptest_helper!(@_EXT _STRAT ($($arg2)*)));
681            $crate::strategy::Strategy::prop_map(strat,
682                move |$crate::proptest_helper!(@_EXT _PAT ($($arg2)*))| $body)
683        }
684    };
685}
686
687/// Similar to `assert!` from std, but returns a test failure instead of
688/// panicking if the condition fails.
689///
690/// This can be used in any function that returns a `Result<_, TestCaseError>`,
691/// including the top-level function inside `proptest!`.
692///
693/// Both panicking via `assert!` and returning a test case failure have the
694/// same effect as far as proptest is concerned; however, the Rust runtime
695/// implicitly prints every panic to stderr by default (including a backtrace
696/// if enabled), which can make test failures unnecessarily noisy. By using
697/// `prop_assert!` instead, the only output on a failing test case is the final
698/// panic including the minimal test case.
699///
700/// ## Example
701///
702/// ```
703/// use proptest::prelude::*;
704///
705/// proptest! {
706///   # /*
707///   #[test]
708///   # */
709///   fn triangle_inequality(a in 0.0f64..10.0, b in 0.0f64..10.0) {
710///     // Called with just a condition will print the condition on failure
711///     prop_assert!((a*a + b*b).sqrt() <= a + b);
712///     // You can also provide a custom failure message
713///     prop_assert!((a*a + b*b).sqrt() <= a + b,
714///                  "Triangle inequality didn't hold for ({}, {})", a, b);
715///     // If calling another function that can return failure, don't forget
716///     // the `?` to propagate the failure.
717///     assert_from_other_function(a, b)?;
718///   }
719/// }
720///
721/// // The macro can be used from another function provided it has a compatible
722/// // return type.
723/// fn assert_from_other_function(a: f64, b: f64) -> Result<(), TestCaseError> {
724///   prop_assert!((a*a + b*b).sqrt() <= a + b);
725///   Ok(())
726/// }
727/// #
728/// # fn main() { triangle_inequality(); }
729/// ```
730#[macro_export]
731macro_rules! prop_assert {
732    ($cond:expr) => {
733        $crate::prop_assert!($cond, concat!("assertion failed: ", stringify!($cond)))
734    };
735
736    ($cond:expr, $($fmt:tt)*) => {
737        if !$cond {
738            let message = format!($($fmt)*);
739            let message = format!("{} at {}:{}", message, file!(), line!());
740            return ::core::result::Result::Err(
741                $crate::test_runner::TestCaseError::fail(message));
742        }
743    };
744}
745
746/// Similar to `assert_eq!` from std, but returns a test failure instead of
747/// panicking if the condition fails.
748///
749/// See `prop_assert!` for a more in-depth discussion.
750///
751/// ## Example
752///
753/// ```
754/// use proptest::prelude::*;
755///
756/// proptest! {
757///   # /*
758///   #[test]
759///   # */
760///   fn concat_string_length(ref a in ".*", ref b in ".*") {
761///     let cat = format!("{}{}", a, b);
762///     // Use with default message
763///     prop_assert_eq!(a.len() + b.len(), cat.len());
764///     // Can also provide custom message (added after the normal
765///     // assertion message)
766///     prop_assert_eq!(a.len() + b.len(), cat.len(),
767///                     "a = {:?}, b = {:?}", a, b);
768///   }
769/// }
770/// #
771/// # fn main() { concat_string_length(); }
772/// ```
773#[macro_export]
774macro_rules! prop_assert_eq {
775    ($left:expr, $right:expr) => {{
776        let left = $left;
777        let right = $right;
778        $crate::prop_assert!(
779            left == right,
780            "assertion failed: `(left == right)` \
781             \n  left: `{:?}`,\n right: `{:?}`",
782            left, right);
783    }};
784
785    ($left:expr, $right:expr, $fmt:tt $($args:tt)*) => {{
786        let left = $left;
787        let right = $right;
788        $crate::prop_assert!(
789            left == right,
790            concat!(
791                "assertion failed: `(left == right)` \
792                 \n  left: `{:?}`, \n right: `{:?}`: ", $fmt),
793            left, right $($args)*);
794    }};
795}
796
797/// Similar to `assert_ne!` from std, but returns a test failure instead of
798/// panicking if the condition fails.
799///
800/// See `prop_assert!` for a more in-depth discussion.
801///
802/// ## Example
803///
804/// ```
805/// use proptest::prelude::*;
806///
807/// proptest! {
808///   # /*
809///   #[test]
810///   # */
811///   fn test_addition(a in 0i32..100i32, b in 1i32..100i32) {
812///     // Use with default message
813///     prop_assert_ne!(a, a + b);
814///     // Can also provide custom message added after the common message
815///     prop_assert_ne!(a, a + b, "a = {}, b = {}", a, b);
816///   }
817/// }
818/// #
819/// # fn main() { test_addition(); }
820/// ```
821#[macro_export]
822macro_rules! prop_assert_ne {
823    ($left:expr, $right:expr) => {{
824        let left = $left;
825        let right = $right;
826        prop_assert!(
827            left != right,
828            "assertion failed: `(left != right)`\
829             \n  left: `{:?}`,\n right: `{:?}`",
830                     left, right);
831    }};
832
833    ($left:expr, $right:expr, $fmt:tt $($args:tt)*) => {{
834        let left = $left;
835        let right = $right;
836        prop_assert!(left != right, concat!(
837            "assertion failed: `(left != right)`\
838             \n  left: `{:?}`,\n right: `{:?}`: ", $fmt),
839                     left, right $($args)*);
840    }};
841}
842
843#[doc(hidden)]
844#[macro_export]
845macro_rules! proptest_helper {
846    (@_WRAP ($a:tt)) => { $a };
847    (@_WRAP ($a0:tt $a1:tt)) => { ($a0, $a1) };
848    (@_WRAP ($a0:tt $a1:tt $a2:tt)) => { ($a0, $a1, $a2) };
849    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt)) => { ($a0, $a1, $a2, $a3) };
850    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt)) => {
851        ($a0, $a1, $a2, $a3, $a4)
852    };
853    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt $a5:tt)) => {
854        ($a0, $a1, $a2, $a3, $a4, $a5)
855    };
856    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt $a5:tt $a6:tt)) => {
857        ($a0, $a1, $a2, $a3, $a4, $a5, $a6)
858    };
859    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt
860             $a4:tt $a5:tt $a6:tt $a7:tt)) => {
861        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7)
862    };
863    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt
864             $a5:tt $a6:tt $a7:tt $a8:tt)) => {
865        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8)
866    };
867    (@_WRAP ($a0:tt $a1:tt $a2:tt $a3:tt $a4:tt
868             $a5:tt $a6:tt $a7:tt $a8:tt $a9:tt)) => {
869        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9)
870    };
871    (@_WRAP ($a:tt $($rest:tt)*)) => {
872        ($a, $crate::proptest_helper!(@_WRAP ($($rest)*)))
873    };
874    (@_WRAPPAT ($item:pat)) => { $item };
875    (@_WRAPPAT ($a0:pat, $a1:pat)) => { ($a0, $a1) };
876    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat)) => { ($a0, $a1, $a2) };
877    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat)) => {
878        ($a0, $a1, $a2, $a3)
879    };
880    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat)) => {
881        ($a0, $a1, $a2, $a3, $a4)
882    };
883    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat, $a5:pat)) => {
884        ($a0, $a1, $a2, $a3, $a4, $a5)
885    };
886    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
887                $a4:pat, $a5:pat, $a6:pat)) => {
888        ($a0, $a1, $a2, $a3, $a4, $a5, $a6)
889    };
890    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
891                $a4:pat, $a5:pat, $a6:pat, $a7:pat)) => {
892        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7)
893    };
894    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
895                $a5:pat, $a6:pat, $a7:pat, $a8:pat)) => {
896        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8)
897    };
898    (@_WRAPPAT ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
899                $a5:pat, $a6:pat, $a7:pat, $a8:pat, $a9:pat)) => {
900        ($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9)
901    };
902    (@_WRAPPAT ($a:pat, $($rest:pat),*)) => {
903        ($a, $crate::proptest_helper!(@_WRAPPAT ($($rest),*)))
904    };
905    (@_WRAPSTR ($item:pat)) => { stringify!($item) };
906    (@_WRAPSTR ($a0:pat, $a1:pat)) => { (stringify!($a0), stringify!($a1)) };
907    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat)) => {
908        (stringify!($a0), stringify!($a1), stringify!($a2))
909    };
910    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat)) => {
911        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3))
912    };
913    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat)) => {
914        (stringify!($a0), stringify!($a1), stringify!($a2),
915         stringify!($a3), stringify!($a4))
916    };
917    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat, $a5:pat)) => {
918        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
919         stringify!($a4), stringify!($a5))
920    };
921    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
922                $a4:pat, $a5:pat, $a6:pat)) => {
923        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
924         stringify!($a4), stringify!($a5), stringify!($a6))
925    };
926    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat,
927                $a4:pat, $a5:pat, $a6:pat, $a7:pat)) => {
928        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
929         stringify!($a4), stringify!($a5), stringify!($a6), stringify!($a7))
930    };
931    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
932                $a5:pat, $a6:pat, $a7:pat, $a8:pat)) => {
933        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
934         stringify!($a4), stringify!($a5), stringify!($a6), stringify!($a7),
935         stringify!($a8))
936    };
937    (@_WRAPSTR ($a0:pat, $a1:pat, $a2:pat, $a3:pat, $a4:pat,
938                $a5:pat, $a6:pat, $a7:pat, $a8:pat, $a9:pat)) => {
939        (stringify!($a0), stringify!($a1), stringify!($a2), stringify!($a3),
940         stringify!($a4), stringify!($a5), stringify!($a6), stringify!($a7),
941         stringify!($a8), stringify!($a9))
942    };
943    (@_WRAPSTR ($a:pat, $($rest:pat),*)) => {
944        (stringify!($a), $crate::proptest_helper!(@_WRAPSTR ($($rest),*)))
945    };
946    // build a property testing block that when executed, executes the full property test.
947    (@_BODY $config:ident ($($parm:pat in $strategy:expr),+) [$($mod:tt)*] $body:expr) => {{
948        $config.source_file = Some(file!());
949        let mut runner = $crate::test_runner::TestRunner::new($config);
950        let names = $crate::proptest_helper!(@_WRAPSTR ($($parm),*));
951        match runner.run(
952            &$crate::strategy::Strategy::prop_map(
953                $crate::proptest_helper!(@_WRAP ($($strategy)*)),
954                |values| $crate::sugar::NamedArguments(names, values)),
955            $($mod)* |$crate::sugar::NamedArguments(
956                _, $crate::proptest_helper!(@_WRAPPAT ($($parm),*)))|
957            {
958                let _: () = $body;
959                Ok(())
960            })
961        {
962            Ok(_) => (),
963            Err(e) => panic!("{}\n{}", e, runner),
964        }
965    }};
966    // build a property testing block that when executed, executes the full property test.
967    (@_BODY2 $config:ident ($($arg:tt)+) [$($mod:tt)*] $body:expr) => {{
968        $config.source_file = Some(file!());
969        let mut runner = $crate::test_runner::TestRunner::new($config);
970        let names = $crate::proptest_helper!(@_EXT _STR ($($arg)*));
971        match runner.run(
972            &$crate::strategy::Strategy::prop_map(
973                $crate::proptest_helper!(@_EXT _STRAT ($($arg)*)),
974                |values| $crate::sugar::NamedArguments(names, values)),
975            $($mod)* |$crate::sugar::NamedArguments(
976                _, $crate::proptest_helper!(@_EXT _PAT ($($arg)*)))|
977            {
978                let _: () = $body;
979                Ok(())
980            })
981        {
982            Ok(_) => (),
983            Err(e) => panic!("{}\n{}", e, runner),
984        }
985    }};
986
987    // The logic below helps support `pat: type` in the proptest! macro.
988
989    // These matchers define the actual logic:
990    (@_STRAT [$s:ty] [$p:pat]) => { $crate::arbitrary::any::<$s>()  };
991    (@_PAT [$s:ty] [$p:pat]) => { $p };
992    (@_STR [$s:ty] [$p:pat]) => { stringify!($p) };
993    (@_STRAT in [$s:expr] [$p:pat]) => { $s };
994    (@_PAT in [$s:expr] [$p:pat]) => { $p };
995    (@_STR in [$s:expr] [$p:pat]) => { stringify!($p) };
996
997    // These matchers rewrite into the above extractors.
998    // We have to do this because `:` can't FOLLOW(pat).
999    // Note that this is not the full `pat` grammar...
1000    // See https://docs.rs/syn/0.14.2/syn/enum.Pat.html for that.
1001    (@_EXT $cmd:ident ($p:pat in $s:expr $(,)?)) => {
1002        $crate::proptest_helper!(@$cmd in [$s] [$p])
1003    };
1004    (@_EXT $cmd:ident (($p:pat) : $s:ty $(,)?)) => {
1005        // Users can wrap in parens as a last resort.
1006        $crate::proptest_helper!(@$cmd [$s] [$p])
1007    };
1008    (@_EXT $cmd:ident (_ : $s:ty $(,)?)) => {
1009        $crate::proptest_helper!(@$cmd [$s] [_])
1010    };
1011    (@_EXT $cmd:ident (ref mut $p:ident : $s:ty $(,)?)) => {
1012        $crate::proptest_helper!(@$cmd [$s] [ref mut $p])
1013    };
1014    (@_EXT $cmd:ident (ref $p:ident : $s:ty $(,)?)) => {
1015        $crate::proptest_helper!(@$cmd [$s] [ref $p])
1016    };
1017    (@_EXT $cmd:ident (mut $p:ident : $s:ty $(,)?)) => {
1018        $crate::proptest_helper!(@$cmd [$s] [mut $p])
1019    };
1020    (@_EXT $cmd:ident ($p:ident : $s:ty $(,)?)) => {
1021        $crate::proptest_helper!(@$cmd [$s] [$p])
1022    };
1023    (@_EXT $cmd:ident ([$($p:tt)*] : $s:ty $(,)?)) => {
1024        $crate::proptest_helper!(@$cmd [$s] [[$($p)*]])
1025    };
1026
1027    // Rewrite, Inductive case:
1028    (@_EXT $cmd:ident ($p:pat in $s:expr, $($r:tt)*)) => {
1029        ($crate::proptest_helper!(@$cmd in [$s] [$p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1030    };
1031    (@_EXT $cmd:ident (($p:pat) : $s:ty, $($r:tt)*)) => {
1032        ($crate::proptest_helper!(@$cmd [$s] [$p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1033    };
1034    (@_EXT $cmd:ident (_ : $s:ty, $($r:tt)*)) => {
1035        ($crate::proptest_helper!(@$cmd [$s] [_]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1036    };
1037    (@_EXT $cmd:ident (ref mut $p:ident : $s:ty, $($r:tt)*)) => {
1038        ($crate::proptest_helper!(@$cmd [$s] [ref mut $p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1039    };
1040    (@_EXT $cmd:ident (ref $p:ident : $s:ty, $($r:tt)*)) => {
1041        ($crate::proptest_helper!(@$cmd [$s] [ref $p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1042    };
1043    (@_EXT $cmd:ident (mut $p:ident : $s:ty, $($r:tt)*)) => {
1044        ($crate::proptest_helper!(@$cmd [$s] [mut $p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1045    };
1046    (@_EXT $cmd:ident ($p:ident : $s:ty, $($r:tt)*)) => {
1047        ($crate::proptest_helper!(@$cmd [$s] [$p]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1048    };
1049    (@_EXT $cmd:ident ([$($p:tt)*] : $s:ty, $($r:tt)*)) => {
1050        ($crate::proptest_helper!(@$cmd [$s] [[$($p)*]]), $crate::proptest_helper!(@_EXT $cmd ($($r)*)))
1051    };
1052}
1053
1054#[doc(hidden)]
1055#[derive(Clone, Copy)]
1056pub struct NamedArguments<N, V>(#[doc(hidden)] pub N, #[doc(hidden)] pub V);
1057
1058impl<V: fmt::Debug> fmt::Debug for NamedArguments<&'static str, V> {
1059    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1060        write!(f, "{} = ", self.0)?;
1061        self.1.fmt(f)
1062    }
1063}
1064
1065macro_rules! named_arguments_tuple {
1066    ($($ix:tt $argn:ident $argv:ident)*) => {
1067        impl<'a, $($argn : Copy),*, $($argv),*> fmt::Debug
1068        for NamedArguments<($($argn,)*),&'a ($($argv,)*)>
1069        where $(NamedArguments<$argn, &'a $argv> : fmt::Debug),*,
1070              $($argv : 'a),*
1071        {
1072            #[allow(unused_assignments)]
1073            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1074                let mut first = true;
1075                $(
1076                    if !first {
1077                        write!(f, ", ")?;
1078                    }
1079                    first = false;
1080                    fmt::Debug::fmt(
1081                        &NamedArguments((self.0).$ix, &(self.1).$ix), f)?;
1082                )*
1083                Ok(())
1084            }
1085        }
1086
1087        impl<$($argn : Copy),*, $($argv),*> fmt::Debug
1088        for NamedArguments<($($argn,)*), ($($argv,)*)>
1089        where $(for<'a> NamedArguments<$argn, &'a $argv> : fmt::Debug),*
1090        {
1091            #[allow(unused_assignments)]
1092            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1093                let mut first = true;
1094                $(
1095                    if !first {
1096                        write!(f, ", ")?;
1097                    }
1098                    first = false;
1099                    fmt::Debug::fmt(
1100                        &NamedArguments((self.0).$ix, &(self.1).$ix), f)?;
1101                )*
1102                Ok(())
1103            }
1104        }
1105    }
1106}
1107
1108named_arguments_tuple!(0 AN AV);
1109named_arguments_tuple!(0 AN AV 1 BN BV);
1110named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV);
1111named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV);
1112named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV);
1113named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1114                       5 FN FV);
1115named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1116                       5 FN FV 6 GN GV);
1117named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1118                       5 FN FV 6 GN GV 7 HN HV);
1119named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1120                       5 FN FV 6 GN GV 7 HN HV 8 IN IV);
1121named_arguments_tuple!(0 AN AV 1 BN BV 2 CN CV 3 DN DV 4 EN EV
1122                       5 FN FV 6 GN GV 7 HN HV 8 IN IV 9 JN JV);
1123
1124#[cfg(feature = "std")]
1125#[doc(hidden)]
1126pub fn force_no_fork(config: &mut crate::test_runner::Config) {
1127    if config.fork() {
1128        eprintln!(
1129            "proptest: Forking/timeout not supported in closure-style \
1130             invocations; ignoring"
1131        );
1132
1133        #[cfg(feature = "fork")]
1134        {
1135            config.fork = false;
1136        }
1137        #[cfg(feature = "timeout")]
1138        {
1139            config.timeout = 0;
1140        }
1141        assert!(!config.fork());
1142    }
1143}
1144
1145#[cfg(not(feature = "std"))]
1146pub fn force_no_fork(_: &mut crate::test_runner::Config) {}
1147
1148#[cfg(test)]
1149mod test {
1150    use crate::strategy::Just;
1151
1152    prop_compose! {
1153        /// These are docs!
1154        #[allow(dead_code)]
1155        fn two_ints(relative: i32)(a in 0..relative, b in relative..)
1156                   -> (i32, i32) {
1157            (a, b)
1158        }
1159    }
1160
1161    prop_compose! {
1162        /// These are docs!
1163        #[allow(dead_code)]
1164        pub fn two_ints_pub(relative: i32)(a in 0..relative, b in relative..)
1165                           -> (i32, i32) {
1166            (a, b)
1167        }
1168    }
1169
1170    prop_compose! {
1171        /// These are docs!
1172        #[allow(dead_code, improper_ctypes_definitions)]
1173        pub [extern "C"] fn two_ints_pub_with_attrs
1174            (relative: i32)(a in 0..relative, b in relative..)
1175            -> (i32, i32)
1176        {
1177            (a, b)
1178        }
1179    }
1180
1181    prop_compose! {
1182        // The only modifier we can usefully put here is "unsafe", but we want
1183        // to keep this crate unsafe-free, even nominally. "const" may
1184        // eventually work, but is not allowed right now since the generated
1185        // code contains local variables. `extern "C"` is accepted, even though
1186        // the result is useless since the return type isn't C-compatible.
1187        #[allow(dead_code, improper_ctypes_definitions)]
1188        [extern "C"] fn with_modifier(relative: i32)(a in 0..relative) -> i32 {
1189            a
1190        }
1191    }
1192
1193    prop_compose! {
1194        #[allow(dead_code)]
1195        fn a_less_than_b()(b in 0..1000)(a in 0..b, b in Just(b))
1196                        -> (i32, i32) {
1197            (a, b)
1198        }
1199    }
1200
1201    proptest! {
1202        #[test]
1203        fn test_something(a in 0u32..42u32, b in 1u32..10u32) {
1204            prop_assume!(a != 41 || b != 9);
1205            assert!(a + b < 50);
1206        }
1207    }
1208
1209    prop_compose! {
1210        #[allow(dead_code)]
1211        fn single_closure_is_move(base: u64)(off in 0..10u64) -> u64 {
1212            base + off
1213        }
1214    }
1215
1216    prop_compose! {
1217        #[allow(dead_code)]
1218        fn double_closure_is_move
1219            (base: u64)
1220            (off1 in 0..10u64)
1221            (off2 in off1..off1+10)
1222            -> u64
1223        {
1224            base + off2
1225        }
1226    }
1227
1228    #[allow(unused_variables)]
1229    mod test_arg_counts {
1230        use crate::strategy::Just;
1231
1232        proptest! {
1233            #[test]
1234            fn test_1_arg(a in Just(0)) { }
1235            #[test]
1236            fn test_2_arg(a in Just(0), b in Just(0)) { }
1237            #[test]
1238            fn test_3_arg(a in Just(0), b in Just(0), c in Just(0)) { }
1239            #[test]
1240            fn test_4_arg(a in Just(0), b in Just(0), c in Just(0),
1241                          d in Just(0)) { }
1242            #[test]
1243            fn test_5_arg(a in Just(0), b in Just(0), c in Just(0),
1244                          d in Just(0), e in Just(0)) { }
1245            #[test]
1246            fn test_6_arg(a in Just(0), b in Just(0), c in Just(0),
1247                          d in Just(0), e in Just(0), f in Just(0)) { }
1248            #[test]
1249            fn test_7_arg(a in Just(0), b in Just(0), c in Just(0),
1250                          d in Just(0), e in Just(0), f in Just(0),
1251                          g in Just(0)) { }
1252            #[test]
1253            fn test_8_arg(a in Just(0), b in Just(0), c in Just(0),
1254                          d in Just(0), e in Just(0), f in Just(0),
1255                          g in Just(0), h in Just(0)) { }
1256            #[test]
1257            fn test_9_arg(a in Just(0), b in Just(0), c in Just(0),
1258                          d in Just(0), e in Just(0), f in Just(0),
1259                          g in Just(0), h in Just(0), i in Just(0)) { }
1260            #[test]
1261            fn test_a_arg(a in Just(0), b in Just(0), c in Just(0),
1262                          d in Just(0), e in Just(0), f in Just(0),
1263                          g in Just(0), h in Just(0), i in Just(0),
1264                          j in Just(0)) { }
1265            #[test]
1266            fn test_b_arg(a in Just(0), b in Just(0), c in Just(0),
1267                          d in Just(0), e in Just(0), f in Just(0),
1268                          g in Just(0), h in Just(0), i in Just(0),
1269                          j in Just(0), k in Just(0)) { }
1270            #[test]
1271            fn test_c_arg(a in Just(0), b in Just(0), c in Just(0),
1272                          d in Just(0), e in Just(0), f in Just(0),
1273                          g in Just(0), h in Just(0), i in Just(0),
1274                          j in Just(0), k in Just(0), l in Just(0)) { }
1275        }
1276    }
1277
1278    #[test]
1279    fn named_arguments_is_debug_for_needed_cases() {
1280        use super::NamedArguments;
1281
1282        println!("{:?}", NamedArguments("foo", &"bar"));
1283        println!("{:?}", NamedArguments(("foo",), &(1,)));
1284        println!("{:?}", NamedArguments(("foo", "bar"), &(1, 2)));
1285        println!("{:?}", NamedArguments(("a", "b", "c"), &(1, 2, 3)));
1286        println!("{:?}", NamedArguments(("a", "b", "c", "d"), &(1, 2, 3, 4)));
1287        println!(
1288            "{:?}",
1289            NamedArguments(("a", "b", "c", "d", "e"), &(1, 2, 3, 4, 5))
1290        );
1291        println!(
1292            "{:?}",
1293            NamedArguments(("a", "b", "c", "d", "e", "f"), &(1, 2, 3, 4, 5, 6))
1294        );
1295        println!(
1296            "{:?}",
1297            NamedArguments(
1298                ("a", "b", "c", "d", "e", "f", "g"),
1299                &(1, 2, 3, 4, 5, 6, 7)
1300            )
1301        );
1302        println!(
1303            "{:?}",
1304            NamedArguments(
1305                ("a", "b", "c", "d", "e", "f", "g", "h"),
1306                &(1, 2, 3, 4, 5, 6, 7, 8)
1307            )
1308        );
1309        println!(
1310            "{:?}",
1311            NamedArguments(
1312                ("a", "b", "c", "d", "e", "f", "g", "h", "i"),
1313                &(1, 2, 3, 4, 5, 6, 7, 8, 9)
1314            )
1315        );
1316        println!(
1317            "{:?}",
1318            NamedArguments(
1319                ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
1320                &(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
1321            )
1322        );
1323        println!(
1324            "{:?}",
1325            NamedArguments((("a", "b"), "c", "d"), &((1, 2), 3, 4))
1326        );
1327    }
1328
1329    #[test]
1330    fn oneof_all_counts() {
1331        use crate::strategy::{Just as J, Strategy, TupleUnion, Union};
1332
1333        fn expect_count(n: usize, s: impl Strategy<Value = i32>) {
1334            use crate::strategy::*;
1335            use crate::test_runner::*;
1336            use std::collections::HashSet;
1337
1338            let mut runner = TestRunner::default();
1339            let mut seen = HashSet::new();
1340            for _ in 0..1024 {
1341                seen.insert(s.new_tree(&mut runner).unwrap().current());
1342            }
1343
1344            assert_eq!(n, seen.len());
1345        }
1346
1347        fn assert_static<T>(v: TupleUnion<T>) -> TupleUnion<T> {
1348            v
1349        }
1350        fn assert_dynamic<T: Strategy>(v: Union<T>) -> Union<T> {
1351            v
1352        }
1353
1354        expect_count(1, prop_oneof![J(0i32)]);
1355        expect_count(2, assert_static(prop_oneof![J(0i32), J(1i32),]));
1356        expect_count(3, assert_static(prop_oneof![J(0i32), J(1i32), J(2i32),]));
1357        expect_count(
1358            4,
1359            assert_static(prop_oneof![J(0i32), J(1i32), J(2i32), J(3i32),]),
1360        );
1361        expect_count(
1362            5,
1363            assert_static(prop_oneof![
1364                J(0i32),
1365                J(1i32),
1366                J(2i32),
1367                J(3i32),
1368                J(4i32),
1369            ]),
1370        );
1371        expect_count(
1372            6,
1373            assert_static(prop_oneof![
1374                J(0i32),
1375                J(1i32),
1376                J(2i32),
1377                J(3i32),
1378                J(4i32),
1379                J(5i32),
1380            ]),
1381        );
1382        expect_count(
1383            7,
1384            assert_static(prop_oneof![
1385                J(0i32),
1386                J(1i32),
1387                J(2i32),
1388                J(3i32),
1389                J(4i32),
1390                J(5i32),
1391                J(6i32),
1392            ]),
1393        );
1394        expect_count(
1395            8,
1396            assert_static(prop_oneof![
1397                J(0i32),
1398                J(1i32),
1399                J(2i32),
1400                J(3i32),
1401                J(4i32),
1402                J(5i32),
1403                J(6i32),
1404                J(7i32),
1405            ]),
1406        );
1407        expect_count(
1408            9,
1409            assert_static(prop_oneof![
1410                J(0i32),
1411                J(1i32),
1412                J(2i32),
1413                J(3i32),
1414                J(4i32),
1415                J(5i32),
1416                J(6i32),
1417                J(7i32),
1418                J(8i32),
1419            ]),
1420        );
1421        expect_count(
1422            10,
1423            assert_static(prop_oneof![
1424                J(0i32),
1425                J(1i32),
1426                J(2i32),
1427                J(3i32),
1428                J(4i32),
1429                J(5i32),
1430                J(6i32),
1431                J(7i32),
1432                J(8i32),
1433                J(9i32),
1434            ]),
1435        );
1436        expect_count(
1437            11,
1438            assert_dynamic(prop_oneof![
1439                J(0i32),
1440                J(1i32),
1441                J(2i32),
1442                J(3i32),
1443                J(4i32),
1444                J(5i32),
1445                J(6i32),
1446                J(7i32),
1447                J(8i32),
1448                J(9i32),
1449                J(10i32),
1450            ]),
1451        );
1452    }
1453}
1454
1455#[cfg(all(test, feature = "timeout"))]
1456mod test_timeout {
1457    proptest! {
1458        #![proptest_config(crate::test_runner::Config {
1459            fork: true,
1460            .. crate::test_runner::Config::default()
1461        })]
1462
1463        // Ensure that the macro sets the test name properly. If it doesn't,
1464        // this test will fail to run correctly.
1465        #[test]
1466        fn test_name_set_correctly_for_fork(_ in 0u32..1u32) { }
1467    }
1468}
1469
1470#[cfg(test)]
1471mod another_test {
1472    use crate::sugar;
1473
1474    // Ensure that we can access the `[pub]` composed function above.
1475    #[allow(dead_code)]
1476    fn can_access_pub_compose() {
1477        let _ = sugar::test::two_ints_pub(42);
1478        let _ = sugar::test::two_ints_pub_with_attrs(42);
1479    }
1480}
1481
1482#[cfg(test)]
1483mod ownership_tests {
1484    #[cfg(feature = "std")]
1485    proptest! {
1486        #[test]
1487        fn accept_ref_arg(ref s in "[0-9]") {
1488            use crate::std_facade::String;
1489            fn assert_string(_s: &String) {}
1490            assert_string(s);
1491        }
1492
1493        #[test]
1494        fn accept_move_arg(s in "[0-9]") {
1495            use crate::std_facade::String;
1496            fn assert_string(_s: String) {}
1497            assert_string(s);
1498        }
1499    }
1500
1501    #[derive(Debug)]
1502    struct NotClone();
1503    const MK: fn() -> NotClone = NotClone;
1504
1505    proptest! {
1506        #[test]
1507        fn accept_noclone_arg(nc in MK) {
1508            let _nc2: NotClone = nc;
1509        }
1510
1511        #[test]
1512        fn accept_noclone_ref_arg(ref nc in MK) {
1513            let _nc2: &NotClone = nc;
1514        }
1515    }
1516}
1517
1518#[cfg(test)]
1519mod closure_tests {
1520    #[test]
1521    fn test_simple() {
1522        let x = 420;
1523
1524        proptest!(|(y: i32)| {
1525            assert!(x != y);
1526        });
1527
1528        proptest!(|(y in 0..100)| {
1529            println!("{}", y);
1530            assert!(x != y);
1531        });
1532
1533        proptest!(|(y: i32,)| {
1534            assert!(x != y);
1535        });
1536
1537        proptest!(|(y in 0..100,)| {
1538            println!("{}", y);
1539            assert!(x != y);
1540        });
1541    }
1542
1543    #[test]
1544    fn test_move() {
1545        let foo = Foo;
1546
1547        proptest!(move |(x in 1..100, y in 0..100)| {
1548            assert!(x + y > 0, "foo: {:?}", foo);
1549        });
1550
1551        let foo = Foo;
1552        proptest!(move |(x: (), y: ())| {
1553            assert!(x == y, "foo: {:?}", foo);
1554        });
1555
1556        #[derive(Debug)]
1557        struct Foo;
1558    }
1559
1560    #[test]
1561    #[should_panic]
1562    #[allow(unreachable_code)]
1563    fn fails_if_closure_panics() {
1564        proptest!(|(_ in 0..1)| {
1565            panic!()
1566        });
1567    }
1568
1569    #[test]
1570    fn accepts_unblocked_syntax() {
1571        proptest!(|(x in 0u32..10, y in 10u32..20)| assert!(x < y));
1572        proptest!(|(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
1573    }
1574
1575    #[test]
1576    fn accepts_custom_config() {
1577        let conf = crate::test_runner::Config::default();
1578
1579        proptest!(conf, |(x in 0u32..10, y in 10u32..20)| assert!(x < y));
1580        proptest!(&conf, |(x in 0u32..10, y in 10u32..20)| assert!(x < y));
1581        proptest!(conf, move |(x in 0u32..10, y in 10u32..20)| assert!(x < y));
1582        proptest!(conf, |(_x: u32, _y: u32)| { });
1583        proptest!(conf, move |(_x: u32, _y: u32)| { });
1584
1585        // Same as above, but with extra trailing comma
1586        proptest!(conf, |(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
1587        proptest!(&conf, |(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
1588        proptest!(conf, move |(x in 0u32..10, y in 10u32..20,)| assert!(x < y));
1589        proptest!(conf, |(_x: u32, _y: u32,)| { });
1590        proptest!(conf, move |(_x: u32, _y: u32,)| { });
1591    }
1592}
1593
1594#[cfg(test)]
1595mod any_tests {
1596    proptest! {
1597        #[test]
1598        fn test_something
1599            (
1600                a: bool,
1601                b in 25u8..,
1602                c in 25u8..,
1603                _d: (),
1604                mut _e: (),
1605                ref _f: (),
1606                ref mut _g: (),
1607                [_, _]: [(); 2],
1608            ) {
1609            if a {} // Assert bool.
1610            assert!(b as usize + c as usize >= 50);
1611        }
1612    }
1613
1614    // Test that the macro accepts some of the inputs we expect it to:
1615    #[test]
1616    fn proptest_ext_test() {
1617        struct Y(pub u8);
1618
1619        let _ = proptest_helper!(@_EXT _STRAT( _ : u8 ));
1620        let _ = proptest_helper!(@_EXT _STRAT( x : u8 ));
1621        let _ = proptest_helper!(@_EXT _STRAT( ref x : u8 ));
1622        let _ = proptest_helper!(@_EXT _STRAT( mut x : u8 ));
1623        let _ = proptest_helper!(@_EXT _STRAT( ref mut x : u8 ));
1624        let _ = proptest_helper!(@_EXT _STRAT( [_, _] : u8 ));
1625        let _ = proptest_helper!(@_EXT _STRAT( (&mut &Y(ref x)) : u8 ));
1626        let _ = proptest_helper!(@_EXT _STRAT( x in 1..2 ));
1627
1628        let proptest_helper!(@_EXT _PAT( _ : u8 )) = 1;
1629        let proptest_helper!(@_EXT _PAT( _x : u8 )) = 1;
1630        let proptest_helper!(@_EXT _PAT( mut _x : u8 )) = 1;
1631        let proptest_helper!(@_EXT _PAT( ref _x : u8 )) = 1;
1632        let proptest_helper!(@_EXT _PAT( ref mut _x : u8 )) = 1;
1633        let proptest_helper!(@_EXT _PAT( [_, _] : u8 )) = [1, 2];
1634        let proptest_helper!(@_EXT _PAT( (&mut &Y(ref _x)) : u8 )) = &mut &Y(1);
1635        let proptest_helper!(@_EXT _PAT( _x in 1..2 )) = 1;
1636    }
1637}