blob: 98ebe99bf2f61d34f1b2d288df2d6af9360ac3cc [file] [log] [blame]
Marshall Clowad7b0962018-01-18 16:52:19 +00001// -*- C++ -*-
2//===------------------------- fuzz_test.cpp ------------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11// A simple program for running regressions on the fuzzing routines.
12// This code is not part of any shipping product.
13//
14// To build:
15// clang++ -std=c++11 fuzz_test.cpp fuzzing.cpp
16//
17// To use:
18// fuzz_test -r partial_sort [-v] files...
19//
20// Each file should contain a test case.
21
Marshall Clow4bb655f2018-01-18 18:37:11 +000022// TODO: should add some memory tracking, too.
23
Marshall Clowad7b0962018-01-18 16:52:19 +000024
25#include <iostream>
26#include <fstream>
Marshall Clow226431c2018-01-18 17:01:34 +000027#include <iterator>
Marshall Clowad7b0962018-01-18 16:52:19 +000028#include <vector>
29#include <map>
30#include <chrono>
31
32#include "fuzzing.h"
33
Marshall Clow4bb655f2018-01-18 18:37:11 +000034// ==== Count memory allocations ====
35
36struct MemoryCounters {
37 size_t totalAllocationCount;
38 size_t netAllocationCount;
39 size_t totalBytesAllocated;
40 };
41
42MemoryCounters gMemoryCounters;
43
44void ZeroMemoryCounters() {
45 gMemoryCounters.totalAllocationCount = 0;
46 gMemoryCounters.netAllocationCount = 0;
47 gMemoryCounters.totalBytesAllocated = 0;
48}
49
50void* operator new(std::size_t size)
51{
52 if (size == 0) size = 1;
53 void *p = ::malloc(size);
54 if (p == NULL)
55 throw std::bad_alloc();
56 gMemoryCounters.totalAllocationCount += 1;
57 gMemoryCounters.netAllocationCount += 1;
58 gMemoryCounters.totalBytesAllocated += size;
59 return p;
60}
61
62void* operator new(std::size_t size, const std::nothrow_t&) noexcept
63{
64 try { return operator new(size); }
65 catch (const std::bad_alloc &) {}
66 return nullptr;
67}
68
69void* operator new[](std::size_t size)
70{
71 return ::operator new(size);
72}
73
74void* operator new[](std::size_t size, const std::nothrow_t&) noexcept
75{
76 try { return operator new(size); }
77 catch (const std::bad_alloc &) {}
78 return nullptr;
79}
80
81void operator delete(void* ptr) noexcept
82{
83 if (ptr)
84 ::free(ptr);
85 gMemoryCounters.netAllocationCount -= 1;
86}
87
88void operator delete(void* ptr, const std::nothrow_t&) noexcept
89{
90 ::operator delete(ptr);
91}
92
93void operator delete[](void* ptr) noexcept
94{
95 ::operator delete(ptr);
96}
97
98void operator delete[](void* ptr, const std::nothrow_t&) noexcept
99{
100 ::operator delete(ptr);
101}
102
103// ==== End count memory allocations ====
104
105
Marshall Clowad7b0962018-01-18 16:52:19 +0000106typedef int (*FuzzProc) (const uint8_t *data, size_t size);
107
108const std::map<std::string, FuzzProc> procs = {
109 {"sort", fuzzing::sort},
110 {"stable_sort", fuzzing::stable_sort},
111 {"partition", fuzzing::partition},
112 {"partition_copy", fuzzing::partition_copy},
113 {"stable_partition", fuzzing::stable_partition},
114 {"unique", fuzzing::unique},
115 {"unique_copy", fuzzing::unique_copy},
116 {"nth_element", fuzzing::nth_element},
117 {"partial_sort", fuzzing::partial_sort},
118 {"partial_sort_copy", fuzzing::partial_sort_copy},
119 {"make_heap", fuzzing::make_heap},
120 {"push_heap", fuzzing::push_heap},
121 {"pop_heap", fuzzing::pop_heap},
122 {"regex_ECMAScript", fuzzing::regex_ECMAScript},
123 {"regex_POSIX", fuzzing::regex_POSIX},
124 {"regex_extended", fuzzing::regex_extended},
125 {"regex_awk", fuzzing::regex_awk},
126 {"regex_grep", fuzzing::regex_grep},
127 {"regex_egrep", fuzzing::regex_egrep},
128 {"search", fuzzing::search}
129};
130
131
132
133bool verbose = false;
134
135void test_one(const char *filename, FuzzProc fp)
136{
137 std::vector<uint8_t> v;
138 std::ifstream f (filename, std::ios::binary);
139 if (!f.is_open())
140 std::cerr << "## Can't open '" << filename << "'" << std::endl;
Marshall Clow4bb655f2018-01-18 18:37:11 +0000141 else
142 {
Marshall Clowad7b0962018-01-18 16:52:19 +0000143 typedef std::istream_iterator<uint8_t> Iter;
144 std::copy(Iter(f), Iter(), std::back_inserter(v));
145 if (verbose)
146 std::cout << "File '" << filename << "' contains " << v.size() << " entries" << std::endl;
Marshall Clow4bb655f2018-01-18 18:37:11 +0000147 ZeroMemoryCounters();
Marshall Clow226431c2018-01-18 17:01:34 +0000148 const auto start_time = std::chrono::high_resolution_clock::now();
Marshall Clowad7b0962018-01-18 16:52:19 +0000149 int ret = fp (v.data(), v.size());
Marshall Clow226431c2018-01-18 17:01:34 +0000150 const auto finish_time = std::chrono::high_resolution_clock::now();
Marshall Clow4bb655f2018-01-18 18:37:11 +0000151 MemoryCounters mc = gMemoryCounters;
Marshall Clowad7b0962018-01-18 16:52:19 +0000152 if (ret != 0)
153 std::cerr << "## Failure code: " << ret << std::endl;
154 if (verbose)
Marshall Clow4bb655f2018-01-18 18:37:11 +0000155 {
Marshall Clowad7b0962018-01-18 16:52:19 +0000156 std::cout << "Execution time: "
157 << std::chrono::duration_cast<std::chrono::milliseconds>(finish_time - start_time).count()
158 << " milliseconds" << std::endl;
Marshall Clow4bb655f2018-01-18 18:37:11 +0000159 std::cout << "Memory: "
160 << mc.totalBytesAllocated << " bytes allocated ("
161 << mc.totalAllocationCount << " allocations); "
162 << mc.netAllocationCount << " allocations remain" << std::endl;
Marshall Clowad7b0962018-01-18 16:52:19 +0000163 }
Marshall Clow4bb655f2018-01-18 18:37:11 +0000164 }
Marshall Clowad7b0962018-01-18 16:52:19 +0000165}
166
167void usage (const char *name)
168{
169 std::cout << "Usage: " << name << " -r proc [-v] files..." << std::endl;
170 std::cout << "Supported routines:" << std::endl;
171 for (const auto &p : procs)
172 std::cout << " " << p.first << std::endl;
173 std::cout << std::endl;
174}
175
176// Poor man's command-line options
177const std::string dashR("-r");
178const std::string dashV("-v");
179
180int main(int argc, char *argv[])
181{
182 if (argc < 4 || dashR != argv[1] || procs.find(argv[2]) == procs.end())
183 usage(argv[0]);
184 else {
185 FuzzProc fp = procs.find(argv[2])->second;
186 int firstFile = 3;
187 if (dashV == argv[firstFile])
188 {
189 verbose = true;
190 ++firstFile;
191 }
192 for (int i = firstFile; i < argc; ++i)
193 test_one(argv[i], fp);
194 }
195}