Skip to content

Commit

Permalink
Fix min_complexity() for RecurToMutator
Browse files Browse the repository at this point in the history
  • Loading branch information
loiclec committed Jul 30, 2022
1 parent b4a1c57 commit 6ae6a60
Show file tree
Hide file tree
Showing 33 changed files with 331 additions and 125 deletions.
2 changes: 2 additions & 0 deletions fuzzcheck/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,8 @@ where
_phantom,
} = self;

mutator.initialize();

crate::fuzzer::launch(
Box::new(test_function),
mutator,
Expand Down
9 changes: 8 additions & 1 deletion fuzzcheck/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,17 @@ where
let generation = Generation(fuzzer_stats.total_number_of_runs);
let input = input.new_source(mutator, generation);
// check that the mutator's handling of the complexity is correct
let serialised = String::from_utf8(serializer.to_data(&input.value)).unwrap();
assert!(
(input.complexity(mutator) - cplx).abs() < 0.01,
"The mutator used by the fuzz test does not evaluate the complexity of the test cases consistently.
This is a bug in the implementation of {}",
This is a bug in the implementation of {}
=============
{serialised}
=============
",
std::any::type_name::<M>()
);

Expand Down
123 changes: 71 additions & 52 deletions fuzzcheck/src/mutators/alternation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::any::Any;
use std::cell::Cell;
use std::cmp::Ordering;
use std::marker::PhantomData;

Expand Down Expand Up @@ -26,10 +27,11 @@ where
{
mutators: Vec<M>,
rng: fastrand::Rng,
search_space_complexity: f64,
added_complexity: f64,
min_complexity: f64,
max_complexity: f64,
initialized: Cell<bool>,
min_complexity: Cell<f64>,
max_complexity: Cell<f64>,
search_space_complexity: Cell<f64>,
_phantom: PhantomData<T>,
}

Expand All @@ -41,57 +43,15 @@ where
#[no_coverage]
pub fn new(mutators: Vec<M>, added_complexity: f64) -> Self {
assert!(!mutators.is_empty());
let complexity_from_choice = crate::mutators::size_to_cplxity(mutators.len());

let search_space_complexity = mutators
.iter()
.map(
#[no_coverage]
|m| {
let cplx = m.global_search_space_complexity();
if cplx == 0. {
complexity_from_choice
} else {
cplx
}
},
)
.max_by(
#[no_coverage]
|x, y| x.partial_cmp(y).unwrap_or(Ordering::Equal),
)
.unwrap();

let max_complexity = mutators
.iter()
.map(
#[no_coverage]
|m| m.max_complexity() + added_complexity,
)
.max_by(
#[no_coverage]
|x1, x2| x1.partial_cmp(x2).unwrap_or(Ordering::Equal),
)
.unwrap();
let min_complexity = mutators
.iter()
.map(
#[no_coverage]
|m| m.min_complexity() + added_complexity,
)
.min_by(
#[no_coverage]
|x1, x2| x1.partial_cmp(x2).unwrap_or(Ordering::Equal),
)
.unwrap();

Self {
mutators,
search_space_complexity,
rng: fastrand::Rng::default(),
added_complexity,
min_complexity,
max_complexity,
initialized: Cell::new(false),
min_complexity: Cell::new(std::f64::INFINITY),
max_complexity: Cell::default(),
search_space_complexity: Cell::default(),
_phantom: PhantomData,
}
}
Expand Down Expand Up @@ -152,6 +112,65 @@ where
#[doc(hidden)]
type UnmutateToken = UnmutateToken<T, M::UnmutateToken>;

#[doc(hidden)]
#[no_coverage]
fn initialize(&self) {
for mutator in self.mutators.iter() {
mutator.initialize();
}

let complexity_from_choice = crate::mutators::size_to_cplxity(self.mutators.len());

let search_space_complexity = self
.mutators
.iter()
.map(
#[no_coverage]
|m| {
let cplx = m.global_search_space_complexity();
if cplx == 0. {
complexity_from_choice
} else {
cplx
}
},
)
.max_by(
#[no_coverage]
|x, y| x.partial_cmp(y).unwrap_or(Ordering::Equal),
)
.unwrap();

let max_complexity = self
.mutators
.iter()
.map(
#[no_coverage]
|m| m.max_complexity() + self.added_complexity,
)
.max_by(
#[no_coverage]
|x1, x2| x1.partial_cmp(x2).unwrap_or(Ordering::Equal),
)
.unwrap();
let min_complexity = self
.mutators
.iter()
.map(
#[no_coverage]
|m| m.min_complexity() + self.added_complexity,
)
.min_by(
#[no_coverage]
|x1, x2| x1.partial_cmp(x2).unwrap_or(Ordering::Equal),
)
.unwrap();
self.min_complexity.set(min_complexity);
self.max_complexity.set(max_complexity);
self.search_space_complexity.set(search_space_complexity);
self.initialized.set(true);
}

#[doc(hidden)]
#[no_coverage]
fn default_arbitrary_step(&self) -> Self::ArbitraryStep {
Expand Down Expand Up @@ -226,19 +245,19 @@ where
#[doc(hidden)]
#[no_coverage]
fn global_search_space_complexity(&self) -> f64 {
self.search_space_complexity
self.search_space_complexity.get()
}

#[doc(hidden)]
#[no_coverage]
fn max_complexity(&self) -> f64 {
self.max_complexity
self.max_complexity.get()
}

#[doc(hidden)]
#[no_coverage]
fn min_complexity(&self) -> f64 {
self.min_complexity
self.min_complexity.get()
}

#[doc(hidden)]
Expand Down
6 changes: 6 additions & 0 deletions fuzzcheck/src/mutators/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ impl<T: Clone + 'static, M: Mutator<T>> Mutator<Arc<T>> for ArcMutator<M> {
#[doc(hidden)]
type UnmutateToken = UnmutateToken<T, M::UnmutateToken>;

#[doc(hidden)]
#[no_coverage]
fn initialize(&self) {
self.mutator.initialize();
}

#[doc(hidden)]
#[no_coverage]
fn default_arbitrary_step(&self) -> Self::ArbitraryStep {
Expand Down
32 changes: 22 additions & 10 deletions fuzzcheck/src/mutators/array.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
use std::any::Any;
use std::cell::Cell;
use std::marker::PhantomData;

use fastrand::Rng;

use crate::{DefaultMutator, Mutator};

/// A mutator for fixed-size arrays `[T; N]`.
///
/// A different mutator can be used for each element of the array.
pub struct ArrayMutator<M, T, const N: usize>
where
T: Clone + 'static,
M: Mutator<T>,
{
mutator: M,
min_complexity: f64,
max_complexity: f64,
initialized: Cell<bool>,
min_complexity: Cell<f64>,
max_complexity: Cell<f64>,
pub rng: Rng,
_phantom: PhantomData<T>,
}
Expand All @@ -27,12 +27,11 @@ where
{
#[no_coverage]
pub fn new(mutator: M) -> Self {
let max_complexity = mutator.max_complexity() * N as f64;
let min_complexity = mutator.min_complexity() * N as f64;
Self {
mutator,
min_complexity,
max_complexity,
initialized: Cell::new(false),
min_complexity: Cell::new(std::f64::INFINITY),
max_complexity: Cell::default(),
rng: Rng::default(),
_phantom: PhantomData,
}
Expand Down Expand Up @@ -171,6 +170,18 @@ impl<M: Mutator<T>, T: Clone + 'static, const N: usize> Mutator<[T; N]> for Arra
#[doc(hidden)]
type UnmutateToken = UnmutateArrayToken<M, T, N>;

#[doc(hidden)]
#[no_coverage]
fn initialize(&self) {
self.mutator.initialize();

let max_complexity = self.mutator.max_complexity() * N as f64;
let min_complexity = self.mutator.min_complexity() * N as f64;
self.min_complexity.set(min_complexity);
self.max_complexity.set(max_complexity);
self.initialized.set(true);
}

#[doc(hidden)]
#[no_coverage]
fn default_arbitrary_step(&self) -> Self::ArbitraryStep {}
Expand Down Expand Up @@ -234,13 +245,13 @@ impl<M: Mutator<T>, T: Clone + 'static, const N: usize> Mutator<[T; N]> for Arra
#[doc(hidden)]
#[no_coverage]
fn max_complexity(&self) -> f64 {
self.max_complexity
self.max_complexity.get()
}

#[doc(hidden)]
#[no_coverage]
fn min_complexity(&self) -> f64 {
self.min_complexity
self.min_complexity.get()
}

#[doc(hidden)]
Expand Down Expand Up @@ -377,6 +388,7 @@ mod tests {
#[no_coverage]
fn test_array_mutator() {
let m = ArrayMutator::<U8Mutator, u8, 32>::new(U8Mutator::default());
m.initialize();
for _ in 0..100 {
let (x, _) = m.ordered_arbitrary(&mut (), 800.0).unwrap();
eprintln!("{:?}", x);
Expand Down
4 changes: 4 additions & 0 deletions fuzzcheck/src/mutators/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ impl Mutator<bool> for BoolMutator {
#[doc(hidden)]
type UnmutateToken = bool;

#[doc(hidden)]
#[no_coverage]
fn initialize(&self) {}

#[doc(hidden)]
#[no_coverage]
fn default_arbitrary_step(&self) -> Self::ArbitraryStep {
Expand Down
6 changes: 6 additions & 0 deletions fuzzcheck/src/mutators/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ impl<T: Clone + 'static, M: Mutator<T>> Mutator<Box<T>> for BoxMutator<M> {
#[doc(hidden)]
type UnmutateToken = UnmutateToken<T, M::UnmutateToken>;

#[doc(hidden)]
#[no_coverage]
fn initialize(&self) {
self.mutator.initialize();
}

#[doc(hidden)]
#[no_coverage]
fn default_arbitrary_step(&self) -> Self::ArbitraryStep {
Expand Down
4 changes: 4 additions & 0 deletions fuzzcheck/src/mutators/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ impl Mutator<char> for CharWithinRangeMutator {
#[doc(hidden)]
type UnmutateToken = char; // old value

#[doc(hidden)]
#[no_coverage]
fn initialize(&self) {}

#[doc(hidden)]
#[no_coverage]
fn default_arbitrary_step(&self) -> Self::ArbitraryStep {
Expand Down
4 changes: 4 additions & 0 deletions fuzzcheck/src/mutators/character_classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ impl Mutator<char> for CharacterMutator {
#[doc(hidden)]
type UnmutateToken = char;

#[doc(hidden)]
#[no_coverage]
fn initialize(&self) {}

#[doc(hidden)]
#[no_coverage]
fn default_arbitrary_step(&self) -> Self::ArbitraryStep {
Expand Down
10 changes: 10 additions & 0 deletions fuzzcheck/src/mutators/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ where
#[doc(hidden)]
type UnmutateToken = Either<M1::UnmutateToken, M2::UnmutateToken>;

#[doc(hidden)]
#[inline]
#[no_coverage]
fn initialize(&self) {
match self {
Either::Left(m) => m.initialize(),
Either::Right(m) => m.initialize(),
}
}

#[doc(hidden)]
#[inline]
#[no_coverage]
Expand Down
4 changes: 4 additions & 0 deletions fuzzcheck/src/mutators/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ where
#[doc(hidden)]
type UnmutateToken = usize;

#[doc(hidden)]
#[no_coverage]
fn initialize(&self) {}

#[doc(hidden)]
#[no_coverage]
fn default_arbitrary_step(&self) -> Self::ArbitraryStep {
Expand Down
6 changes: 6 additions & 0 deletions fuzzcheck/src/mutators/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ where
#[doc(hidden)]
type UnmutateToken = <M as Mutator<T>>::UnmutateToken;

#[doc(hidden)]
#[no_coverage]
fn initialize(&self) {
self.mutator.initialize();
}

#[doc(hidden)]
#[no_coverage]
fn default_arbitrary_step(&self) -> Self::ArbitraryStep {
Expand Down
Loading

0 comments on commit 6ae6a60

Please sign in to comment.