reopen_ut.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #include "backend.h"
  2. #include "reopen.h"
  3. #include <exception>
  4. #include <util/generic/string.h>
  5. #include <util/generic/array_ref.h>
  6. #include <library/cpp/testing/unittest/registar.h>
  7. #include <library/cpp/testing/unittest/tests_data.h>
  8. #include <future>
  9. #include <atomic>
  10. #include <barrier>
  11. namespace {
  12. struct TMockLogBackend : public TLogBackend {
  13. void WriteData(const TLogRecord& rec) override {
  14. BytesWritten.fetch_add(rec.Len);
  15. }
  16. void ReopenLog() override {
  17. NumReopens.fetch_add(1);
  18. }
  19. std::atomic<ui64> BytesWritten{0};
  20. std::atomic<ui64> NumReopens{0};
  21. };
  22. void WriteData(TReopenLogBackend& log, const TString& data) {
  23. log.WriteData(TLogRecord(ELogPriority::TLOG_INFO, data.data(), data.size()));
  24. }
  25. }
  26. Y_UNIT_TEST_SUITE(ReopenLogSuite) {
  27. Y_UNIT_TEST(TestSimple) {
  28. constexpr ui64 limit = 5;
  29. const auto testData = {"test", "dshkafhuadshfiasuh", "log", "data"};
  30. constexpr ui64 expectedReopens = 2; // considering the limit, the first reopen after the second string and one more at the end
  31. auto mockHolder = MakeHolder<TMockLogBackend>();
  32. auto& mock = *mockHolder;
  33. TReopenLogBackend log(std::move(mockHolder), limit);
  34. ui64 expectedWritten = 0;
  35. for (const TString str : testData) {
  36. WriteData(log, str);
  37. expectedWritten += str.size();
  38. }
  39. UNIT_ASSERT(mock.BytesWritten.load() == expectedWritten);
  40. UNIT_ASSERT(mock.NumReopens.load() == expectedReopens);
  41. }
  42. Y_UNIT_TEST(TestSingleThreaded) {
  43. constexpr ui64 limit = 1_KB;
  44. constexpr ui64 numLogs = 123;
  45. constexpr ui64 logSize = 1_KB / 4;
  46. static_assert((limit / logSize) * logSize == limit); // should be divisible for this test
  47. constexpr ui64 expectedWritten = numLogs * logSize;
  48. constexpr ui64 expectedReopens = expectedWritten / limit;
  49. auto mockHolder = MakeHolder<TMockLogBackend>();
  50. auto& mock = *mockHolder;
  51. TReopenLogBackend log(std::move(mockHolder), limit);
  52. for (ui64 i = 0; i < numLogs; ++i) {
  53. WriteData(log, TString(logSize, 'a'));
  54. }
  55. UNIT_ASSERT(mock.BytesWritten.load() == expectedWritten);
  56. UNIT_ASSERT(mock.NumReopens.load() == expectedReopens);
  57. }
  58. Y_UNIT_TEST(TestMultiThreaded) {
  59. constexpr ui64 limit = 1_KB;
  60. constexpr ui64 numLogsPerThread = 123;
  61. constexpr ui64 numThreads = 12;
  62. constexpr ui64 logSize = 1_KB / 4;
  63. static_assert((limit / logSize) * logSize == limit); // should be divisible for this test
  64. constexpr ui64 expectedWritten = numLogsPerThread * numThreads * logSize;
  65. // can't guarantee consistent number of reopens every N bytes in multithreaded setting
  66. constexpr ui64 minExpectedReopens = limit / logSize;
  67. constexpr ui64 maxExpectedReopens = expectedWritten / limit;
  68. auto mockHolder = MakeHolder<TMockLogBackend>();
  69. auto& mock = *mockHolder;
  70. TReopenLogBackend log(std::move(mockHolder), limit);
  71. std::barrier barrier(numThreads);
  72. const auto job = [&]() {
  73. barrier.arrive_and_wait();
  74. for (ui64 i = 0; i < numLogsPerThread; ++i) {
  75. WriteData(log, TString(logSize, 'a'));
  76. }
  77. };
  78. std::vector<std::future<void>> jobs;
  79. for (ui64 i = 0; i < numThreads; ++i) {
  80. jobs.emplace_back(std::async(std::launch::async, job));
  81. }
  82. for (auto& res : jobs) {
  83. res.wait();
  84. }
  85. UNIT_ASSERT(mock.BytesWritten.load() == expectedWritten);
  86. UNIT_ASSERT(mock.NumReopens.load() >= minExpectedReopens);
  87. UNIT_ASSERT(mock.NumReopens.load() <= maxExpectedReopens);
  88. }
  89. Y_UNIT_TEST(TestZeroThrows) {
  90. UNIT_ASSERT_EXCEPTION(TReopenLogBackend(MakeHolder<TMockLogBackend>(), 0), std::exception);
  91. }
  92. }