A C++ library for logging very fast and without allocating.
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.

138 lines
3.2 KiB

преди 2 години
преди 2 години
преди 2 години
  1. #include <thread>
  2. #include "catch2/catch_all.hpp"
  3. #include "../LibSnugLog/include/disruptor.h"
  4. struct strategy {
  5. static constexpr overflow_response_t on_overflow = overflow_response_t::must_wait;
  6. void wait() {}
  7. };
  8. TEST_CASE("Disruptor works sequentially") {
  9. std::array<char, 8192> buffer{};
  10. disruptor<strategy> v{buffer.data(), buffer.size()};
  11. SECTION("117") {
  12. auto W = v.reserve_write(100);
  13. v[W.start] = 117;
  14. v.conclude_write(W);
  15. auto R = v.reserve_read();
  16. REQUIRE(v[R.start]== 117);
  17. v.conclude_read(R);
  18. }
  19. SECTION("12") {
  20. {
  21. auto W = v.reserve_write(6);
  22. v[W.start] = 12;
  23. v.conclude_write(W);
  24. auto R = v.reserve_read();
  25. REQUIRE(v[R.start]== 12);
  26. v.conclude_read(R);
  27. }
  28. {
  29. auto W = v.reserve_write(6);
  30. v[W.start] = 8;
  31. v.conclude_write(W);
  32. auto R = v.reserve_read();
  33. REQUIRE(v[R.start]== 8);
  34. v.conclude_read(R);
  35. }
  36. }
  37. SECTION("Disruptor loop around") {
  38. std::multiset<char> mset;
  39. for(int i = 0; i != 255; i++) {
  40. auto W = v.reserve_write(100);
  41. v[W.start] = (char)i;
  42. for(size_t idx = W.start; idx != W.end; idx = (idx+1)%v.size()) {
  43. v[idx] = (char)i;
  44. }
  45. v.conclude_write(W);
  46. auto R = v.reserve_read();
  47. for(size_t idx = R.start; idx != R.end; idx = (idx+1)%v.size()) {
  48. mset.insert(v[idx]);
  49. }
  50. v.conclude_read(R);
  51. }
  52. for(int i = 0; i != 255; i++) {
  53. REQUIRE(mset.count((char)i) == 100);
  54. }
  55. }
  56. SECTION("Disruptor concurrent odd vs even") {
  57. std::atomic<bool> trigger = false;
  58. std::multiset<char> mset;
  59. std::stringstream continuity;
  60. int acc = 0;
  61. for(int i = 0; i<= 255; i++) {
  62. acc+=i;
  63. }
  64. std::thread reader([&](){
  65. int cnt = 0;
  66. while (cnt != acc) {
  67. auto R = v.reserve_read();
  68. for (size_t idx = R.start; idx != R.end; idx = (idx + 1) % v.size()) {
  69. mset.insert(v[idx]);
  70. continuity << (char)v[idx];
  71. }
  72. v.conclude_read(R);
  73. cnt += (R.end > R.start) * (R.end - R.start)
  74. + (R.end < R.start) * (v.size() - R.start + R.end);
  75. }
  76. });
  77. std::thread even([&]() {
  78. while(!trigger.load());
  79. for (int i = 2; i <= 255; i += 2) {
  80. auto W = v.reserve_write(i);
  81. v[W.start] = (char) i;
  82. for (size_t idx = W.start; idx != W.end; idx = (idx + 1) % v.size()) {
  83. v[idx] = (char) i;
  84. }
  85. v.conclude_write(W);
  86. }
  87. });
  88. std::thread odd([&]() {
  89. while(!trigger.load());
  90. for (int i = 1; i <= 255; i += 2) {
  91. auto W = v.reserve_write(i);
  92. v[W.start] = (char) i;
  93. for (size_t idx = W.start; idx != W.end; idx = (idx + 1) % v.size()) {
  94. v[idx] = (char) i;
  95. }
  96. v.conclude_write(W);
  97. }
  98. });
  99. // byte received count test
  100. trigger.store(true);
  101. reader.join(); even.join(); odd.join();
  102. for(int i = 1; i <= 255; i++) {
  103. REQUIRE(mset.count((char)i) == i);
  104. }
  105. // Continuity tests
  106. int changes = 0;
  107. auto str = continuity.str();
  108. char current = *str.begin();
  109. auto it = str.begin();
  110. for(;it != str.end();) {
  111. while(it != str.end() && *it == current) {++it;}
  112. changes += 1;
  113. current = *it;
  114. }
  115. REQUIRE(changes == 255);
  116. }
  117. }
  118. TEST_CASE("Fails if buffer too small") {
  119. REQUIRE_THROWS_AS(disruptor<OverflowWait>(nullptr, page_size), disruptor_exception);
  120. }
  121. TEST_CASE("Fails if buffer size is 0") {
  122. REQUIRE_THROWS_AS(disruptor<OverflowWait>(nullptr, 0), disruptor_exception);
  123. }