proptest_arbitrary/
lib.rs

1//-
2// Copyright 2017 Mazdak Farrokhzad
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
10//! NOTE: This version is still WIP; don't use yet, just reserving at crates.io.
11//!
12//! Proptest is a property testing framework (i.e., the [`QuickCheck`] family)
13//! inspired by the [Hypothesis](http://hypothesis.works/) framework for
14//! Python.
15//!
16//! This crate, `proptest-arbitrary`, additionally provides an
17//! [`Arbitrary`] trait which allows you to have a canonical [`Strategy`]
18//! per type. This is the equivalent of [Haskell QuickCheck's implementation
19//! of `Arbitrary`]. In this interpretation of `Arbitrary`, `Strategy` is the
20//! equivalent of the `Gen` monad.
21//!
22//! Arbitrary is currently implemented as:
23//!
24//! ```ignore, rust
25//! /// Arbitrary determines a canonical Strategy [..]
26//! pub trait Arbitrary<'a> : Sized + Debug {
27//!    fn arbitrary() -> Self::Strategy {
28//!        Self::arbitrary_with(Default::default())
29//!    }
30//!
31//!    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy;
32//!
33//!    type Parameters: Default;
34//!
35//!     type Strategy: Strategy<Value = Self::ValueTree>;
36//!
37//!     /// NOTE:
38//!     /// This type should NOT be relied upon outside of this crate
39//!     /// other than for implementing `Arbitrary` for other types.
40//!     type ValueTree: ValueTree<Value = Self>;
41//!
42//! }
43//! ```
44//!
45//! <!-- NOREADME
46//! ## Status of this crate
47//!
48//! This crate is currently experimental. It will hopefully be included in
49//! `proptest` in the future.
50//!
51//! The current definition of the [Arbitrary] trait might change in the future
52//! pending the development of [existential types] in Rust.
53//! However, as long as you don't rely on Arbitrary having associated types
54//! in calling Arbitrary, in practice, this should not be a problem.
55//!
56//! This crate mostly just contains Arbitrary and implementations for it.
57//! Therefore, it is unlikely to see breaking change. If any change occurs,
58//! it will likely be new implementations or newtypes around common types.
59//!
60//! See the [changelog] for a full list of substantial historical changes,
61//! breaking and otherwise.
62//!
63//! NOREADME -->
64//!
65//! [changelog]:
66//! https://github.com/Centril/proptest-arbitrary/blob/master/CHANGELOG.md
67//!
68//! [`Arbitrary`]: trait.Arbitrary.html
69//!
70//! [`Strategy`]:
71//! https://docs.rs/proptest/0.3.0/proptest/strategy/trait.Strategy.html
72//!
73//! [existential types]: https://github.com/rust-lang/rfcs/pull/2071
74//!
75//! [Haskell QuickCheck's implementation of `Arbitrary`]:
76//! https://hackage.haskell.org/package/QuickCheck/docs/Test-QuickCheck-Arbitrary.html
77//!
78//! [`QuickCheck`]:
79//! https://hackage.haskell.org/package/QuickCheck
80
81#![deny(missing_docs)]
82
83//==============================================================================
84// Nightly opt-in features:
85//==============================================================================
86
87#![cfg_attr(feature = "unstable", feature(
88      try_from
89    , decode_utf8
90    , io
91    , iterator_step_by
92    , ip
93    , inclusive_range_syntax
94    , inclusive_range
95    , generator_trait
96    , try_trait
97    , integer_atomics
98    , mpsc_select
99    , thread_local_state
100    , allocator_api
101))]
102
103//==============================================================================
104// Frunk:
105//==============================================================================
106
107#[cfg(feature = "frunk")]
108#[macro_use]
109extern crate frunk_derives;
110
111#[cfg(feature = "frunk")]
112#[macro_use]
113extern crate frunk_core;
114
115#[cfg(feature = "frunk")]
116#[macro_use] mod product_frunk;
117
118#[cfg(not(feature = "frunk"))]
119#[macro_use] mod product_tuple;
120
121//==============================================================================
122// Utility:
123//==============================================================================
124
125#[macro_use]
126extern crate derive_more;
127
128//==============================================================================
129// proptest:
130//==============================================================================
131
132#[macro_use]
133extern crate proptest;
134
135extern crate bit_set;
136
137use std::fmt::Debug;
138use proptest::strategy::*;
139
140//==============================================================================
141// Arbitrary trait + auxilary functions:
142//==============================================================================
143
144/// Arbitrary determines a canonical [`Strategy`] for the implementing type.
145///
146/// It provides the function arbitrary which generates a `Strategy` for
147/// producing arbitrary values of the implementing type *(`Self`)*.
148///
149/// This trait is the equivalent of
150/// [Haskell QuickCheck's implementation of `Arbitrary`][HaskellQC].
151/// In this interpretation of `Arbitray`, `Strategy` is the equivalent of
152/// the `Gen` monad.
153///
154/// `Arbitrary` currently only works for types which represent owned data as
155/// opposed to borrowed data. This is a fundamental restriction of `proptest`
156/// which may be lifted in the future as the [generic associated types (GAT)]
157/// feature of Rust is implemented and stabilized.
158///
159/// [generic associated types (GAT)]: https://github.com/rust-lang/rust/issues/44265
160///
161/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
162///
163/// [HaskellQC]:
164/// https://hackage.haskell.org/package/QuickCheck/docs/Test-QuickCheck-Arbitrary.html
165pub trait Arbitrary<'a>: Sized + Debug {
166    // Unfortunately, Generic Associated Types won't be in stable for some time.
167    // Tracking issue: https://github.com/rust-lang/rust/issues/44265
168
169    // We also can't get rid of `ValueTree` yet since it would require:
170    // type Strategy: Strategy<Value = impl ValueTree<Value = Self>>;
171    // which we can't express yet.
172
173    /// Generates a [`Strategy`] for producing arbitrary values
174    /// of type the implementing type (`Self`).
175    ///
176    /// Calling this for the type `X` is the equivalent of using
177    /// [`X::arbitrary_with(Default::default())`].
178    ///
179    /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
180    /// [`X::arbitrary_with(Default::default())`]:
181    ///     trait.Arbitrary.html#tymethod.arbitrary_with
182    fn arbitrary() -> Self::Strategy {
183        Self::arbitrary_with(Default::default())
184    }
185
186    /// Generates a [`Strategy`] for producing arbitrary values of type the
187    /// implementing type (`Self`). The strategy is passed the arguments given
188    /// in args.
189    ///
190    /// If you wish to use the [`default()`] arguments,
191    /// use [`arbitrary`] instead.
192    ///
193    /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
194    ///
195    /// [`arbitrary`]: trait.Arbitrary.html#method.arbitrary
196    ///
197    /// [`default()`]:
198    ///     https://doc.rust-lang.org/nightly/std/default/trait.Default.html
199    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy;
200
201    /// The type of parameters that [`arbitrary_with`] accepts for configuration
202    /// of the generated [`Strategy`]. Parameters must implement [`Default`].
203    ///
204    /// [`arbitrary_with`]: trait.Arbitrary.html#tymethod.arbitrary_with
205    ///
206    /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
207    /// [`Default`]:
208    ///     https://doc.rust-lang.org/nightly/std/default/trait.Default.html
209    type Parameters: Default;
210
211    /// The type of [`Strategy`] used to generate values of type `Self`.
212    ///
213    /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
214    type Strategy: Strategy<Value = Self::ValueTree>;
215
216    /// The type of [`ValueTree`] used for `Self`'s [`Strategy`].
217    ///
218    /// **NOTE:**
219    /// This type should **NOT** be relied upon outside of this
220    /// crate other than for implementing `Arbitrary` for other types.
221    ///
222    /// [`ValueTree`]: ../proptest/strategy/trait.ValueTree.html
223    /// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
224    type ValueTree: ValueTree<Value = Self>;
225}
226
227/// `StrategyFor` allows you to mention the type of [`Strategy`] for the input
228/// type `A` without directly using associated types or without resorting to
229/// existential types. This way, if implementation of [`Arbitrary`] changes,
230/// your tests should not break. This can be especially beneficial when the
231/// type of `Strategy` that you are dealing with is very long in name
232/// (the case with generics). Additionally, if you have a custom `Strategy`
233/// type, or use a `Strategy` type with generics in it where you've provided a
234/// custom type for the type parameter, you need not export your type if `A`
235/// is `Arbitrary` as the `Strategy` type is still reachable from `StrategyFor`.
236///
237/// This is the same as [`StrategyType<'static, A>`].
238///
239/// [`Arbitrary`]: trait.Arbitrary.html
240/// [`StrategyType<'static, A>`]: type.StrategyType.html
241/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
242pub type StrategyFor<A> = StrategyType<'static, A>;
243
244/// `StrategyType` allows you to mention the type of [`Strategy`] for the
245/// input type `A` without directly using associated types or without resorting
246/// to existential types. This way, if implementation of [`Arbitrary`] changes,
247/// your tests should not break. This can be especially beneficial when the
248/// type of `Strategy` that you are dealing with is very long in name
249/// (the case with generics). Additionally, if you have a custom `Strategy`
250/// type, or use a `Strategy` type with generics in it where you've provided
251/// a custom type for the type parameter, you need not export your type if `A`
252/// is `Arbitrary` as the `Strategy` type is still reachable from `StrategyType`.
253///
254/// Unless the strategy uses lifetimes in the type, you most likely want
255/// [`StrategyFor<A>`] instead.
256///
257/// [`Arbitrary`]: trait.Arbitrary.html
258/// [`StrategyFor<A>`]: type.StrategyFor.html
259/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
260pub type StrategyType<'a, A> = <A as Arbitrary<'a>>::Strategy;
261
262/// `ParamsFor` allows you to mention the type of [`Parameters`] for the input
263/// type `A` without directly using associated types or without resorting to
264/// existential types. This way, if implementation of [`Arbitrary`] changes,
265/// your tests should not break. Additionally, if you have a custom
266/// `Arbitrary::Parameters` type, or use a `Arbitrary::Parameters` type with
267/// generics in it where you've provided a custom type for the type parameter,
268/// you need not export your type if `A` is `Arbitrary` as the `Parameters`
269/// type is still reachable from `ParamsFor`.
270///
271/// This is the same as [`ParamsType<'static, A>`].
272///
273/// [`Parameters`]: trait.Arbitrary.html#associatedtype.Parameters
274/// [`Arbitrary`]: trait.Arbitrary.html
275/// [`ParamsType<'static, A>`]: type.StrategyType.html
276/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
277pub type ParamsFor<A> = ParamsType<'static, A>;
278
279/// `ParamsType` allows you to mention the type of [`Parameters`] for the input
280/// type `A` without directly using associated types or without resorting to
281/// existential types. This way, if implementation of [`Arbitrary`] changes,
282/// your tests should not break. Additionally, if you have a custom
283/// `Arbitrary::Parameters` type, or use a `Arbitrary::Parameters` type with
284/// generics in it where you've provided a custom type for the type parameter,
285/// you need not export your type if `A` is `Arbitrary` as the `Parameters`
286/// type is still reachable from `ParamsType`.
287///
288/// Unless the strategy uses lifetimes in the type, you most likely want
289/// [`ParamsFor<A>`] instead.
290///
291/// [`Parameters`]: trait.Arbitrary.html#associatedtype.Parameters
292/// [`Arbitrary`]: trait.Arbitrary.html
293/// [`ParamsFor<A>`]: type.ParamsFor.html
294/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
295pub type ParamsType<'a, A> = <A as Arbitrary<'a>>::Parameters;
296
297/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A`.
298/// Works better with type inference than [`any::<A>()`].
299///
300/// With this version, you shouldn't need to specify any of the (many) type
301/// parameters explicitly. This can have a positive effect on type inference.
302/// However, if you want specify `A`, you should use [`any::<A>()`] instead.
303///
304/// For clarity, it is often a good idea to specify the type generated, and
305/// so using [`any::<A>()`] can be a good idea.
306///
307/// If you want to customize how the strategy is generated, use
308/// [`arbitrary_with(args)`] where `args` is of type
309/// `<A as Arbitrary>::Parameters`.
310///
311/// # Example
312///
313/// The function can be used as:
314///
315/// ```rust
316/// extern crate proptest_arbitrary;
317/// use proptest_arbitrary::{arbitrary, StrategyFor};
318///
319/// fn gen_vec_usize() -> StrategyFor<Vec<usize>> {
320///     arbitrary()
321/// }
322///
323/// # fn main() {}
324/// ```
325///
326/// [`arbitrary_with(args)`]: fn.arbitrary_with.html
327/// [`any::<A>()`]: fn.any.html
328/// [`Arbitrary`]: trait.Arbitrary.html
329/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
330pub fn arbitrary<'a, A, S, V, P>() -> S
331where
332    P: Default,
333    V: ValueTree<Value = A>,
334    S: Strategy<Value = V>,
335    A: Arbitrary<'a, Strategy = S, ValueTree = V, Parameters = P>,
336{
337    A::arbitrary()
338}
339
340/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
341/// given configuration arguments passed in `args`.
342/// Works better with type inference than [`any_with::<A>(args)`].
343///
344/// With this version, you shouldn't need to specify any of the (many) type
345/// parameters explicitly. This can have a positive effect on type inference.
346/// However, if you want specify `A`, you should use
347/// [`any_with::<A>(args)`] instead.
348///
349/// For clarity, it is often a good idea to specify the type generated, and
350/// so using [`any::<A>()`] can be a good idea.
351///
352/// If you don't want to specify any arguments and instead use the default
353/// behavior, you should use [`arbitrary()`].
354///
355/// # Example
356///
357/// The function can be used as:
358///
359/// ```rust
360/// extern crate proptest_arbitrary;
361/// use proptest_arbitrary::{arbitrary_with, StrategyFor, size_bounds};
362///
363/// fn gen_vec_5_u32() -> StrategyFor<Vec<u32>> {
364///     arbitrary_with(size_bounds(10).lift())
365/// }
366///
367/// # fn main() {}
368/// ```
369///
370/// [`any_with::<A>(args)`]: fn.any_with.html
371/// [`arbitrary()`]: fn.arbitrary.html
372/// [`Arbitrary`]: trait.Arbitrary.html
373/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
374pub fn arbitrary_with<'a, A, S, V, P>(args: P) -> S
375where
376    P: Default,
377    V: ValueTree<Value = A>,
378    S: Strategy<Value = V>,
379    A: Arbitrary<'a, Strategy = S, ValueTree = V, Parameters = P>,
380{
381    A::arbitrary_with(args)
382}
383
384/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A`.
385/// Unlike [`arbitrary`], it should be used for being explicit on what `A` is.
386/// For clarity, this may be a good idea.
387///
388/// Use this version instead of [`arbitrary`] if you want to be clear which
389/// type you want to generate a `Strategy` for, or if you don't have an anchoring
390/// type for type inference to work with.
391///
392/// If you want to customize how the strategy is generated, use
393/// [`any_with::<A>(args)`] where `args` are any arguments accepted by
394/// the `Arbitrary` impl in question.
395///
396/// # Example
397///
398/// The function can be used as:
399///
400/// ```rust
401/// #[macro_use] extern crate proptest;
402/// extern crate proptest_arbitrary;
403/// use proptest_arbitrary::{any, StrategyFor};
404///
405/// proptest! {
406///     fn reverse_reverse_is_identity(ref vec in any::<Vec<u32>>()) {
407///         let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
408///         prop_assert_eq!(vec, &vec2);
409///     }
410/// }
411///
412/// fn main() {
413///     reverse_reverse_is_identity();
414/// }
415/// ```
416///
417/// [`any_with::<A>(args)`]: fn.any_with.html
418/// [`arbitrary`]: fn.arbitrary.html
419/// [`Arbitrary`]: trait.Arbitrary.html
420/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
421pub fn any<'a, A: Arbitrary<'a>>() -> StrategyType<'a, A> {
422    // ^-- We use a shorter name so that turbofish becomes more ergonomic.
423    A::arbitrary()
424}
425
426/// Generates a [`Strategy`] producing [`Arbitrary`] values of `A` with the
427/// given configuration arguments passed in `args`. Unlike [`arbitrary_with`],
428/// it should be used for being explicit on what `A` is.
429/// For clarity, this may be a good idea.
430///
431/// Use this version instead of [`arbitrary_with`] if you want to be clear which
432/// type you want to generate a `Strategy` for, or if you don't have an anchoring
433/// type for type inference to work with.
434///
435/// If you don't want to specify any arguments and instead use the default
436/// behavior, you should use [`any::<A>()`].
437///
438/// # Example
439///
440/// The function can be used as:
441///
442/// ```rust
443/// #[macro_use] extern crate proptest;
444/// extern crate proptest_arbitrary;
445/// use proptest_arbitrary::{any_with, StrategyFor, size_bounds};
446///
447/// proptest! {
448///     fn reverse_reverse_is_identity
449///         (ref vec in any_with::<Vec<u32>>(size_bounds(1000).lift()))
450///     {
451///         let vec2 = vec.iter().cloned().rev().rev().collect::<Vec<u32>>();
452///         prop_assert_eq!(vec, &vec2);
453///     }
454/// }
455///
456/// fn main() {
457///     reverse_reverse_is_identity();
458/// }
459/// ```
460///
461/// [`any::<A>()`]: fn.any.html
462/// [`arbitrary_with`]: fn.arbitrary_with.html
463/// [`Arbitrary`]: trait.Arbitrary.html
464/// [`Strategy`]: ../proptest/strategy/trait.Strategy.html
465pub fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters)
466    -> StrategyType<'a, A> {
467    // ^-- We use a shorter name so that turbofish becomes more ergonomic.
468    A::arbitrary_with(args)
469}
470
471//==============================================================================
472// Modules:
473//==============================================================================
474
475#[macro_use] mod macros;
476
477mod utils;
478use utils::*;
479pub use utils::{Mapped, FMapped as MappedF, SMapped as MappedS};
480pub use extras::*;
481mod extras;
482
483mod params;
484pub use params::*;
485
486mod primitives;
487pub use primitives::*;
488
489mod _std;
490pub use _std::*;
491
492mod arrays;
493pub use arrays::*;
494
495mod tuples;
496
497//==============================================================================
498// Sandbox / Dummy region for trying stuff out first:
499//==============================================================================.
500
501// TODO: Relative likelyhood of union (optionally) based on a function:
502// (lexical_pos: usize) -> likelyhood: usize.