#include "test_scaffold.h" #include "gp/array.hpp" #include "gp/allocator/aggregator.hpp" #include "gp/allocator/buddy.hpp" #include "gp/allocator/dummy.hpp" #include "gp/algorithm/repeat.hpp" #include "gp/ring_list.hpp" #include #include #include #include #include #include #include #include #include #include #include #ifndef FUZZ_STRENGTH #define FUZZ_STRENGTH 2048 #endif #define MACRO_STRGEN(X) #X #define MACRO_STR(X) MACRO_STRGEN(X) constexpr bool time_fuzzes = true; struct static_mapper { static gp::array store; static gp::buddy<> impl; void* allocate(size_t sz) { return impl.allocate(sz); } bool deallocate(void* ptr) { return impl.deallocate(ptr); } }; alignas(2048) gp::array static_mapper::store; gp::buddy<> static_mapper::impl = gp::buddy<>{store.begin().data, store.size()}; struct arraysum_test : public test_scaffold { arraysum_test() { name = __FILE__ ":1"; } virtual int run() { gp::array test; for(auto& elem : test) { elem = 12; } return std::accumulate(test.begin(), test.end(), 0) != 12*test.size(); } }; append_test dummy_sd45uisd3(new arraysum_test{}); struct optional_test : public test_scaffold { optional_test() { name = __FILE__ ":1"; } virtual int run() { int res = 0; { gp::optional test; if(test.has_value()) { res++; } test = 12; if(test.has_value()) { if(test.value()!=12) { res++; } } else { res++; } } { gp::optional test; if(test.has_value()) { res++; } test = std::ifstream("/proc/cpuinfo"); if(!test.has_value()) { res++; } } return res; } }; append_test dummy_mlyusisd3(new optional_test{}); struct buddy_test : public test_scaffold { buddy_test() { name = std::string(__FILE__ "seed_") + std::to_string(seed) + ":3"; rng.seed(seed); } std::mt19937 rng{}; int seed = std::random_device{}(); virtual int run() { int res = 0; gp::repeat(10, [&](){ gp::array store; { gp::buddy(4096)> bud{&*store.begin(), store.size()}; gp::buddy(4096)> dum_bud{store.size()}; gp::buddy inner_bud{2048}; gp::dummy_allocator dummyall; { gp_config::assertion(!dummyall.try_reallocate(nullptr, 0), "reallocation works wut?"); gp_config::assertion(!bud.try_reallocate(nullptr, 0), "reallocation works wut?"); gp_config::assertion(!inner_bud.try_reallocate(nullptr, 0), "reallocation works wut?"); std::set ptr_set; for(int i = 0; i < 2048 / 16; i++) { void* v = inner_bud.allocate(16); gp_config::assertion(!inner_bud.empty(), "allocator should have elements"); if(v == nullptr) throw gp::runtime_error("allocation failed"); ptr_set.insert(v); } bool wut = ptr_set.count(nullptr)!=0 || ptr_set.size()!=(2048/16); if(wut) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__)); if(nullptr != inner_bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected"); for(auto elem : ptr_set) { gp_config::assertion(!inner_bud.empty(), "allocator should have elements"); if(inner_bud.deallocate(elem) == false) { res += 1; } } gp_config::assertion(inner_bud.empty(), "allocator should be empty"); } { gp_config::assertion(!dummyall.try_reallocate(nullptr, 0), "reallocation works wut?"); gp_config::assertion(!bud.try_reallocate(nullptr, 0), "reallocation works wut?"); std::set ptr_set; for(int i = 0; i < 4096 / 16; i++) { void* v = bud.allocate(16); gp_config::assertion(!bud.empty(), "allocator should have elements"); if(v == nullptr) throw gp::runtime_error("allocation failed"); ptr_set.insert(v); } if(ptr_set.count(nullptr)!=0 || ptr_set.size()!=(4096/16)) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__)); if(nullptr != bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected"); for(auto elem : ptr_set) { gp_config::assertion(!bud.empty(), "allocator should have elements"); if(bud.deallocate(elem) == false) { res += 1; } } gp_config::assertion(bud.empty(), "allocator should be empty"); } { std::set ptr_set; for(int i = 0; i < 4096 / 8; i++) { void* v = bud.allocate(8); gp_config::assertion(!bud.empty(), "allocator should have elements"); if(v == nullptr) throw gp::runtime_error("allocation failed"); ptr_set.insert(v); } if(ptr_set.count(nullptr)!=0 || ptr_set.size()!=(4096/8)) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__)); if(nullptr != bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected"); for(auto elem : ptr_set) { gp_config::assertion(!bud.empty(), "allocator should have elements"); if(bud.deallocate(elem) == false) { res += 1; } } gp_config::assertion(bud.empty(), "allocator should be empty"); } { std::set ptr_set; std::vector infill; std::insert_iterator< std::vector > inserter{infill, std::end(infill)}; std::fill_n(inserter, 4096 / 16 / 4, 16); inserter = std::insert_iterator< std::vector >{infill, std::end(infill)}; std::fill_n(inserter, 4096 / 8 / 4, 8); std::shuffle(infill.begin(), infill.end(), rng); for(auto sz : infill) { void* v = bud.allocate(sz); gp_config::assertion(!bud.empty(), "allocator should have elements"); if(v == nullptr) throw gp::runtime_error("allocation failed"); ptr_set.insert(v); } if(ptr_set.count(nullptr)!=0) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__)); gp_config::assertion(!bud.deallocate((char*)store.begin().data + 1), "misaligned deallocation fails"); for(auto elem : ptr_set) { gp_config::assertion(!bud.empty(), "allocator should have elements"); if(bud.deallocate(elem) == false) { res += 1; } } gp_config::assertion(!bud.deallocate(nullptr), "deallocating out of scope returns false"); gp_config::assertion(bud.empty(), "allocator should be empty"); } } }); return res; } }; append_test dummy_654sisd3(new buddy_test{}); struct buddy_fuzz_test : public test_scaffold { buddy_fuzz_test() { name = std::string(__FILE__ "seed_") + std::to_string(seed) + ":4"; rng.seed(seed); } buddy_fuzz_test(size_t _seed) { seed = _seed; name = std::string(__FILE__ "seed_") + std::to_string(seed) + ":4"; rng.seed(seed); } std::mt19937 rng{}; int seed = std::random_device{}(); virtual int run() { int res = 0; alignas(8) gp::array store; gp::buddy(4096)> bud{&*store.begin(), store.size()}; std::vector ptr_set; auto get_random_mem_qt = [&]() -> size_t { return 1+rng()%(store.size()-1); }; auto start = std::chrono::steady_clock::now(); { gp::repeat(FUZZ_STRENGTH, [&](){ void* ptr; auto sz = get_random_mem_qt(); size_t tries = 0; std::shuffle( ptr_set.begin(), ptr_set.end(), rng ); while(!(ptr = bud.allocate(sz))) { void* free_ptr = ptr_set.back(); ptr_set.pop_back(); gp_config::assertion(bud.deallocate(free_ptr), "could not free sample"); gp_config::assertion(++tries <= store.size(), "infinite fuzzing"); } ptr_set.emplace_back(ptr); }); for(auto ptr : ptr_set) { bud.deallocate(ptr); } ptr_set.resize(0); } auto duration = std::chrono::steady_clock::now() - start; start = std::chrono::steady_clock::now(); { size_t acc = 0; gp::repeat(FUZZ_STRENGTH, [&](){ void* ptr; auto sz = get_random_mem_qt(); size_t tries = 0; std::shuffle( ptr_set.begin(), ptr_set.end(), rng ); ptr = malloc(sz); acc+=1; while(acc > 20) { void* free_ptr = ptr_set.back(); free(free_ptr); acc -= 1; ptr_set.pop_back(); gp_config::assertion(++tries <= store.size(), "infinite fuzzing"); } ptr_set.emplace_back(ptr); }); for(auto ptr : ptr_set) { free(ptr); } } auto reference = std::chrono::steady_clock::now() - start; std::cout << "Fuzzing timed at " << std::chrono::duration_cast(duration).count() << "µs for " << FUZZ_STRENGTH << " (reference: " << std::chrono::duration_cast(reference).count() << "µs)" << std::endl; return res; } }; append_test dummy_df987sd3(new buddy_fuzz_test{781017366}); append_test dummy_df4sisd3(new buddy_fuzz_test{}); struct ring_list_test : public test_scaffold { ring_list_test() { name = __FILE__ ":5"; } virtual int run() { int res = 0; alignas(8) gp::array store; using local_allocator = gp::buddy(4096)>; local_allocator bud{&*store.begin(), store.size()}; { using string_ring = gp::ring_list; auto p = new(bud.allocate(sizeof(std::string))) std::string("Hello"); auto orig = new(bud.allocate(sizeof(string_ring::node))) string_ring::node(p); string_ring ring{orig, bud}; ring.insert("World"); auto it = ring.explore(); std::string test = ""; do{ test += *it; ++it; }while(it != ring.explore()); res += (test != "HelloWorld"); } return res; } }; append_test dummy_867fdrgsd3(new ring_list_test{}); struct aggregator_test : public test_scaffold { aggregator_test() { name = std::string(__FILE__ "seed_") + std::to_string(seed) + ":6"; rng.seed(seed); } std::mt19937 rng{}; int seed = std::random_device{}(); virtual int run() { int res = 0; alignas(8) gp::array store; using local_allocator = gp::buddy(4096)>; local_allocator bud{&*store.begin(), store.size()}; alignas(8) gp::array store2; local_allocator bud2{&*store2.begin(), store2.size()}; gp::aggregator allocator{bud}; allocator.insert(bud2); { std::vector ptr_set; auto get_random_mem_qt = [&]() -> size_t { return 1+rng()%(store.size()-1); }; auto start = std::chrono::steady_clock::now(); { gp::repeat(FUZZ_STRENGTH, [&](){ void* ptr; auto sz = get_random_mem_qt(); size_t tries = 0; std::shuffle( ptr_set.begin(), ptr_set.end(), rng ); while(!(ptr = allocator.allocate(sz))) { void* free_ptr = ptr_set.back(); ptr_set.pop_back(); gp_config::assertion(allocator.deallocate(free_ptr), "could not free sample"); gp_config::assertion(++tries <= store.size(), "infinite fuzzing"); } ptr_set.emplace_back(ptr); }); for(auto ptr : ptr_set) { bud.deallocate(ptr); } ptr_set.resize(0); } auto duration = std::chrono::steady_clock::now() - start; } return res; } }; append_test dummy_8ijfsd658(new aggregator_test{});