proptest/arbitrary/traits.rs
1//-
2// Copyright 2017, 2018 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 core::fmt;
11
12use crate::strategy::Strategy;
13
14//==============================================================================
15// Arbitrary trait
16//==============================================================================
17
18/// Arbitrary determines a canonical [`Strategy`] for the implementing type.
19///
20/// It provides the method `arbitrary_with` which generates a `Strategy` for
21/// producing arbitrary values of the implementing type *(`Self`)*. In general,
22/// these strategies will produce the entire set of values possible for the
23/// type, up to some size limitation or constraints set by their parameters.
24/// When this is not desired, strategies to produce the desired values can be
25/// built by combining [`Strategy`]s as described in the crate documentation.
26///
27/// This trait analogous to
28/// [Haskell QuickCheck's implementation of `Arbitrary`][HaskellQC].
29/// In this interpretation of `Arbitrary`, `Strategy` is the equivalent of
30/// the `Gen` monad. Unlike in QuickCheck, `Arbitrary` is not a core component;
31/// types do not need to implement `Arbitrary` unless one wants to use
32/// [`any`](fn.any.html) or other free functions in this module.
33///
34/// `Arbitrary` currently only works for types which represent owned data as
35/// opposed to borrowed data. This is a fundamental restriction of `proptest`
36/// which may be lifted in the future as the [generic associated types (GAT)]
37/// feature of Rust is implemented and stabilized.
38///
39/// If you do not have unique constraints on how to generate the data for your
40/// custom types, consider using [the derive macro] to implement Arbitrary
41///
42/// [generic associated types (GAT)]: https://github.com/rust-lang/rust/issues/44265
43///
44/// [`Strategy`]: ../strategy/trait.Strategy.html
45///
46/// [the derive macro]: https://docs.rs/proptest-derive/latest/proptest_derive/
47///
48/// [HaskellQC]:
49/// https://hackage.haskell.org/package/QuickCheck/docs/Test-QuickCheck-Arbitrary.html
50pub trait Arbitrary: Sized + fmt::Debug {
51 /// The type of parameters that [`arbitrary_with`] accepts for configuration
52 /// of the generated [`Strategy`]. Parameters must implement [`Default`].
53 ///
54 /// [`arbitrary_with`]: trait.Arbitrary.html#tymethod.arbitrary_with
55 ///
56 /// [`Strategy`]: ../strategy/trait.Strategy.html
57 /// [`Default`]:
58 /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
59 type Parameters: Default;
60
61 /// Generates a [`Strategy`] for producing arbitrary values
62 /// of type the implementing type (`Self`).
63 ///
64 /// Calling this for the type `X` is the equivalent of using
65 /// [`X::arbitrary_with(Default::default())`].
66 ///
67 /// This method is defined in the trait for optimization for the
68 /// default if you want to do that. It is a logic error to not
69 /// preserve the semantics when overriding.
70 ///
71 /// [`Strategy`]: ../strategy/trait.Strategy.html
72 /// [`X::arbitrary_with(Default::default())`]:
73 /// trait.Arbitrary.html#tymethod.arbitrary_with
74 fn arbitrary() -> Self::Strategy {
75 Self::arbitrary_with(Default::default())
76 }
77
78 /// Generates a [`Strategy`] for producing arbitrary values of type the
79 /// implementing type (`Self`). The strategy is passed the arguments given
80 /// in args.
81 ///
82 /// If you wish to use the [`default()`] arguments,
83 /// use [`arbitrary`] instead.
84 ///
85 /// [`Strategy`]: ../strategy/trait.Strategy.html
86 ///
87 /// [`arbitrary`]: trait.Arbitrary.html#method.arbitrary
88 ///
89 /// [`default()`]:
90 /// https://doc.rust-lang.org/nightly/std/default/trait.Default.html
91 fn arbitrary_with(args: Self::Parameters) -> Self::Strategy;
92
93 /// The type of [`Strategy`] used to generate values of type `Self`.
94 ///
95 /// [`Strategy`]: ../strategy/trait.Strategy.html
96 type Strategy: Strategy<Value = Self>;
97}
98
99//==============================================================================
100// Type aliases for associated types
101//==============================================================================
102
103/// `StrategyFor` allows you to mention the type of [`Strategy`] for the input
104/// type `A` without directly using associated types or without resorting to
105/// existential types. This way, if implementation of [`Arbitrary`] changes,
106/// your tests should not break. This can be especially beneficial when the
107/// type of `Strategy` that you are dealing with is very long in name
108/// (the case with generics).
109///
110/// [`Arbitrary`]: trait.Arbitrary.html
111/// [`Strategy`]: ../strategy/trait.Strategy.html
112pub type StrategyFor<A> = <A as Arbitrary>::Strategy;
113
114/// `ParamsFor` allows you to mention the type of [`Parameters`] for the input
115/// type `A` without directly using associated types or without resorting to
116/// existential types. This way, if implementation of [`Arbitrary`] changes,
117/// your tests should not break.
118///
119/// [`Parameters`]: trait.Arbitrary.html#associatedtype.Parameters
120/// [`Arbitrary`]: trait.Arbitrary.html
121/// [`Strategy`]: ../strategy/trait.Strategy.html
122pub type ParamsFor<A> = <A as Arbitrary>::Parameters;
123
124//==============================================================================
125// Free functions that people should use
126//==============================================================================
127
128/// Generates a [`Strategy`] producing [`Arbitrary`][trait Arbitrary] values of
129/// `A`. Unlike [`arbitrary`][fn arbitrary], it should be used for being
130/// explicit on what `A` is. For clarity, this may be a good idea.
131///
132/// Use this version instead of [`arbitrary`][fn arbitrary] if you want to be
133/// clear which type you want to generate a `Strategy` for, or if you don't
134/// have an anchoring type for type inference to work with.
135///
136/// If you want to customize how the strategy is generated, use
137/// [`any_with::<A>(args)`] where `args` are any arguments accepted by
138/// the `Arbitrary` impl in question.
139///
140/// # Example
141///
142/// The function can be used as:
143///
144/// ```rust
145/// use proptest::prelude::*;
146///
147/// proptest! {
148/// fn reverse_reverse_is_identity(ref vec in any::<Vec<u32>>()) {
149/// let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
150/// prop_assert_eq!(vec, &vec2);
151/// }
152/// }
153///
154/// fn main() {
155/// reverse_reverse_is_identity();
156/// }
157/// ```
158///
159/// [`any_with::<A>(args)`]: fn.any_with.html
160/// [fn arbitrary]: fn.arbitrary.html
161/// [trait Arbitrary]: trait.Arbitrary.html
162/// [`Strategy`]: ../strategy/trait.Strategy.html
163#[must_use = "strategies do nothing unless used"]
164pub fn any<A: Arbitrary>() -> StrategyFor<A> {
165 // ^-- We use a shorter name so that turbofish becomes more ergonomic.
166 A::arbitrary()
167}
168
169/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
170/// given configuration arguments passed in `args`. Unlike [`arbitrary_with`],
171/// it should be used for being explicit on what `A` is.
172/// For clarity, this may be a good idea.
173///
174/// Use this version instead of [`arbitrary_with`] if you want to be clear which
175/// type you want to generate a `Strategy` for, or if you don't have an anchoring
176/// type for type inference to work with.
177///
178/// If you don't want to specify any arguments and instead use the default
179/// behavior, you should use [`any::<A>()`].
180///
181/// # Example
182///
183/// The function can be used as:
184///
185/// ```rust
186/// use proptest::prelude::*;
187/// use proptest::collection::size_range;
188///
189/// proptest! {
190/// fn reverse_reverse_is_identity
191/// (ref vec in any_with::<Vec<u32>>(size_range(1000).lift()))
192/// {
193/// let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
194/// prop_assert_eq!(vec, &vec2);
195/// }
196/// }
197///
198/// fn main() {
199/// reverse_reverse_is_identity();
200/// }
201/// ```
202///
203/// [`any::<A>()`]: fn.any.html
204/// [`arbitrary_with`]: fn.arbitrary_with.html
205/// [`Arbitrary`]: trait.Arbitrary.html
206/// [`Strategy`]: ../strategy/trait.Strategy.html
207#[must_use = "strategies do nothing unless used"]
208pub fn any_with<A: Arbitrary>(args: ParamsFor<A>) -> StrategyFor<A> {
209 // ^-- We use a shorter name so that turbofish becomes more ergonomic.
210 A::arbitrary_with(args)
211}
212
213/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A`.
214/// Works better with type inference than [`any::<A>()`].
215///
216/// With this version, you shouldn't need to specify any of the (many) type
217/// parameters explicitly. This can have a positive effect on type inference.
218/// However, if you want specify `A`, you should use [`any::<A>()`] instead.
219///
220/// For clarity, it is often a good idea to specify the type generated, and
221/// so using [`any::<A>()`] can be a good idea.
222///
223/// If you want to customize how the strategy is generated, use
224/// [`arbitrary_with(args)`] where `args` is of type
225/// `<A as Arbitrary>::Parameters`.
226///
227/// # Example
228///
229/// The function can be used as:
230///
231/// ```rust
232/// extern crate proptest;
233/// use proptest::arbitrary::{arbitrary, StrategyFor};
234///
235/// fn gen_vec_usize() -> StrategyFor<Vec<usize>> {
236/// arbitrary()
237/// }
238///
239/// # fn main() {}
240/// ```
241///
242/// [`arbitrary_with(args)`]: fn.arbitrary_with.html
243/// [`any::<A>()`]: fn.any.html
244/// [`Arbitrary`]: trait.Arbitrary.html
245/// [`Strategy`]: ../strategy/trait.Strategy.html
246#[must_use = "strategies do nothing unless used"]
247pub fn arbitrary<A, S>() -> S
248where
249 // The backlinking here cause an injection which helps type inference.
250 S: Strategy<Value = A>,
251 A: Arbitrary<Strategy = S>,
252{
253 A::arbitrary()
254}
255
256/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
257/// given configuration arguments passed in `args`.
258/// Works better with type inference than [`any_with::<A>(args)`].
259///
260/// With this version, you shouldn't need to specify any of the (many) type
261/// parameters explicitly. This can have a positive effect on type inference.
262/// However, if you want specify `A`, you should use
263/// [`any_with::<A>(args)`] instead.
264///
265/// For clarity, it is often a good idea to specify the type generated, and
266/// so using [`any_with::<A>(args)`] can be a good idea.
267///
268/// If you don't want to specify any arguments and instead use the default
269/// behavior, you should use [`arbitrary()`].
270///
271/// # Example
272///
273/// The function can be used as:
274///
275/// ```rust
276/// extern crate proptest;
277/// use proptest::arbitrary::{arbitrary_with, StrategyFor};
278/// use proptest::collection::size_range;
279///
280/// fn gen_vec_10_u32() -> StrategyFor<Vec<u32>> {
281/// arbitrary_with(size_range(10).lift())
282/// }
283///
284/// # fn main() {}
285/// ```
286///
287/// [`any_with::<A>(args)`]: fn.any_with.html
288/// [`arbitrary()`]: fn.arbitrary.html
289/// [`Arbitrary`]: trait.Arbitrary.html
290/// [`Strategy`]: ../strategy/trait.Strategy.html
291#[must_use = "strategies do nothing unless used"]
292pub fn arbitrary_with<A, S, P>(args: P) -> S
293where
294 P: Default,
295 // The backlinking here cause an injection which helps type inference.
296 S: Strategy<Value = A>,
297 A: Arbitrary<Strategy = S, Parameters = P>,
298{
299 A::arbitrary_with(args)
300}