General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

432 lines
11 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. #include "test_scaffold.h"
  2. #include "gp/array.hpp"
  3. #include "gp/allocator/aggregator.hpp"
  4. #include "gp/allocator/buddy.hpp"
  5. #include "gp/allocator/dummy.hpp"
  6. #include "gp/algorithm/repeat.hpp"
  7. #include "gp/ring_list.hpp"
  8. #include <thread>
  9. #include <chrono>
  10. #include <set>
  11. #include <stack>
  12. #include <numeric>
  13. #include <chrono>
  14. #include <random>
  15. #include <iomanip>
  16. #include <iostream>
  17. #include <fstream>
  18. #include <algorithm>
  19. #ifndef FUZZ_STRENGTH
  20. #define FUZZ_STRENGTH 2048
  21. #endif
  22. #define MACRO_STRGEN(X) #X
  23. #define MACRO_STR(X) MACRO_STRGEN(X)
  24. constexpr bool time_fuzzes = true;
  25. struct static_mapper {
  26. static gp::array<char, 4096> store;
  27. static gp::buddy<> impl;
  28. void* allocate(size_t sz) {
  29. return impl.allocate(sz);
  30. }
  31. bool deallocate(void* ptr) {
  32. return impl.deallocate(ptr);
  33. }
  34. };
  35. alignas(2048) gp::array<char, 4096> static_mapper::store;
  36. gp::buddy<> static_mapper::impl = gp::buddy<>{store.begin().data, store.size()};
  37. struct arraysum_test : public test_scaffold {
  38. arraysum_test() {
  39. name = __FILE__ ":1";
  40. }
  41. virtual int run() {
  42. gp::array<uint32_t, 16> test;
  43. for(auto& elem : test)
  44. {
  45. elem = 12;
  46. }
  47. return std::accumulate(test.begin(), test.end(), 0) != 12*test.size();
  48. }
  49. };
  50. append_test dummy_sd45uisd3(new arraysum_test{});
  51. struct optional_test : public test_scaffold {
  52. optional_test() {
  53. name = __FILE__ ":1";
  54. }
  55. virtual int run() {
  56. int res = 0;
  57. {
  58. gp::optional<uint32_t> test;
  59. if(test.has_value())
  60. {
  61. res++;
  62. }
  63. test = 12;
  64. if(test.has_value())
  65. {
  66. if(test.value()!=12)
  67. {
  68. res++;
  69. }
  70. }
  71. else
  72. {
  73. res++;
  74. }
  75. }
  76. {
  77. gp::optional<std::ifstream> test;
  78. if(test.has_value())
  79. {
  80. res++;
  81. }
  82. test = std::ifstream("/proc/cpuinfo");
  83. if(!test.has_value())
  84. {
  85. res++;
  86. }
  87. }
  88. return res;
  89. }
  90. };
  91. append_test dummy_mlyusisd3(new optional_test{});
  92. struct buddy_test : public test_scaffold {
  93. buddy_test() {
  94. name = std::string(__FILE__ "seed_") + std::to_string(seed) + ":3";
  95. rng.seed(seed);
  96. }
  97. std::mt19937 rng{};
  98. int seed = std::random_device{}();
  99. virtual int run() {
  100. int res = 0;
  101. gp::repeat(10, [&](){
  102. gp::array<char, 4096> store;
  103. {
  104. gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)> bud{&*store.begin(), store.size()};
  105. gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)> dum_bud{store.size()};
  106. gp::buddy<static_mapper> inner_bud{2048};
  107. gp::dummy_allocator dummyall;
  108. {
  109. gp_config::assertion(!dummyall.try_reallocate(nullptr, 0), "reallocation works wut?");
  110. gp_config::assertion(!bud.try_reallocate(nullptr, 0), "reallocation works wut?");
  111. gp_config::assertion(!inner_bud.try_reallocate(nullptr, 0), "reallocation works wut?");
  112. std::set<void*> ptr_set;
  113. for(int i = 0; i < 2048 / 16; i++)
  114. {
  115. void* v = inner_bud.allocate(16);
  116. gp_config::assertion(!inner_bud.empty(), "allocator should have elements");
  117. if(v == nullptr) throw gp::runtime_error("allocation failed");
  118. ptr_set.insert(v);
  119. }
  120. bool wut = ptr_set.count(nullptr)!=0 || ptr_set.size()!=(2048/16);
  121. if(wut) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__));
  122. if(nullptr != inner_bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected");
  123. for(auto elem : ptr_set) {
  124. gp_config::assertion(!inner_bud.empty(), "allocator should have elements");
  125. if(inner_bud.deallocate(elem) == false)
  126. {
  127. res += 1;
  128. }
  129. }
  130. gp_config::assertion(inner_bud.empty(), "allocator should be empty");
  131. }
  132. {
  133. gp_config::assertion(!dummyall.try_reallocate(nullptr, 0), "reallocation works wut?");
  134. gp_config::assertion(!bud.try_reallocate(nullptr, 0), "reallocation works wut?");
  135. std::set<void*> ptr_set;
  136. for(int i = 0; i < 4096 / 16; i++)
  137. {
  138. void* v = bud.allocate(16);
  139. gp_config::assertion(!bud.empty(), "allocator should have elements");
  140. if(v == nullptr) throw gp::runtime_error("allocation failed");
  141. ptr_set.insert(v);
  142. }
  143. if(ptr_set.count(nullptr)!=0 || ptr_set.size()!=(4096/16)) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__));
  144. if(nullptr != bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected");
  145. for(auto elem : ptr_set) {
  146. gp_config::assertion(!bud.empty(), "allocator should have elements");
  147. if(bud.deallocate(elem) == false)
  148. {
  149. res += 1;
  150. }
  151. }
  152. gp_config::assertion(bud.empty(), "allocator should be empty");
  153. }
  154. {
  155. std::set<void*> ptr_set;
  156. for(int i = 0; i < 4096 / 8; i++)
  157. {
  158. void* v = bud.allocate(8);
  159. gp_config::assertion(!bud.empty(), "allocator should have elements");
  160. if(v == nullptr) throw gp::runtime_error("allocation failed");
  161. ptr_set.insert(v);
  162. }
  163. if(ptr_set.count(nullptr)!=0 || ptr_set.size()!=(4096/8)) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__));
  164. if(nullptr != bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected");
  165. for(auto elem : ptr_set) {
  166. gp_config::assertion(!bud.empty(), "allocator should have elements");
  167. if(bud.deallocate(elem) == false)
  168. {
  169. res += 1;
  170. }
  171. }
  172. gp_config::assertion(bud.empty(), "allocator should be empty");
  173. }
  174. {
  175. std::set<void*> ptr_set;
  176. std::vector<size_t> infill;
  177. std::insert_iterator< std::vector<size_t> > inserter{infill, std::end(infill)};
  178. std::fill_n(inserter, 4096 / 16 / 4, 16);
  179. inserter = std::insert_iterator< std::vector<size_t> >{infill, std::end(infill)};
  180. std::fill_n(inserter, 4096 / 8 / 4, 8);
  181. std::shuffle(infill.begin(), infill.end(), rng);
  182. for(auto sz : infill)
  183. {
  184. void* v = bud.allocate(sz);
  185. gp_config::assertion(!bud.empty(), "allocator should have elements");
  186. if(v == nullptr) throw gp::runtime_error("allocation failed");
  187. ptr_set.insert(v);
  188. }
  189. if(ptr_set.count(nullptr)!=0) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__));
  190. gp_config::assertion(!bud.deallocate((char*)store.begin().data + 1), "misaligned deallocation fails");
  191. for(auto elem : ptr_set) {
  192. gp_config::assertion(!bud.empty(), "allocator should have elements");
  193. if(bud.deallocate(elem) == false)
  194. {
  195. res += 1;
  196. }
  197. }
  198. gp_config::assertion(!bud.deallocate(nullptr), "deallocating out of scope returns false");
  199. gp_config::assertion(bud.empty(), "allocator should be empty");
  200. }
  201. }
  202. });
  203. return res;
  204. }
  205. };
  206. append_test dummy_654sisd3(new buddy_test{});
  207. struct buddy_fuzz_test : public test_scaffold {
  208. buddy_fuzz_test() {
  209. name = std::string(__FILE__ "seed_") + std::to_string(seed) + ":4";
  210. rng.seed(seed);
  211. }
  212. buddy_fuzz_test(size_t _seed) {
  213. seed = _seed;
  214. name = std::string(__FILE__ "seed_") + std::to_string(seed) + ":4";
  215. rng.seed(seed);
  216. }
  217. std::mt19937 rng{};
  218. int seed = std::random_device{}();
  219. virtual int run() {
  220. int res = 0;
  221. alignas(8) gp::array<char, 4096> store;
  222. gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)> bud{&*store.begin(), store.size()};
  223. std::vector<void*> ptr_set;
  224. auto get_random_mem_qt = [&]() -> size_t {
  225. return 1+rng()%(store.size()-1);
  226. };
  227. auto start = std::chrono::steady_clock::now();
  228. {
  229. gp::repeat(FUZZ_STRENGTH, [&](){
  230. void* ptr;
  231. auto sz = get_random_mem_qt();
  232. size_t tries = 0;
  233. std::shuffle(
  234. ptr_set.begin(),
  235. ptr_set.end(),
  236. rng
  237. );
  238. while(!(ptr = bud.allocate(sz)))
  239. {
  240. void* free_ptr = ptr_set.back();
  241. ptr_set.pop_back();
  242. gp_config::assertion(bud.deallocate(free_ptr), "could not free sample");
  243. gp_config::assertion(++tries <= store.size(), "infinite fuzzing");
  244. }
  245. ptr_set.emplace_back(ptr);
  246. });
  247. for(auto ptr : ptr_set)
  248. {
  249. bud.deallocate(ptr);
  250. }
  251. ptr_set.resize(0);
  252. }
  253. auto duration = std::chrono::steady_clock::now() - start;
  254. start = std::chrono::steady_clock::now();
  255. {
  256. size_t acc = 0;
  257. gp::repeat(FUZZ_STRENGTH, [&](){
  258. void* ptr;
  259. auto sz = get_random_mem_qt();
  260. size_t tries = 0;
  261. std::shuffle(
  262. ptr_set.begin(),
  263. ptr_set.end(),
  264. rng
  265. );
  266. ptr = malloc(sz);
  267. acc+=1;
  268. while(acc > 20)
  269. {
  270. void* free_ptr = ptr_set.back();
  271. free(free_ptr);
  272. acc -= 1;
  273. ptr_set.pop_back();
  274. gp_config::assertion(++tries <= store.size(), "infinite fuzzing");
  275. }
  276. ptr_set.emplace_back(ptr);
  277. });
  278. for(auto ptr : ptr_set)
  279. {
  280. free(ptr);
  281. }
  282. }
  283. auto reference = std::chrono::steady_clock::now() - start;
  284. std::cout
  285. << "Fuzzing timed at "
  286. << std::chrono::duration_cast<std::chrono::microseconds>(duration).count()
  287. << "µs for "
  288. << FUZZ_STRENGTH
  289. << " (reference: "
  290. << std::chrono::duration_cast<std::chrono::microseconds>(reference).count()
  291. << "µs)"
  292. << std::endl;
  293. return res;
  294. }
  295. };
  296. append_test dummy_df987sd3(new buddy_fuzz_test{781017366});
  297. append_test dummy_df4sisd3(new buddy_fuzz_test{});
  298. struct ring_list_test : public test_scaffold {
  299. ring_list_test() {
  300. name = __FILE__ ":5";
  301. }
  302. virtual int run() {
  303. int res = 0;
  304. alignas(8) gp::array<char, 4096> store;
  305. using local_allocator = gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)>;
  306. local_allocator bud{&*store.begin(), store.size()};
  307. {
  308. using string_ring = gp::ring_list<std::string, local_allocator, false>;
  309. auto p = new(bud.allocate(sizeof(std::string))) std::string("Hello");
  310. auto orig = new(bud.allocate(sizeof(string_ring::node))) string_ring::node(p);
  311. string_ring ring{orig, bud};
  312. ring.insert("World");
  313. auto it = ring.explore();
  314. std::string test = "";
  315. do{
  316. test += *it;
  317. ++it;
  318. }while(it != ring.explore());
  319. res += (test != "HelloWorld");
  320. }
  321. return res;
  322. }
  323. };
  324. append_test dummy_867fdrgsd3(new ring_list_test{});
  325. struct aggregator_test : public test_scaffold {
  326. aggregator_test() {
  327. name = std::string(__FILE__ "seed_") + std::to_string(seed) + ":6";
  328. rng.seed(seed);
  329. }
  330. std::mt19937 rng{};
  331. int seed = std::random_device{}();
  332. virtual int run() {
  333. int res = 0;
  334. alignas(8) gp::array<char, 4096> store;
  335. using local_allocator = gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)>;
  336. local_allocator bud{&*store.begin(), store.size()};
  337. alignas(8) gp::array<char, 4096> store2;
  338. local_allocator bud2{&*store2.begin(), store2.size()};
  339. gp::aggregator allocator{bud};
  340. allocator.insert(bud2);
  341. {
  342. std::vector<void*> ptr_set;
  343. auto get_random_mem_qt = [&]() -> size_t {
  344. return 1+rng()%(store.size()-1);
  345. };
  346. auto start = std::chrono::steady_clock::now();
  347. {
  348. gp::repeat(FUZZ_STRENGTH, [&](){
  349. void* ptr;
  350. auto sz = get_random_mem_qt();
  351. size_t tries = 0;
  352. std::shuffle(
  353. ptr_set.begin(),
  354. ptr_set.end(),
  355. rng
  356. );
  357. while(!(ptr = allocator.allocate(sz)))
  358. {
  359. void* free_ptr = ptr_set.back();
  360. ptr_set.pop_back();
  361. gp_config::assertion(allocator.deallocate(free_ptr), "could not free sample");
  362. gp_config::assertion(++tries <= store.size(), "infinite fuzzing");
  363. }
  364. ptr_set.emplace_back(ptr);
  365. });
  366. for(auto ptr : ptr_set)
  367. {
  368. bud.deallocate(ptr);
  369. }
  370. ptr_set.resize(0);
  371. }
  372. auto duration = std::chrono::steady_clock::now() - start;
  373. }
  374. return res;
  375. }
  376. };
  377. append_test dummy_8ijfsd658(new aggregator_test{});