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.

533 lines
13 KiB

пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
  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. #include "gp/vfs/vfs.hpp"
  23. #ifndef FUZZ_STRENGTH
  24. #define FUZZ_STRENGTH 2048
  25. #endif
  26. #define MACRO_STRGEN(X) #X
  27. #define MACRO_STR(X) MACRO_STRGEN(X)
  28. constexpr bool time_fuzzes = true;
  29. struct arraysum_test : public test_scaffold {
  30. arraysum_test() {
  31. name = __FILE__ ":1";
  32. }
  33. virtual int run() {
  34. gp::array<uint32_t, 16> test;
  35. for(auto& elem : test)
  36. {
  37. elem = 12;
  38. }
  39. return std::accumulate(test.begin(), test.end(), 0) != 12*test.size();
  40. }
  41. };
  42. append_test dummy_sd45uisd3(new arraysum_test{});
  43. struct optional_test : public test_scaffold {
  44. optional_test() {
  45. name = __FILE__ ":1";
  46. }
  47. virtual int run() {
  48. int res = 0;
  49. {
  50. gp::optional<uint32_t> test;
  51. if(test.has_value())
  52. {
  53. res++;
  54. }
  55. test = 12;
  56. if(test.has_value())
  57. {
  58. if(test.value()!=12)
  59. {
  60. res++;
  61. }
  62. }
  63. else
  64. {
  65. res++;
  66. }
  67. }
  68. {
  69. gp::optional<std::ifstream> test;
  70. if(test.has_value())
  71. {
  72. res++;
  73. }
  74. test = std::ifstream("/proc/cpuinfo");
  75. if(!test.has_value())
  76. {
  77. res++;
  78. }
  79. }
  80. return res;
  81. }
  82. };
  83. append_test dummy_mlyusisd3(new optional_test{});
  84. struct buddy_test : public test_scaffold {
  85. buddy_test() {
  86. name = std::string(__FILE__ "seed_") + std::to_string(seed) + ":3";
  87. rng.seed(seed);
  88. }
  89. std::mt19937 rng{};
  90. int seed = std::random_device{}();
  91. virtual int run() {
  92. int res = 0;
  93. gp::repeat(10, [&](){
  94. gp::array<char, 4096> store;
  95. {
  96. gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)> bud{&*store.begin(), store.size()};
  97. gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)> dum_bud{store.size()};
  98. gp::buddy<static_mapper> inner_bud{2048};
  99. gp::dummy_allocator dummyall;
  100. {
  101. gp_config::assertion(!dummyall.try_reallocate(nullptr, 0), "reallocation works wut?");
  102. gp_config::assertion(!bud.try_reallocate(nullptr, 0), "reallocation works wut?");
  103. gp_config::assertion(!inner_bud.try_reallocate(nullptr, 0), "reallocation works wut?");
  104. std::set<void*> ptr_set;
  105. for(int i = 0; i < 2048 / 16; i++)
  106. {
  107. void* v = inner_bud.allocate(16);
  108. gp_config::assertion(!inner_bud.empty(), "allocator should have elements");
  109. if(v == nullptr) throw gp::runtime_error("allocation failed");
  110. ptr_set.insert(v);
  111. }
  112. bool wut = ptr_set.count(nullptr)!=0 || ptr_set.size()!=(2048/16);
  113. if(wut) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__));
  114. if(nullptr != inner_bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected");
  115. for(auto elem : ptr_set) {
  116. gp_config::assertion(!inner_bud.empty(), "allocator should have elements");
  117. if(inner_bud.deallocate(elem) == false)
  118. {
  119. res += 1;
  120. }
  121. }
  122. gp_config::assertion(inner_bud.empty(), "allocator should be empty");
  123. }
  124. {
  125. gp_config::assertion(!dummyall.try_reallocate(nullptr, 0), "reallocation works wut?");
  126. gp_config::assertion(!bud.try_reallocate(nullptr, 0), "reallocation works wut?");
  127. std::set<void*> ptr_set;
  128. for(int i = 0; i < 4096 / 16; i++)
  129. {
  130. void* v = bud.allocate(16);
  131. gp_config::assertion(!bud.empty(), "allocator should have elements");
  132. if(v == nullptr) throw gp::runtime_error("allocation failed");
  133. ptr_set.insert(v);
  134. }
  135. if(ptr_set.count(nullptr)!=0 || ptr_set.size()!=(4096/16)) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__));
  136. if(nullptr != bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected");
  137. for(auto elem : ptr_set) {
  138. gp_config::assertion(!bud.empty(), "allocator should have elements");
  139. if(bud.deallocate(elem) == false)
  140. {
  141. res += 1;
  142. }
  143. }
  144. gp_config::assertion(bud.empty(), "allocator should be empty");
  145. }
  146. {
  147. std::set<void*> ptr_set;
  148. for(int i = 0; i < 4096 / 8; i++)
  149. {
  150. void* v = bud.allocate(8);
  151. gp_config::assertion(!bud.empty(), "allocator should have elements");
  152. if(v == nullptr) throw gp::runtime_error("allocation failed");
  153. ptr_set.insert(v);
  154. }
  155. if(ptr_set.count(nullptr)!=0 || ptr_set.size()!=(4096/8)) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__));
  156. if(nullptr != bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected");
  157. for(auto elem : ptr_set) {
  158. gp_config::assertion(!bud.empty(), "allocator should have elements");
  159. if(bud.deallocate(elem) == false)
  160. {
  161. res += 1;
  162. }
  163. }
  164. gp_config::assertion(bud.empty(), "allocator should be empty");
  165. }
  166. {
  167. std::set<void*> ptr_set;
  168. std::vector<size_t> infill;
  169. std::insert_iterator< std::vector<size_t> > inserter{infill, std::end(infill)};
  170. std::fill_n(inserter, 4096 / 16 / 4, 16);
  171. inserter = std::insert_iterator< std::vector<size_t> >{infill, std::end(infill)};
  172. std::fill_n(inserter, 4096 / 8 / 4, 8);
  173. std::shuffle(infill.begin(), infill.end(), rng);
  174. for(auto sz : infill)
  175. {
  176. void* v = bud.allocate(sz);
  177. gp_config::assertion(!bud.empty(), "allocator should have elements");
  178. if(v == nullptr) throw gp::runtime_error("allocation failed");
  179. ptr_set.insert(v);
  180. }
  181. if(ptr_set.count(nullptr)!=0) throw gp::runtime_error("some allocations failed line: " MACRO_STR(__LINE__));
  182. gp_config::assertion(!bud.deallocate((char*)store.begin().data + 1), "misaligned deallocation fails");
  183. for(auto elem : ptr_set) {
  184. gp_config::assertion(!bud.empty(), "allocator should have elements");
  185. if(bud.deallocate(elem) == false)
  186. {
  187. res += 1;
  188. }
  189. }
  190. gp_config::assertion(!bud.deallocate(nullptr), "deallocating out of scope returns false");
  191. gp_config::assertion(bud.empty(), "allocator should be empty");
  192. }
  193. }
  194. });
  195. return res;
  196. }
  197. };
  198. append_test dummy_654sisd3(new buddy_test{});
  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{});