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