General Purpose library for Freestanding C++ and POSIX systems
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 

432 строки
11 KiB

#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 <thread>
#include <chrono>
#include <set>
#include <stack>
#include <numeric>
#include <chrono>
#include <random>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <algorithm>
#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<char, 4096> 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<char, 4096> 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<uint32_t, 16> 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<uint32_t> test;
if(test.has_value())
{
res++;
}
test = 12;
if(test.has_value())
{
if(test.value()!=12)
{
res++;
}
}
else
{
res++;
}
}
{
gp::optional<std::ifstream> 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<char, 4096> store;
{
gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)> bud{&*store.begin(), store.size()};
gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)> dum_bud{store.size()};
gp::buddy<static_mapper> 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<void*> 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<void*> 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<void*> 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<void*> ptr_set;
std::vector<size_t> infill;
std::insert_iterator< std::vector<size_t> > inserter{infill, std::end(infill)};
std::fill_n(inserter, 4096 / 16 / 4, 16);
inserter = std::insert_iterator< std::vector<size_t> >{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<char, 4096> store;
gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)> bud{&*store.begin(), store.size()};
std::vector<void*> 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<std::chrono::microseconds>(duration).count()
<< "µs for "
<< FUZZ_STRENGTH
<< " (reference: "
<< std::chrono::duration_cast<std::chrono::microseconds>(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<char, 4096> store;
using local_allocator = gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)>;
local_allocator bud{&*store.begin(), store.size()};
{
using string_ring = gp::ring_list<std::string, local_allocator, false>;
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<char, 4096> store;
using local_allocator = gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)>;
local_allocator bud{&*store.begin(), store.size()};
alignas(8) gp::array<char, 4096> store2;
local_allocator bud2{&*store2.begin(), store2.size()};
gp::aggregator allocator{bud};
allocator.insert(bud2);
{
std::vector<void*> 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{});