2 //===------------------------- fuzz_test.cpp ------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 // A simple program for running regressions on the fuzzing routines.
11 // This code is not part of any shipping product.
14 // clang++ -std=c++11 fuzz_test.cpp fuzzing.cpp
17 // fuzz_test -r partial_sort [-v] files...
19 // Each file should contain a test case.
21 // TODO: should add some memory tracking, too.
33 // ==== Count memory allocations ====
35 struct MemoryCounters
{
36 size_t totalAllocationCount
;
37 size_t netAllocationCount
;
38 size_t totalBytesAllocated
;
41 MemoryCounters gMemoryCounters
;
43 void ZeroMemoryCounters() {
44 gMemoryCounters
.totalAllocationCount
= 0;
45 gMemoryCounters
.netAllocationCount
= 0;
46 gMemoryCounters
.totalBytesAllocated
= 0;
49 void* operator new(std::size_t size
)
51 if (size
== 0) size
= 1;
52 void *p
= ::malloc(size
);
54 throw std::bad_alloc();
55 gMemoryCounters
.totalAllocationCount
+= 1;
56 gMemoryCounters
.netAllocationCount
+= 1;
57 gMemoryCounters
.totalBytesAllocated
+= size
;
61 void* operator new(std::size_t size
, const std::nothrow_t
&) noexcept
63 try { return operator new(size
); }
64 catch (const std::bad_alloc
&) {}
68 void* operator new[](std::size_t size
)
70 return ::operator new(size
);
73 void* operator new[](std::size_t size
, const std::nothrow_t
&) noexcept
75 try { return operator new(size
); }
76 catch (const std::bad_alloc
&) {}
80 void operator delete(void* ptr
) noexcept
84 gMemoryCounters
.netAllocationCount
-= 1;
87 void operator delete(void* ptr
, const std::nothrow_t
&) noexcept
89 ::operator delete(ptr
);
92 void operator delete[](void* ptr
) noexcept
94 ::operator delete(ptr
);
97 void operator delete[](void* ptr
, const std::nothrow_t
&) noexcept
99 ::operator delete(ptr
);
102 // ==== End count memory allocations ====
105 typedef int (*FuzzProc
) (const uint8_t *data
, size_t size
);
107 const std::map
<std::string
, FuzzProc
> procs
= {
108 {"sort", fuzzing::sort
},
109 {"stable_sort", fuzzing::stable_sort
},
110 {"partition", fuzzing::partition
},
111 {"partition_copy", fuzzing::partition_copy
},
112 {"stable_partition", fuzzing::stable_partition
},
113 {"unique", fuzzing::unique
},
114 {"unique_copy", fuzzing::unique_copy
},
115 {"nth_element", fuzzing::nth_element
},
116 {"partial_sort", fuzzing::partial_sort
},
117 {"partial_sort_copy", fuzzing::partial_sort_copy
},
118 {"make_heap", fuzzing::make_heap
},
119 {"push_heap", fuzzing::push_heap
},
120 {"pop_heap", fuzzing::pop_heap
},
121 {"regex_ECMAScript", fuzzing::regex_ECMAScript
},
122 {"regex_POSIX", fuzzing::regex_POSIX
},
123 {"regex_extended", fuzzing::regex_extended
},
124 {"regex_awk", fuzzing::regex_awk
},
125 {"regex_grep", fuzzing::regex_grep
},
126 {"regex_egrep", fuzzing::regex_egrep
},
127 {"search", fuzzing::search
}
132 bool verbose
= false;
134 void test_one(const char *filename
, FuzzProc fp
)
136 std::vector
<uint8_t> v
;
137 std::ifstream
f (filename
, std::ios::binary
);
139 std::cerr
<< "## Can't open '" << filename
<< "'" << std::endl
;
142 typedef std::istream_iterator
<uint8_t> Iter
;
143 std::copy(Iter(f
), Iter(), std::back_inserter(v
));
145 std::cout
<< "File '" << filename
<< "' contains " << v
.size() << " entries" << std::endl
;
146 ZeroMemoryCounters();
147 const auto start_time
= std::chrono::high_resolution_clock::now();
148 int ret
= fp (v
.data(), v
.size());
149 const auto finish_time
= std::chrono::high_resolution_clock::now();
150 MemoryCounters mc
= gMemoryCounters
;
152 std::cerr
<< "## Failure code: " << ret
<< std::endl
;
155 std::cout
<< "Execution time: "
156 << std::chrono::duration_cast
<std::chrono::milliseconds
>(finish_time
- start_time
).count()
157 << " milliseconds" << std::endl
;
158 std::cout
<< "Memory: "
159 << mc
.totalBytesAllocated
<< " bytes allocated ("
160 << mc
.totalAllocationCount
<< " allocations); "
161 << mc
.netAllocationCount
<< " allocations remain" << std::endl
;
166 void usage (const char *name
)
168 std::cout
<< "Usage: " << name
<< " -r proc [-v] files..." << std::endl
;
169 std::cout
<< "Supported routines:" << std::endl
;
170 for (const auto &p
: procs
)
171 std::cout
<< " " << p
.first
<< std::endl
;
172 std::cout
<< std::endl
;
175 // Poor man's command-line options
176 const std::string
dashR("-r");
177 const std::string
dashV("-v");
179 int main(int argc
, char *argv
[])
181 if (argc
< 4 || dashR
!= argv
[1] || procs
.find(argv
[2]) == procs
.end())
184 FuzzProc fp
= procs
.find(argv
[2])->second
;
186 if (dashV
== argv
[firstFile
])
191 for (int i
= firstFile
; i
< argc
; ++i
)
192 test_one(argv
[i
], fp
);