fuzzcheck/mutators/vector/
vec_mutation.rs

1use super::crossover_insert_slice::CrossoverInsertSlice;
2use super::crossover_replace_element::CrossoverReplaceElement;
3use super::{
4    arbitrary, copy_element, crossover_insert_slice, crossover_replace_element, insert_element, insert_many_elements,
5    mutate_element, only_choose_length, remove, remove_and_insert_element, swap_elements, VecMutator,
6};
7use crate::mutators::mutations::{Mutation, NoMutation, RevertMutation};
8use crate::mutators::vose_alias::VoseAlias;
9use crate::Mutator;
10
11pub struct WeightedMutation<M> {
12    mutation: M,
13    random_weight: f64,
14    ordered_weight: f64,
15}
16macro_rules! impl_vec_mutation {
17    ($(($i:ident,$t:ty)),*) => {
18        pub enum InnerVectorMutation {
19            $($i($t),)*
20        }
21        pub struct VectorMutation {
22            mutations: Vec<WeightedMutation<InnerVectorMutation>>,
23        }
24        pub enum VectorMutationInnerStep<T, M>
25        where
26            T: Clone + 'static,
27            M: Mutator<T>,
28        {
29            $($i(< $t as Mutation<Vec<T>, VecMutator<T, M>>>::Step),)*
30        }
31        pub struct VectorMutationStep<T, M>
32        where
33            T: Clone + 'static,
34            M: Mutator<T>,
35        {
36            inner_steps: Vec<VectorMutationInnerStep<T, M>>,
37            weights: Vec<f64>,
38            sampling: VoseAlias,
39        }
40        pub enum VectorMutationInnerRandomStep<T, M>
41        where
42            T: Clone + 'static,
43            M: Mutator<T>,
44        {
45            $($i(< $t as Mutation<Vec<T>, VecMutator<T, M>>>::RandomStep),)*
46        }
47        pub struct VectorMutationRandomStep<T, M>
48        where
49            T: Clone + 'static,
50            M: Mutator<T>
51        {
52            inner_steps: Vec<VectorMutationInnerRandomStep<T, M>>,
53            sampling: VoseAlias,
54        }
55        pub enum ConcreteVectorMutation<'a, T, M>
56        where
57            T: Clone + 'static,
58            M: Mutator<T>,
59        {
60            $($i(< $t as Mutation<Vec<T>, VecMutator<T, M>>>::Concrete<'a>),)*
61        }
62        pub enum RevertVectorMutation<T, M>
63        where
64            T: Clone + 'static,
65            M: Mutator<T>,
66        {
67            $($i(< $t as Mutation<Vec<T>, VecMutator<T, M>>>::Revert),)*
68        }
69        impl<T, M> Clone for VectorMutationInnerStep<T, M>
70        where
71            T: Clone + 'static,
72            M: Mutator<T>,
73        {
74            #[coverage(off)]
75            fn clone(&self) -> Self {
76                match self {
77                    $(
78                        Self::$i(x) => Self::$i(x.clone())
79                    ),*
80                }
81            }
82        }
83
84        impl<T, M> Clone for VectorMutationStep<T, M>
85        where
86            T: Clone + 'static,
87            M: Mutator<T>,
88            VectorMutationInnerStep<T, M>: Clone
89        {
90            #[coverage(off)]
91            fn clone(&self) -> Self {
92                Self {
93                    inner_steps: self.inner_steps.clone(),
94                    weights: self.weights.clone(),
95                    sampling: self.sampling.clone(),
96                }
97            }
98        }
99
100        impl<T, M> Clone for VectorMutationInnerRandomStep<T, M>
101        where
102            T: Clone + 'static,
103            M: Mutator<T>,
104        {
105            #[allow(unreachable_code)]
106            #[coverage(off)]
107            fn clone(&self) -> Self {
108                match self {
109                    $(
110                        Self::$i(x) => Self::$i(x.clone())
111                    ),*
112                }
113            }
114        }
115
116        impl<T, M> Clone for VectorMutationRandomStep<T, M>
117        where
118            T: Clone + 'static,
119            M: Mutator<T>,
120            VectorMutationInnerRandomStep<T, M>: Clone
121        {
122            #[coverage(off)]
123            fn clone(&self) -> Self {
124                Self {
125                    inner_steps: self.inner_steps.clone(),
126                    sampling: self.sampling.clone(),
127                }
128            }
129        }
130
131        impl<T, M> RevertMutation<Vec<T>, VecMutator<T, M>> for RevertVectorMutation<T, M>
132        where
133            T: Clone + 'static,
134            M: Mutator<T>,
135        {
136            #[coverage(off)]
137            fn revert(
138                self,
139                mutator: &VecMutator<T, M>,
140                value: &mut Vec<T>,
141                cache: &mut <VecMutator<T, M> as Mutator<Vec<T>>>::Cache,
142            ) {
143                match self {
144                    $(
145                        Self::$i(r) => r.revert(mutator, value, cache)
146                    ),*
147                }
148            }
149        }
150
151        impl<T, M> Mutation<Vec<T>, VecMutator<T, M>> for VectorMutation
152        where
153            T: Clone + 'static,
154            M: Mutator<T>,
155        {
156            type RandomStep = VectorMutationRandomStep<T, M>;
157            type Step = VectorMutationStep<T, M>;
158            type Concrete<'a> = ConcreteVectorMutation<'a, T, M>;
159            type Revert = RevertVectorMutation<T, M>;
160            #[coverage(off)]
161            fn default_random_step(&self, mutator: &VecMutator<T, M>, value: &Vec<T>) -> Option<Self::RandomStep> {
162                let inner_steps_and_weights: Vec<(_, f64)> = self
163                    .mutations
164                    .iter()
165                    .filter_map(#[coverage(off)] |mutation| {
166                        match &mutation.mutation {
167                            $(
168                                InnerVectorMutation::$i(r) => r
169                                    .default_random_step(mutator, value)
170                                    .map(VectorMutationInnerRandomStep::$i)
171                            ),*
172                        }
173                        .map(#[coverage(off)] |inner| (inner, mutation.random_weight))
174                    })
175                    .collect::<Vec<_>>();
176
177                if inner_steps_and_weights.is_empty() {
178                    return None;
179                }
180                let weights = inner_steps_and_weights.iter().map(#[coverage(off)] |x| x.1).collect();
181                let sampling = VoseAlias::new(weights);
182                let inner_steps = inner_steps_and_weights.into_iter().map(#[coverage(off)] |x| x.0).collect();
183
184                Some(VectorMutationRandomStep { inner_steps, sampling })
185            }
186            #[coverage(off)]
187            fn random<'a>(
188                mutator: &VecMutator<T, M>,
189                value: &Vec<T>,
190                cache: &<VecMutator<T, M> as Mutator<Vec<T>>>::Cache,
191                step: &Self::RandomStep,
192                max_cplx: f64,
193            ) -> Self::Concrete<'a> {
194                let inner_step_idx = step.sampling.sample();
195                let step = &step.inner_steps[inner_step_idx];
196                match step {
197                    $(
198                        VectorMutationInnerRandomStep::$i(s) =>
199                            ConcreteVectorMutation::$i(<$t>::random(mutator, value, cache, s, max_cplx))
200                    ),*
201                }
202            }
203            #[coverage(off)]
204            fn default_step(
205                &self,
206                mutator: &VecMutator<T, M>,
207                value: &Vec<T>,
208                cache: &<VecMutator<T, M> as Mutator<Vec<T>>>::Cache,
209            ) -> Option<Self::Step> {
210                let inner_steps_and_weights: Vec<(VectorMutationInnerStep<_, _>, f64)> = self
211                    .mutations
212                    .iter()
213                    .filter_map(#[coverage(off)] |mutation| {
214                        match &mutation.mutation {
215                            $(
216                                InnerVectorMutation::$i(r) =>
217                                    r.default_step(mutator, value, cache)
218                                    .map(VectorMutationInnerStep::$i)
219                            ),*
220                        }
221                        .map(#[coverage(off)] |inner| (inner, mutation.ordered_weight))
222                    })
223                    .collect::<Vec<_>>();
224
225                if inner_steps_and_weights.is_empty() {
226                    return None;
227                }
228
229                let mut inner_steps = Vec::with_capacity(inner_steps_and_weights.len());
230                let mut weights = Vec::with_capacity(inner_steps_and_weights.len());
231                let mut probabilities = Vec::with_capacity(inner_steps_and_weights.len());
232                for (inner_step, weight) in inner_steps_and_weights {
233                    inner_steps.push(inner_step);
234                    probabilities.push(weight);
235                    weights.push(weight);
236                }
237                let sampling = VoseAlias::new(probabilities);
238
239                Some(VectorMutationStep {
240                    inner_steps,
241                    weights,
242                    sampling,
243                })
244            }
245            #[coverage(off)]
246            fn from_step<'a>(
247                mutator: &VecMutator<T, M>,
248                value: &Vec<T>,
249                cache: &<VecMutator<T, M> as Mutator<Vec<T>>>::Cache,
250                step: &'a mut Self::Step,
251                subvalue_provider: &dyn crate::SubValueProvider,
252                max_cplx: f64,
253            ) -> Option<Self::Concrete<'a>> {
254                if step.inner_steps.is_empty() {
255                    return None;
256                }
257                let inner_step_idx = step.sampling.sample();
258                let step_raw = step as *mut Self::Step;
259                {
260                    let inner_step = &mut step.inner_steps[inner_step_idx];
261
262                    let concrete: Option<<VectorMutation as Mutation<Vec<T>, VecMutator<T, M>>>::Concrete<'a>> =
263                        match inner_step {
264                            $(
265                                VectorMutationInnerStep::$i(step) =>
266                                    <$t>::from_step(mutator, value, cache, step, subvalue_provider, max_cplx)
267                                    .map(ConcreteVectorMutation::$i)
268                            ),*
269                        };
270                    if let Some(concrete) = concrete {
271                        return Some(concrete);
272                    }
273                }
274                // See: https://stackoverflow.com/questions/50519147/double-mutable-borrow-error-in-a-loop-happens-even-with-nll-on/50570026#50570026 and https://twitter.com/m_ou_se/status/1463606672807632900 https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md#problem-case-3-conditional-control-flow-across-functions for why I had to lie to the borrow checker here
275                let step = unsafe { &mut *step_raw };
276                // remove the step from the array
277                step.weights.remove(inner_step_idx);
278                step.inner_steps.remove(inner_step_idx);
279                if step.weights.is_empty() {
280                    None
281                } else {
282                    step.sampling = VoseAlias::new(step.weights.clone());
283                    Self::from_step(mutator, value, cache, step, subvalue_provider, max_cplx)
284                }
285            }
286            #[coverage(off)]
287            fn apply<'a>(
288                mutation: Self::Concrete<'a>,
289                mutator: &VecMutator<T, M>,
290                value: &mut Vec<T>,
291                cache: &mut <VecMutator<T, M> as Mutator<Vec<T>>>::Cache,
292                subvalue_provider: &dyn crate::SubValueProvider,
293                max_cplx: f64,
294            ) -> (Self::Revert, f64) {
295                match mutation {
296                    $(
297                        ConcreteVectorMutation::$i(mutation) => {
298                            let (revert, cplx) =  <$t>::apply(mutation, mutator, value, cache, subvalue_provider, max_cplx);
299                            (RevertVectorMutation::$i(revert), cplx)
300                        }
301                    )*
302                }
303            }
304        }
305    }
306}
307
308impl_vec_mutation! {
309    (NoMutation, NoMutation),
310    (CopyElement, copy_element::CopyElement),
311    (Remove, remove::Remove),
312    (MutateElement, mutate_element::MutateElement),
313    (InsertElement, insert_element::InsertElement),
314    (SwapElements, swap_elements::SwapElements),
315    (InsertManyElements, insert_many_elements::InsertManyElements),
316    (RemoveAndInsertElement, remove_and_insert_element::RemoveAndInsertElement),
317    (OnlyChooseLength, only_choose_length::OnlyChooseLength),
318    (Arbitrary, arbitrary::Arbitrary),
319    (CrossoverReplaceElement, crossover_replace_element::CrossoverReplaceElement),
320    (CrossoverInsertSlice, crossover_insert_slice::CrossoverInsertSlice)
321}
322
323impl<'a, T, M> std::fmt::Debug for ConcreteVectorMutation<'a, T, M>
324where
325    T: Clone + 'static,
326    M: Mutator<T>,
327{
328    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
329        match self {
330            ConcreteVectorMutation::NoMutation(_) => {
331                write!(f, "NoMutation")
332            }
333            ConcreteVectorMutation::CopyElement(_) => {
334                write!(f, "CopyElement")
335            }
336            ConcreteVectorMutation::Remove(_) => {
337                write!(f, "Remove")
338            }
339            ConcreteVectorMutation::MutateElement(_) => {
340                write!(f, "MutateElement")
341            }
342            ConcreteVectorMutation::InsertElement(_) => {
343                write!(f, "InsertElement")
344            }
345            ConcreteVectorMutation::SwapElements(_) => {
346                write!(f, "SwapElements")
347            }
348            ConcreteVectorMutation::InsertManyElements(_) => {
349                write!(f, "InsertManyElements")
350            }
351            ConcreteVectorMutation::RemoveAndInsertElement(_) => {
352                write!(f, "RemoveAndInsertElement")
353            }
354            ConcreteVectorMutation::OnlyChooseLength(_) => {
355                write!(f, "OnlyChooseLength")
356            }
357            ConcreteVectorMutation::Arbitrary(_) => {
358                write!(f, "Arbitrary")
359            }
360            ConcreteVectorMutation::CrossoverReplaceElement(_) => {
361                write!(f, "CrossoverReplaceElement")
362            }
363            ConcreteVectorMutation::CrossoverInsertSlice(_) => {
364                write!(f, "CrossoverInsertSlice")
365            }
366        }
367    }
368}
369
370// ====== Default Vector Mutations =====
371
372impl Default for VectorMutation {
373    #[coverage(off)]
374    fn default() -> Self {
375        // use the same standard for all of them
376        Self {
377            mutations: vec![
378                WeightedMutation {
379                    mutation: InnerVectorMutation::CopyElement(copy_element::CopyElement),
380                    random_weight: 50.,
381                    ordered_weight: 500.,
382                },
383                WeightedMutation {
384                    mutation: InnerVectorMutation::OnlyChooseLength(only_choose_length::OnlyChooseLength),
385                    random_weight: 1., // doesn't matter, it's the only mutation when relevant!
386                    ordered_weight: 1.,
387                },
388                WeightedMutation {
389                    mutation: InnerVectorMutation::Arbitrary(arbitrary::Arbitrary),
390                    random_weight: 1.,
391                    ordered_weight: 1.,
392                },
393                WeightedMutation {
394                    mutation: InnerVectorMutation::Remove(remove::Remove),
395                    random_weight: 50.,
396                    ordered_weight: 50_000.,
397                },
398                WeightedMutation {
399                    mutation: InnerVectorMutation::MutateElement(mutate_element::MutateElement),
400                    random_weight: 1000.,
401                    ordered_weight: 1000.,
402                },
403                WeightedMutation {
404                    mutation: InnerVectorMutation::InsertElement(insert_element::InsertElement),
405                    random_weight: 50.,
406                    ordered_weight: 50.,
407                },
408                WeightedMutation {
409                    mutation: InnerVectorMutation::RemoveAndInsertElement(
410                        remove_and_insert_element::RemoveAndInsertElement,
411                    ),
412                    random_weight: 50.,
413                    ordered_weight: 30.,
414                },
415                WeightedMutation {
416                    mutation: InnerVectorMutation::SwapElements(swap_elements::SwapElements),
417                    random_weight: 20.,
418                    ordered_weight: 500.,
419                },
420                WeightedMutation {
421                    mutation: InnerVectorMutation::InsertManyElements(insert_many_elements::InsertManyElements {
422                        nbr_added_elements: 2,
423                        repeated: false,
424                    }),
425                    random_weight: 10.,
426                    ordered_weight: 5.,
427                },
428                WeightedMutation {
429                    mutation: InnerVectorMutation::InsertManyElements(insert_many_elements::InsertManyElements {
430                        nbr_added_elements: 3,
431                        repeated: false,
432                    }),
433                    random_weight: 8.,
434                    ordered_weight: 4.,
435                },
436                WeightedMutation {
437                    mutation: InnerVectorMutation::InsertManyElements(insert_many_elements::InsertManyElements {
438                        nbr_added_elements: 4,
439                        repeated: false,
440                    }),
441                    random_weight: 6.,
442                    ordered_weight: 3.,
443                },
444                WeightedMutation {
445                    mutation: InnerVectorMutation::InsertManyElements(insert_many_elements::InsertManyElements {
446                        nbr_added_elements: 5,
447                        repeated: false,
448                    }),
449                    random_weight: 4.,
450                    ordered_weight: 2.,
451                },
452                WeightedMutation {
453                    mutation: InnerVectorMutation::InsertManyElements(insert_many_elements::InsertManyElements {
454                        nbr_added_elements: 2,
455                        repeated: true,
456                    }),
457                    random_weight: 10.,
458                    ordered_weight: 5.,
459                },
460                WeightedMutation {
461                    mutation: InnerVectorMutation::InsertManyElements(insert_many_elements::InsertManyElements {
462                        nbr_added_elements: 3,
463                        repeated: true,
464                    }),
465                    random_weight: 8.,
466                    ordered_weight: 4.,
467                },
468                WeightedMutation {
469                    mutation: InnerVectorMutation::CrossoverReplaceElement(CrossoverReplaceElement),
470                    random_weight: 0.,
471                    ordered_weight: 100.,
472                },
473                WeightedMutation {
474                    mutation: InnerVectorMutation::CrossoverInsertSlice(CrossoverInsertSlice),
475                    random_weight: 0.,
476                    ordered_weight: 50.,
477                },
478                // WeightedMutation {
479                //     mutation: InnerVectorMutation::InsertManyElements(insert_many_elements::InsertManyElements {
480                //         nbr_added_elements: 4,
481                //         repeated: true,
482                //     }),
483                //     random_weight: 6.,
484                //     ordered_weight: 3.,
485                // },
486                // WeightedMutation {
487                //     mutation: InnerVectorMutation::InsertManyElements(insert_many_elements::InsertManyElements {
488                //         nbr_added_elements: 5,
489                //         repeated: true,
490                //     }),
491                //     random_weight: 4.,
492                //     ordered_weight: 2.,
493                // },
494            ],
495        }
496    }
497}