1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Derive macros that generates both a fuzz target for use with `cargo fuzz`, and a property test
16 //! (via `quickcheck` or `proptest`) for use with `cargo test`.
17 //!
18 //! The reason for having both is that property testing allows for quick iteration to make sure the
19 //! test works, and can be checked in presubmit CI, while fuzzing can test the input space more
20 //! exhaustively and run continuously.
21 //!
22 //! # Example
23 //!
24 //! ```no_run
25 //! #![cfg_attr(fuzzing, no_main)]
26 //!
27 //! #[derive_fuzztest::fuzztest]
28 //! fn transitive_ord(a: u32, b: u32, c: u32) {
29 //!     if a >= b && b >= c {
30 //!         assert!(a >= c);
31 //!     }
32 //!     if a <= b && b <= c {
33 //!         assert!(a <= c);
34 //!     }
35 //! }
36 //!
37 //! #[test]
38 //! fn additional_test_here() {
39 //!     /* ... */
40 //! }
41 //! ```
42 //!
43 //! # Usage
44 //!
45 //!
46 //! Run the generated property tests
47 //! ```sh
48 //! cargo test
49 //! ```
50 //!
51 //! Run continuous fuzzing
52 //! ```sh
53 //! cargo +nightly fuzz run <binary name>
54 //! ```
55 //!
56 //! # Crate structure
57 //!
58 //! If you use `#[fuzz]` or `#[fuzztest]`, the fuzz target imposes the following requirements:
59 //!
60 //! * The target must be in a separate `[[bin]]` target that only contains a single fuzz target.
61 //! * The crate containing the bin target has `[package.metadata] cargo-fuzz = true`
62 //! * The bin target is annotated with `#![cfg_attr(fuzzing, no_main)]`
63 //!
64 //! The recommended structure for your crate `foo` is to put your tests under `foo/fuzz/src/bin`:
65 //!
66 //! ```text
67 //! foo
68 //! ├── fuzz
69 //! │   ├── src
70 //! │   │   └── bin
71 //! │   │       └── fuzz_target_1.rs
72 //! │   └── Cargo.toml
73 //! ├── src
74 //! │   └── [project source]
75 //! └── Cargo.toml
76 //! ```
77 //!
78 //! This is different from the default structure generated by `cargo fuzz init` or `cargo fuzz add`
79 //! so that we can take advantage of [target
80 //! auto-discovery](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#target-auto-discovery).
81 //! If you prefer, the default structure generated by `cargo fuzz` can also work, but make sure you
82 //! remove `test = false` from the generated target in `Cargo.toml`.
83 //!
84 //! You will also need to declare a dependency on the `libfuzzer-sys` crate, but only if fuzzing is
85 //! requested:
86 //!
87 //! ```toml
88 //! [target.'cfg(fuzzing)'.dependencies]
89 //! libfuzzer-sys = "*"
90 //! ```
91 //!
92 //! (The reason for this conditional dependency is that `libfuzzer-sys` injects a main function to
93 //! the resulting binary, and there will be linking failures if we link that in without defining a
94 //! corresponding `fuzz_target`.)
95 //!
96 //! # Features
97 //!
98 //! * `quickcheck` (default) — Enable generation of
99 //!   [`quickcheck`](https://docs.rs/quickcheck/latest/quickcheck/) property tests.
100 //! * `proptest` — Enable generation of [`proptest`](https://docs.rs/proptest/latest/proptest/)
101 //!   property tests.
102 //!
103 //! #### See also
104 //! * [Announcing Better Support for Fuzzing with Structured Inputs in
105 //!   Rust](https://fitzgeraldnick.com/2020/01/16/better-support-for-fuzzing-structured-inputs-in-rust.html#how-is-all-this-different-from-quickcheck-and-proptest)
106 //! * [Bridging Fuzzing and Property
107 //!   Testing](https://blog.yoshuawuyts.com/bridging-fuzzing-and-property-testing/)
108 
109 pub use derive_fuzztest_macro::{fuzz, fuzztest, proptest};
110 
111 #[doc(hidden)]
112 pub mod reexport {
113     #[cfg(feature = "proptest")]
114     pub use proptest;
115     #[cfg(feature = "proptest")]
116     pub use proptest_arbitrary_interop;
117     #[cfg(feature = "quickcheck")]
118     pub use quickcheck;
119 }
120 
121 #[cfg(feature = "quickcheck")]
122 #[doc(hidden)]
123 pub mod arbitrary_bridge {
124 
125     /// Wrapper type that allows `arbitrary::Arbitrary` to be used as `quickcheck::Arbitrary`
126     #[derive(Debug, Clone)]
127     pub struct ArbitraryAdapter<T: for<'a> arbitrary::Arbitrary<'a>>(
128         pub Result<T, arbitrary::Error>,
129     );
130 
131     impl<T> quickcheck::Arbitrary for ArbitraryAdapter<T>
132     where
133         T: for<'a> arbitrary::Arbitrary<'a> + Clone + 'static,
134     {
arbitrary(g: &mut quickcheck::Gen) -> Self135         fn arbitrary(g: &mut quickcheck::Gen) -> Self {
136             let bytes = Vec::<u8>::arbitrary(g);
137             let mut unstructured = arbitrary::Unstructured::new(&bytes);
138             Self(T::arbitrary(&mut unstructured))
139         }
140     }
141 }
142