make_mutator!() { /* proc-macro */ }
Expand description

Make a mutator for a custom type, optionally making it the type’s default mutator.

The syntax is as follows:

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:

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:

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:

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> }
        }
}