1use crate::{
2 quickcheck::{Arbitrary, Mutate, RunResult},
3 seedpool::{Seed, SeedPool},
4};
5use std::fmt::Debug;
6
7
8pub fn maximizing_fuzz_loop<
9 Domain: Clone + Arbitrary + Mutate,
10 Codomain,
11 Feedback: Clone + Ord + Debug,
12>(
13 f: fn(Domain) -> Codomain,
14 fb: fn(Box<dyn FnOnce() -> Codomain + '_>) -> (Codomain, Feedback),
15) -> Seed<Domain, Feedback> {
16 let mut pool: SeedPool<Domain, Feedback> = SeedPool::new();
17 let fuel = 100000;
18
19 for i in 1..=fuel {
20 if i % 1000 == 0 {
21 println!("Iteration: {}", i);
22 println!("Pool size: {}", pool.size());
23 println!(
24 "Best of all time: {:?}",
25 pool.best_of_all_time.clone().unwrap().feedback
26 );
27 println!("====================\n");
28 }
29 let input = if let Some(seed) = pool.pop() {
30 Domain::mutate(&seed.input)
31 } else {
32 Domain::generate()
33 };
34
35 let copy = input.clone();
36 let (_, feedback) = fb(Box::new(move || f(copy)));
37
38 if pool.is_empty() {
39 let seed = Seed {
40 input,
41 feedback: feedback,
42 energy: 1000,
43 };
44
45 pool.add_seed(seed);
46 } else {
47 if feedback > pool.best().clone().feedback {
48 let seed = Seed {
49 input,
50 feedback: feedback,
51 energy: 1000,
52 };
53
54 pool.add_seed(seed);
55 }
56 }
57 }
58
59 pool.best_of_all_time.unwrap().clone()
60}
61
62
63pub fn prop_fuzz_loop<Domain: Clone + Arbitrary + Mutate, Feedback: Clone + Ord + Debug>(
64 p: fn(Domain) -> bool,
65 fb: fn(Box<dyn FnOnce() -> bool + '_>) -> (bool, Feedback),
66) -> RunResult<Seed<Domain, Feedback>> {
67 let mut pool: SeedPool<Domain, Feedback> = SeedPool::new();
68 let fuel = 100000;
69
70 for i in 1..=fuel {
71 if i % 1000 == 0 {
72 println!("Iteration: {}", i);
73 println!("Pool size: {}", pool.size());
74 println!(
75 "Best of all time: {:?}",
76 pool.best_of_all_time.clone().unwrap().feedback
77 );
78 println!("====================\n");
79 }
80 let input = if let Some(seed) = pool.pop() {
81 Domain::mutate(&seed.input)
82 } else {
83 Domain::generate()
84 };
85
86 let copy = input.clone();
87 let (result, feedback) = fb(Box::new(move || p(copy)));
88
89 if !result {
90 return RunResult {
91 passed: i,
92 discarded: 0,
93 counterexample: Some(Seed {
94 input: input,
95 feedback: feedback,
96 energy: 1000,
97 }),
98 };
99 }
100 if pool.is_empty() {
101 let seed = Seed {
102 input,
103 feedback: feedback,
104 energy: 1000,
105 };
106
107 pool.add_seed(seed);
108 } else {
109 if feedback > pool.best().clone().feedback {
110 let seed = Seed {
111 input,
112 feedback: feedback,
113 energy: 1000,
114 };
115
116 pool.add_seed(seed);
117 }
118 }
119 }
120
121 RunResult {
122 passed: fuel,
123 discarded: 0,
124 counterexample: None,
125 }
126}