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.