// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Derive macros that generates both a fuzz target for use with `cargo fuzz`, and a property test //! (via `quickcheck` or `proptest`) for use with `cargo test`. //! //! The reason for having both is that property testing allows for quick iteration to make sure the //! test works, and can be checked in presubmit CI, while fuzzing can test the input space more //! exhaustively and run continuously. //! //! # Example //! //! ```no_run //! #![cfg_attr(fuzzing, no_main)] //! //! #[derive_fuzztest::fuzztest] //! fn transitive_ord(a: u32, b: u32, c: u32) { //! if a >= b && b >= c { //! assert!(a >= c); //! } //! if a <= b && b <= c { //! assert!(a <= c); //! } //! } //! //! #[test] //! fn additional_test_here() { //! /* ... */ //! } //! ``` //! //! # Usage //! //! //! Run the generated property tests //! ```sh //! cargo test //! ``` //! //! Run continuous fuzzing //! ```sh //! cargo +nightly fuzz run //! ``` //! //! # Crate structure //! //! If you use `#[fuzz]` or `#[fuzztest]`, the fuzz target imposes the following requirements: //! //! * The target must be in a separate `[[bin]]` target that only contains a single fuzz target. //! * The crate containing the bin target has `[package.metadata] cargo-fuzz = true` //! * The bin target is annotated with `#![cfg_attr(fuzzing, no_main)]` //! //! The recommended structure for your crate `foo` is to put your tests under `foo/fuzz/src/bin`: //! //! ```text //! foo //! ├── fuzz //! │ ├── src //! │ │ └── bin //! │ │ └── fuzz_target_1.rs //! │ └── Cargo.toml //! ├── src //! │ └── [project source] //! └── Cargo.toml //! ``` //! //! This is different from the default structure generated by `cargo fuzz init` or `cargo fuzz add` //! so that we can take advantage of [target //! auto-discovery](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#target-auto-discovery). //! If you prefer, the default structure generated by `cargo fuzz` can also work, but make sure you //! remove `test = false` from the generated target in `Cargo.toml`. //! //! You will also need to declare a dependency on the `libfuzzer-sys` crate, but only if fuzzing is //! requested: //! //! ```toml //! [target.'cfg(fuzzing)'.dependencies] //! libfuzzer-sys = "*" //! ``` //! //! (The reason for this conditional dependency is that `libfuzzer-sys` injects a main function to //! the resulting binary, and there will be linking failures if we link that in without defining a //! corresponding `fuzz_target`.) //! //! # Features //! //! * `quickcheck` (default) — Enable generation of //! [`quickcheck`](https://docs.rs/quickcheck/latest/quickcheck/) property tests. //! * `proptest` — Enable generation of [`proptest`](https://docs.rs/proptest/latest/proptest/) //! property tests. //! //! #### See also //! * [Announcing Better Support for Fuzzing with Structured Inputs in //! 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) //! * [Bridging Fuzzing and Property //! Testing](https://blog.yoshuawuyts.com/bridging-fuzzing-and-property-testing/) pub use derive_fuzztest_macro::{fuzz, fuzztest, proptest}; #[doc(hidden)] pub mod reexport { #[cfg(feature = "proptest")] pub use proptest; #[cfg(feature = "proptest")] pub use proptest_arbitrary_interop; #[cfg(feature = "quickcheck")] pub use quickcheck; } #[cfg(feature = "quickcheck")] #[doc(hidden)] pub mod arbitrary_bridge { /// Wrapper type that allows `arbitrary::Arbitrary` to be used as `quickcheck::Arbitrary` #[derive(Debug, Clone)] pub struct ArbitraryAdapter arbitrary::Arbitrary<'a>>( pub Result, ); impl quickcheck::Arbitrary for ArbitraryAdapter where T: for<'a> arbitrary::Arbitrary<'a> + Clone + 'static, { fn arbitrary(g: &mut quickcheck::Gen) -> Self { let bytes = Vec::::arbitrary(g); let mut unstructured = arbitrary::Unstructured::new(&bytes); Self(T::arbitrary(&mut unstructured)) } } }