1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
//! Fuzzcheck is an evolutionary fuzzing engine for Rust functions.
//!
//! It is recommended to use it with the command line tool `cargo-fuzzcheck`, which
//! makes it easy to compile your crate with code coverage instrumentation and
//! to manage fuzz targets.
//!
//! The best way to get started is to follow [the guide at fuzzcheck.neocities.org](https://fuzzcheck.neocities.org).
//!
//! The crate documentation contains information on how to set up and launch a fuzz-test ([here](crate::builder)) but
//! also documents the core traits ([`Pool`], [`Sensor`], [`Mutator`], etc.) that are useful to understand how it works
//! and to extend it.
// Note: ideally fuzzcheck would work on stable Rust
// Recently, -C instrument-coverage was stabilised. The next truly essential
// feature that needs to be stabilised is #[no_coverage]. After that is done,
// I would like to release fuzzcheck on stable.
//
// I have annotated the nightly features below to keep track of what their
// roles are and whether they can be removed easily.
// documentation, not essential
#![feature(doc_cfg)]
// can be replaced by an empty enum
#![feature(never_type)]
// essential
#![feature(no_coverage)]
// used to add #[no_coverage] on closures
#![feature(stmt_expr_attributes)]
// very very nice to use, but I guess not essential?
#![feature(type_alias_impl_trait)]
// essential for tuple mutators, but there may be a (more complicated) way
// to do without them
#![feature(generic_associated_types)]
//
// end nightly features
//
#![allow(clippy::nonstandard_macro_braces)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::partialeq_ne_impl)]
#![allow(clippy::collapsible_if)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::len_without_is_empty)]
#![allow(clippy::nonminimal_bool)]
#![allow(clippy::comparison_chain)]
#![allow(clippy::needless_lifetimes)]
#![allow(clippy::manual_map)]
#![allow(clippy::bool_comparison)]
#![allow(clippy::type_complexity)]
#![allow(clippy::needless_range_loop)]
#[doc(hidden)]
pub extern crate fastrand;
mod bitset;
mod bloom_filter;
pub mod builder;
mod code_coverage_sensor;
mod data_structures;
mod fenwick_tree;
mod fuzzer;
pub mod mutators;
pub mod sensors_and_pools;
pub mod serializers;
mod signals_handler;
mod split_string;
pub mod subvalue_provider;
mod traits;
mod world;
#[doc(inline)]
pub use builder::fuzz_test;
pub use fuzzcheck_common::arg::Arguments;
/**
Make a mutator for a custom type, optionally making it the type’s default mutator.
The syntax is as follows:
```
# #![feature(no_coverage)]
# #![feature(trivial_bounds)]
use fuzzcheck_mutators_derive::make_mutator;
use fuzzcheck::mutators::integer_within_range::U8WithinRangeMutator;
// somewhere, this type is defined
#[derive(Clone)]
pub struct S<T> {
x: u8,
y: T
}
// create a mutator for this type:
make_mutator! {
name: SMutator, // the name of the mutator
recursive: false, // the type is not recursive
default: false, // if `true`, impl DefaultMutator<Mutator = SMutator> for S
type: // repeat the declaration of S
pub struct S<T> {
// left hand side: the type of the mutator for the field
// right hand side (optional): the default value of that mutator
#[field_mutator(U8WithinRangeMutator = { U8WithinRangeMutator::new(0 ..= 10) })]
x: u8,
y: T
}
}
```
For enums:
```
# #![feature(no_coverage)]
use fuzzcheck::make_mutator;
use fuzzcheck::mutators::integer::U8Mutator;
// somewhere, this type is defined
#[derive(Clone)]
pub enum E<T> {
One,
Two(T, u8),
Three { x: Option<u8> }
}
// create a mutator for this type:
make_mutator! {
name: EMutator, // the name of the mutator
recursive: false, // the type is not recursive
default: true, // this is E's default mutator
type: // repeat the declaration of E
pub enum E<T> {
One,
Two(T, #[field_mutator(U8Mutator)] u8),
Three { x: Option<u8> }
}
}
```
Create a recursive mutator:
```
# #![feature(no_coverage)]
use fuzzcheck::make_mutator;
use fuzzcheck::mutators::{option::OptionMutator, boxed::BoxMutator};
use fuzzcheck::mutators::recursive::RecurToMutator;
#[derive(Clone)]
pub struct R<T> {
x: u8,
y: Option<Box<R<T>>>,
z: Vec<T>,
}
make_mutator! {
name: RMutator,
recursive: true,
default: true,
type: // repeat the declaration of R
pub struct R<T> {
x: u8,
// for recursive mutators, it is necessary to indicate *where* the recursion is
// and use a `RecurToMutator` as the recursive field's mutator
// M0 is the type parameter for the mutator of the `x` field, M2 is the type parameter for the mutator of the `z` field
#[field_mutator(OptionMutator<Box<R<T>>, BoxMutator<RecurToMutator<RMutator<T, M0, M2>>>> = { OptionMutator::new(BoxMutator::new(self_.into())) })]
// self_.into() creates the RecurToMutator
y: Option<Box<R<T>>>,
z: Vec<T>
}
}
```
Ignore certain variants of an enum:
```
# #![feature(no_coverage)]
use fuzzcheck::make_mutator;
#[derive(Clone)]
pub enum F<T> {
One,
Two(T, u8),
Three { x: Option<u8> }
}
make_mutator! {
name: FMutator, // the name of the mutator
default: true, // this is F's default mutator
type: // repeat the declaration of F
pub enum F<T> {
One,
Two(T, u8),
#[ignore_variant] // never produce values of the form F::Three { .. }
Three { x: Option<u8> }
}
}
```
*/
pub use fuzzcheck_mutators_derive::make_mutator;
/// Implement a mutator for the type and make it the type’s `DefaultMutator`.
///
/// The mutator will be called `<Name>Mutator`. It can be constructed in two ways:
/// 1. Through the `DefaultMutator` trait, for example:
/// ```
/// # #![feature(no_coverage)]
/// use fuzzcheck::DefaultMutator;
///
/// #[derive(Clone, DefaultMutator)]
/// struct X<A> {
/// field: A,
/// }
/// let mutator = <X<u8> as DefaultMutator>::default_mutator();
/// // but it can also be inferred by the rust compiler:
/// let mutator = X::<u8>::default_mutator();
/// ```
/// 2. By using `<Name>Mutator::new(..)` with the submutators for every field given as argument, for example:
/// ```
/// # #![feature(no_coverage)]
/// use fuzzcheck::DefaultMutator;
///
/// #[derive(Clone, DefaultMutator)]
/// enum Either<A, B> {
/// Left(A),
/// Right(B)
/// }
/// let mutator = EitherMutator::new(u8::default_mutator(), bool::default_mutator());
/// // mutator impl Mutator<Either<u8, bool>>
/// ```
/// Similarly to [`make_mutator!`](crate::make_mutator), you can use the attributes `#[field_mutator]` and `#[ignore_variant]`
/// to customise the generated mutator.
pub use fuzzcheck_mutators_derive::DefaultMutator;
#[doc(inline)]
pub use fuzzer::FuzzingResult;
#[doc(inline)]
pub use fuzzer::PoolStorageIndex;
#[doc(inline)]
pub use fuzzer::ReasonForStopping;
#[doc(inline)]
pub use mutators::DefaultMutator;
#[doc(inline)]
pub use mutators::MutatorExt;
pub(crate) use mutators::CROSSOVER_RATE;
#[doc(inline)]
pub use sensors_and_pools::PoolExt;
#[doc(inline)]
pub use sensors_and_pools::SensorExt;
#[doc(inline)]
pub use serializers::ByteSerializer;
#[cfg(feature = "serde_json_serializer")]
#[doc(inline)]
pub use serializers::SerdeSerializer;
#[doc(inline)]
pub use serializers::StringSerializer;
pub(crate) use split_string::split_string_by_whitespace;
#[doc(inline)]
pub use subvalue_provider::SubValueProvider;
#[doc(inline)]
pub use subvalue_provider::SubValueProviderId;
#[doc(inline)]
pub use traits::CompatibleWithObservations;
#[doc(inline)]
pub use traits::CorpusDelta;
#[doc(inline)]
pub use traits::Mutator;
#[doc(inline)]
pub use traits::Pool;
#[doc(inline)]
pub use traits::SaveToStatsFolder;
#[doc(inline)]
pub use traits::Sensor;
#[doc(inline)]
pub use traits::SensorAndPool;
#[doc(inline)]
pub use traits::Serializer;
#[doc(inline)]
pub use traits::Stats;
#[doc(inline)]
pub use traits::{CSVField, ToCSV};