General Purpose library for Freestanding C++ and POSIX systems
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

532 linhas
14 KiB

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