forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			195 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| // -*- C++ -*-
 | |
| //===------------------------- fuzz_test.cpp ------------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| //  A simple program for running regressions on the fuzzing routines.
 | |
| //  This code is not part of any shipping product.
 | |
| //
 | |
| //  To build:
 | |
| //      clang++ -std=c++11 fuzz_test.cpp fuzzing.cpp
 | |
| //
 | |
| //  To use:
 | |
| //      fuzz_test -r partial_sort [-v] files...
 | |
| //
 | |
| //  Each file should contain a test case.
 | |
| 
 | |
| //  TODO: should add some memory tracking, too.
 | |
| 
 | |
| 
 | |
| #include <iostream>
 | |
| #include <fstream>
 | |
| #include <iterator>
 | |
| #include <vector>
 | |
| #include <map>
 | |
| #include <chrono>
 | |
| 
 | |
| #include "fuzzing.h"
 | |
| 
 | |
| //  ==== Count memory allocations ====
 | |
| 
 | |
| struct MemoryCounters {
 | |
|     size_t totalAllocationCount;
 | |
|     size_t netAllocationCount;
 | |
|     size_t totalBytesAllocated;
 | |
|     };
 | |
| 
 | |
| MemoryCounters gMemoryCounters;
 | |
| 
 | |
| void ZeroMemoryCounters() {
 | |
|     gMemoryCounters.totalAllocationCount = 0;
 | |
|     gMemoryCounters.netAllocationCount = 0;
 | |
|     gMemoryCounters.totalBytesAllocated = 0;
 | |
| }
 | |
| 
 | |
| void* operator new(std::size_t size)
 | |
| {
 | |
|     if (size == 0) size = 1;
 | |
|     void *p = ::malloc(size);
 | |
|     if (p == NULL)
 | |
|         throw std::bad_alloc();
 | |
|     gMemoryCounters.totalAllocationCount += 1;
 | |
|     gMemoryCounters.netAllocationCount  += 1;
 | |
|     gMemoryCounters.totalBytesAllocated += size;
 | |
|     return p;
 | |
| }
 | |
| 
 | |
| void* operator new(std::size_t size, const std::nothrow_t&) noexcept
 | |
| {
 | |
|     try { return operator new(size); }
 | |
|     catch (const std::bad_alloc &) {}
 | |
|     return nullptr;
 | |
| }
 | |
| 
 | |
| void* operator new[](std::size_t size)
 | |
| {
 | |
|     return ::operator new(size);
 | |
| }
 | |
| 
 | |
| void* operator new[](std::size_t size, const std::nothrow_t&) noexcept
 | |
| {
 | |
|     try { return operator new(size); }
 | |
|     catch (const std::bad_alloc &) {}
 | |
|     return nullptr;
 | |
| }
 | |
| 
 | |
| void  operator delete(void* ptr) noexcept
 | |
| {
 | |
|     if (ptr)
 | |
|         ::free(ptr);
 | |
|     gMemoryCounters.netAllocationCount -= 1;
 | |
| }
 | |
| 
 | |
| void  operator delete(void* ptr, const std::nothrow_t&) noexcept
 | |
| {
 | |
|     ::operator delete(ptr);
 | |
| }
 | |
| 
 | |
| void  operator delete[](void* ptr) noexcept
 | |
| {
 | |
|     ::operator delete(ptr);
 | |
| }
 | |
| 
 | |
| void  operator delete[](void* ptr, const std::nothrow_t&) noexcept
 | |
| {
 | |
|     ::operator delete(ptr);
 | |
| }
 | |
| 
 | |
| //  ==== End count memory allocations ====
 | |
| 
 | |
| 
 | |
| typedef int (*FuzzProc) (const uint8_t *data, size_t size);
 | |
| 
 | |
