|
1 | | -# proptest-arbitrary-interop |
| 1 | +# proptest-arbitrary-adapter |
2 | 2 |
|
3 | | -This crate provides the necessary glue to reuse an implementation of |
4 | | -[`arbitrary::Arbitrary`] as a [`proptest::strategy::Strategy`]. |
| 3 | +Provides the necessary glue to reuse an implementation of [`arbitrary::Arbitrary`][arbitrary] as a |
| 4 | +[`proptest::strategy::Strategy`][strategy]. |
5 | 5 |
|
6 | | -## Usage |
| 6 | +[arbitrary]: https://docs.rs/arbitrary/1.0.0/arbitrary/trait.Arbitrary.html |
7 | 7 |
|
8 | | -in `Cargo.toml`: |
| 8 | +[strategy]: https://docs.rs/proptest/1.0.0/proptest/strategy/trait.Strategy.html |
9 | 9 |
|
10 | | -```toml |
11 | | -[dependencies] |
12 | | -arbitrary = "1.1.3" |
13 | | -proptest = "1.0.0" |
14 | | -``` |
| 10 | +## Usage |
15 | 11 |
|
16 | | -In your code: |
| 12 | +Assuming you use [`test-strategy`](https://crates.io/crates/test-strategy) (which you should), using a strategy for a |
| 13 | +type that implements `arbitrary::Arbitrary` is as simple as: |
17 | 14 |
|
18 | 15 | ```rust |
19 | | - |
20 | | -// Part 1: suppose you implement Arbitrary for one of your types |
21 | | -// because you want to fuzz it. |
22 | | - |
23 | | -use arbitrary::{Arbitrary, Result, Unstructured}; |
24 | | -#[derive(Copy, Clone, Debug)] |
25 | | -pub struct Rgb { |
26 | | - pub r: u8, |
27 | | - pub g: u8, |
28 | | - pub b: u8, |
29 | | -} |
30 | | -impl<'a> Arbitrary<'a> for Rgb { |
31 | | - fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { |
32 | | - let r = u8::arbitrary(u)?; |
33 | | - let g = u8::arbitrary(u)?; |
34 | | - let b = u8::arbitrary(u)?; |
35 | | - Ok(Rgb { r, g, b }) |
36 | | - } |
| 16 | +#[proptest] |
| 17 | +fn my_test(#[strategy(arb())] my_type: MyType) { |
| 18 | + // … |
37 | 19 | } |
| 20 | +``` |
38 | 21 |
|
39 | | -// Part 2: suppose you later decide that in addition to fuzzing |
40 | | -// you want to use that Arbitrary impl, but with proptest. |
| 22 | +## Origin |
41 | 23 |
|
42 | | -use proptest::prelude::*; |
43 | | -use proptest_arbitrary_interop::arb; |
| 24 | +This code is a copy of the unmaintained crate [`proptest-arbitrary-interop`][origin], with some additional improvements |
| 25 | +from open pull requests of the original's repository. |
44 | 26 |
|
45 | | -proptest! { |
46 | | - #[test] |
47 | | - #[should_panic] |
48 | | - fn always_red(color in arb::<Rgb>()) { |
49 | | - prop_assert!(color.g == 0 || color.r > color.g); |
50 | | - } |
51 | | -} |
52 | | -``` |
| 27 | +[origin]: https://crates.io/crates/proptest-arbitrary-interop |
53 | 28 |
|
54 | 29 | ## Caveats |
55 | 30 |
|
56 | | -It only works with types that implement [`arbitrary::Arbitrary`] in a |
57 | | -particular fashion: those conforming to the requirements of [`ArbInterop`]. |
58 | | -These are roughly "types that, when randomly-generated, don't retain |
59 | | -pointers into the random-data buffer wrapped by the |
60 | | -[`arbitrary::Unstructured`] they are generated from". Many implementations |
61 | | -of [`arbitrary::Arbitrary`] will fit the bill, but certain kinds of |
62 | | -"zero-copy" implementations of [`arbitrary::Arbitrary`] will not work. This |
63 | | -requirement appears to be a necessary part of the semantic model of |
64 | | -[`proptest`] -- generated values have to own their pointer graph, no |
65 | | -borrows. Patches welcome if you can figure out a way to not require it. |
66 | | - |
67 | | -This crate is based on |
68 | | -[`proptest-quickcheck-interop`](https://crates.io/crates/proptest-quickcheck-interop) |
69 | | -by Mazdak Farrokhzad, without whose work I wouldn't have had a clue how to |
70 | | -approach this. The exact type signatures for the [`ArbInterop`] type are |
71 | | -courtesy of Jim Blandy, who I hereby officially designate for-all-time as |
72 | | -the Rust Puzzle King. Any errors I've introduced along the way are, of |
73 | | -course, my own. |
74 | | - |
75 | | -License: MIT OR Apache-2.0 |
| 31 | +It only works with types that implement `arbitrary::Arbitrary` in a particular fashion: those conforming to the |
| 32 | +requirements of `ArbInterop`. These are roughly "types that, when randomly-generated, don't retain pointers into the |
| 33 | +random-data buffer wrapped by the `arbitrary::Unstructured` they are generated from". Many implementations of |
| 34 | +`arbitrary::Arbitrary` will fit the bill, but certain kinds of "zero-copy" implementations of `arbitrary::Arbitrary` |
| 35 | +will not work. This requirement appears to be a necessary part of the semantic model of `proptest` – generated values |
| 36 | +have to own their pointer graph, no borrows. Patches welcome if you can figure out a way to not require it. |
0 commit comments