valFuzz 1.2.0
Loading...
Searching...
No Matches
fuzz.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// Author: Giovanni Santini
3// Mail: giovanni.santini@proton.me
4// Github: @San7o
5
6#include <valfuzz/fuzz.hpp>
7
8namespace valfuzz
9{
10
11std::mt19937 &get_random_engine()
12{
13 static std::mt19937 random_engine;
14 return random_engine;
15}
16
17std::uniform_real_distribution<> &get_uniform_distribution()
18{
19 static std::uniform_real_distribution<> distribution(-1.0, 1.0);
20 return distribution;
21}
22
23template <> __attribute__((noinline)) int get_random<int>()
24{
25 return std::rand();
26}
27
28template <> float get_random<float>()
29{
30 std::mt19937 &random_engine = valfuzz::get_random_engine();
31 std::uniform_real_distribution<> &uniform_distribution =
33 return static_cast<float>(uniform_distribution(random_engine));
34}
35
36template <> double get_random<double>()
37{
38 std::mt19937 &random_engine = valfuzz::get_random_engine();
39 std::uniform_real_distribution<> &uniform_distribution =
41 return static_cast<double>(uniform_distribution(random_engine));
42}
43
44template <> char get_random<char>()
45{
46 return static_cast<char>(std::rand() % 256);
47}
48
49template <> bool get_random<bool>()
50{
51 return static_cast<bool>(std::rand() % 2);
52}
53
54template <> std::string get_random<std::string>()
55{
56 int len = std::rand() % MAX_RANDOM_STRING_LEN;
57 std::string random_string = "";
58 for (int i = 0; i < len; i++)
59 {
60 random_string += get_random<char>();
61 }
62 return random_string;
63}
64
65std::deque<fuzz_pair> &get_fuzzs()
66{
67 static std::deque<fuzz_pair> registered_fuzzs = {};
68 return registered_fuzzs;
69}
70
71long unsigned int get_num_fuzz_tests()
72{
73 auto &fuzzs = get_fuzzs();
74 return fuzzs.size();
75}
76
77std::atomic<long unsigned int> &get_iterations()
78{
79#if __cplusplus >= 202002L // C++20
80 constinit
81#endif
82 static std::atomic<long unsigned int>
83 iterations = 0;
84 return iterations;
85}
86
88{
89 auto &iterations = get_iterations();
90 iterations++;
91}
92
93std::optional<fuzz_pair> pop_fuzz_or_null()
94{
95 auto &fuzzs = get_fuzzs();
96 auto &fuzzs_mutex = get_tests_mutex();
97
98 std::lock_guard<std::mutex> lock(fuzzs_mutex);
99 if (fuzzs.empty())
100 {
101 return std::nullopt;
102 }
103 valfuzz::test_pair test = fuzzs.front();
104 fuzzs.pop_front();
105 return test;
106}
107
108void add_fuzz_test(const std::string &name, fuzz_function fuzz)
109{
110 auto &fuzzs = get_fuzzs();
111 std::lock_guard<std::mutex> lock(get_tests_mutex());
112 fuzzs.push_back({name, fuzz});
113}
114
115void run_one_fuzz(const std::string &name)
116{
117 auto &fuzzs = get_fuzzs();
118 std::deque<fuzz_pair> the_fuzz;
119 std::for_each(fuzzs.begin(), fuzzs.end(),
120 [&the_fuzz, &name](fuzz_pair &fuzz)
121 {
122 if (fuzz.first == name)
123 {
124 for (long unsigned int i = 0; i < get_max_num_threads();
125 i++)
126 {
127 the_fuzz.push_back(fuzz);
128 }
129 }
130 });
131 if (the_fuzz.empty())
132 {
133 std::lock_guard<std::mutex> lock(get_stream_mutex());
134 std::cout << "Fuzz test \"" << name << "\" not found\n";
135 std::exit(1);
136 }
137 fuzzs = the_fuzz;
138 {
139 std::lock_guard<std::mutex> lock(get_stream_mutex());
140 std::cout << "Running fuzz test: " << name << "\n";
141 }
142}
143
145{
146 auto fuzz = std::optional<fuzz_pair>{};
147 while ((fuzz = pop_fuzz_or_null()).has_value())
148 {
149 if (get_verbose())
150 {
151 std::lock_guard<std::mutex> lock(get_stream_mutex());
152 std::cout << "Running fuzz: \"" << fuzz.value().first << "\"\n";
153 }
154 fuzz.value().second(fuzz.value().first);
155
157 long unsigned int iterations = get_iterations();
158 if (iterations % 1000000 == 0)
159 {
160 std::lock_guard<std::mutex> lock(get_stream_mutex());
161 std::cout << "Iterations: " << iterations << "\n";
162 }
163
164 add_fuzz_test(fuzz.value().first, fuzz.value().second);
165 }
166}
167
169{
170 if (get_is_threaded())
171 {
172 auto &thread_pool = get_thread_pool();
173 // spawn threads
174 for (long unsigned int i = 0;
175 i < get_max_num_threads() && i < get_num_fuzz_tests(); i++)
176 {
177 thread_pool.push_back(std::thread(_run_fuzz_tests));
178 }
179 for (auto &thread : get_thread_pool())
180 {
181 thread.join();
182 }
183 }
184 else
185 {
187 }
188}
189
190} // namespace valfuzz
#define MAX_RANDOM_STRING_LEN
Definition fuzz.hpp:27
std::pair< std::string, fuzz_function > fuzz_pair
Definition fuzz.hpp:43
__attribute__((noinline)) int get_random< int >()
Definition fuzz.cpp:23
void run_fuzz_tests()
Definition fuzz.cpp:168
long unsigned int get_num_fuzz_tests()
Definition fuzz.cpp:71
float get_random< float >()
Definition fuzz.cpp:28
std::atomic< long unsigned int > & get_iterations()
Definition fuzz.cpp:77
std::deque< fuzz_pair > & get_fuzzs()
Definition fuzz.cpp:65
std::atomic< long unsigned int > & get_max_num_threads()
Definition common.cpp:30
void _run_fuzz_tests()
Definition fuzz.cpp:144
std::vector< std::thread > & get_thread_pool()
Definition common.cpp:59
std::mutex & get_tests_mutex()
Definition common.cpp:40
std::atomic< bool > & get_verbose()
Definition common.cpp:20
void run_one_fuzz(const std::string &name)
Definition fuzz.cpp:115
void increment_iterations()
Definition fuzz.cpp:87
char get_random< char >()
Definition fuzz.cpp:44
void add_fuzz_test(const std::string &name, fuzz_function test)
Definition fuzz.cpp:108
bool get_random< bool >()
Definition fuzz.cpp:49
std::pair< std::string, test_function > test_pair
Definition common.hpp:19
std::atomic< bool > & get_is_threaded()
Definition common.cpp:49
double get_random< double >()
Definition fuzz.cpp:36
std::string get_random< std::string >()
Definition fuzz.cpp:54
std::optional< fuzz_pair > pop_fuzz_or_null()
Definition fuzz.cpp:93
std::mt19937 & get_random_engine()
Definition fuzz.cpp:11
T get_random()
std::uniform_real_distribution & get_uniform_distribution()
Definition fuzz.cpp:17
std::function< void(std::string)> fuzz_function
Definition fuzz.hpp:42
std::mutex & get_stream_mutex()
Definition common.cpp:11