| const std::map<std::string, FuzzProc> procs = {
 | |
|     {"sort",                fuzzing::sort},
 | |
|     {"stable_sort",         fuzzing::stable_sort},
 | |
|     {"partition",           fuzzing::partition},
 | |
|     {"partition_copy",      fuzzing::partition_copy},
 | |
|     {"stable_partition",    fuzzing::stable_partition},
 | |
|     {"unique",              fuzzing::unique},
 | |
|     {"unique_copy",         fuzzing::unique_copy},
 | |
|     {"nth_element",         fuzzing::nth_element},
 | |
|     {"partial_sort",        fuzzing::partial_sort},
 | |
|     {"partial_sort_copy",   fuzzing::partial_sort_copy},
 | |
|     {"make_heap",           fuzzing::make_heap},
 | |
|     {"push_heap",           fuzzing::push_heap},
 | |
|     {"pop_heap",            fuzzing::pop_heap},
 | |
|     {"regex_ECMAScript",    fuzzing::regex_ECMAScript},
 | |
|     {"regex_POSIX",         fuzzing::regex_POSIX},
 | |
|     {"regex_extended",      fuzzing::regex_extended},
 | |
|     {"regex_awk",           fuzzing::regex_awk},
 | |
|     {"regex_grep",          fuzzing::regex_grep},
 | |
|     {"regex_egrep",         fuzzing::regex_egrep},
 | |
|     {"search",              fuzzing::search}
 | |
| };
 | |
| 
 | |
| 
 | |
| 
 | |
| bool verbose = false;
 | |
| 
 | |
| void test_one(const char *filename, FuzzProc fp)
 | |
| {
 | |
|     std::vector<uint8_t> v;
 | |
|     std::ifstream f (filename, std::ios::binary);
 | |
|     if (!f.is_open())
 | |
|         std::cerr << "## Can't open '" << filename << "'" << std::endl;
 | |
|     else
 | |
|     {
 | |
|         typedef std::istream_iterator<uint8_t> Iter;
 | |
|         std::copy(Iter(f), Iter(), std::back_inserter(v));
 | |
|         if (verbose)
 | |
|             std::cout << "File '" << filename << "' contains " << v.size() << " entries" << std::endl;
 | |
|         ZeroMemoryCounters();
 | |
|         const auto start_time = std::chrono::high_resolution_clock::now();
 | |
|         int ret = fp (v.data(), v.size());
 | |
|         const auto finish_time = std::chrono::high_resolution_clock::now();
 | |
|         MemoryCounters mc = gMemoryCounters;
 | |
|         if (ret != 0)
 | |
|             std::cerr << "## Failure code: " << ret << std::endl;
 | |
|         if (verbose)
 | |
|         {
 | |
|             std::cout << "Execution time: "
 | |
|                 << std::chrono::duration_cast<std::chrono::milliseconds>(finish_time - start_time).count()
 | |
|                 << " milliseconds" << std::endl;
 | |
|             std::cout << "Memory: "
 | |
|                       << mc.totalBytesAllocated  << " bytes allocated ("
 | |
|                       << mc.totalAllocationCount << " allocations); "
 | |
|                       << mc.netAllocationCount   << " allocations remain" << std::endl;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void usage (const char *name)
 | |
| {
 | |
|     std::cout << "Usage: " << name << " -r proc [-v] files..." << std::endl;
 | |
|     std::cout << "Supported routines:" << std::endl;
 | |
|     for (const auto &p : procs)
 | |
|         std::cout << "    " << p.first << std::endl;
 | |
|     std::cout << std::endl;
 | |
| }
 | |
| 
 | |
| // Poor man's command-line options
 | |
| const std::string dashR("-r");
 | |
| const std::string dashV("-v");
 | |
| 
 | |
| int main(int argc, char *argv[])
 | |
| {
 | |
|     if (argc < 4 || dashR != argv[1] || procs.find(argv[2]) == procs.end())
 | |
|         usage(argv[0]);
 | |
|     else {
 | |
|         FuzzProc fp = procs.find(argv[2])->second;
 | |
|         int firstFile = 3;
 | |
|         if (dashV == argv[firstFile])
 | |
|         {
 | |
|             verbose = true;
 | |
|             ++firstFile;
 | |
|         }
 | |
|         for (int i = firstFile; i < argc; ++i)
 | |
|             test_one(argv[i], fp);
 | |
|         }
 | |
| }
 |