mutex_ut.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "mutex.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/thread/pool.h>
  4. #include <util/random/random.h>
  5. class TMutexTest: public TTestBase {
  6. UNIT_TEST_SUITE(TMutexTest);
  7. UNIT_TEST(TestBasics)
  8. UNIT_TEST(TestFake)
  9. UNIT_TEST(TestRecursive)
  10. UNIT_TEST_SUITE_END();
  11. struct TSharedData {
  12. TSharedData()
  13. : sharedCounter(0)
  14. , failed(false)
  15. {
  16. }
  17. volatile ui32 sharedCounter;
  18. TMutex mutex;
  19. TFakeMutex fakeMutex;
  20. bool failed;
  21. };
  22. class TThreadTask: public IObjectInQueue {
  23. public:
  24. using PFunc = void (TThreadTask::*)(void);
  25. TThreadTask(PFunc func, TSharedData& data, size_t id)
  26. : Func_(func)
  27. , Data_(data)
  28. , Id_(id)
  29. {
  30. }
  31. void Process(void*) override {
  32. THolder<TThreadTask> This(this);
  33. (this->*Func_)();
  34. }
  35. #define FAIL_ASSERT(cond) \
  36. if (!(cond)) { \
  37. Data_.failed = true; \
  38. }
  39. void RunBasics() {
  40. Data_.mutex.Acquire();
  41. ui32 oldCounter = ui32(Data_.sharedCounter + Id_);
  42. Data_.sharedCounter = oldCounter;
  43. usleep(10 + RandomNumber<ui32>() % 10);
  44. FAIL_ASSERT(Data_.sharedCounter == oldCounter);
  45. Data_.mutex.Release();
  46. }
  47. void RunFakeMutex() {
  48. bool res = Data_.fakeMutex.TryAcquire();
  49. FAIL_ASSERT(res);
  50. }
  51. void RunRecursiveMutex() {
  52. for (size_t i = 0; i < Id_ + 1; ++i) {
  53. Data_.mutex.Acquire();
  54. ++Data_.sharedCounter;
  55. usleep(1);
  56. }
  57. FAIL_ASSERT(Data_.sharedCounter == Id_ + 1);
  58. bool res = Data_.mutex.TryAcquire();
  59. FAIL_ASSERT(res);
  60. Data_.mutex.Release();
  61. for (size_t i = 0; i < Id_; ++i) {
  62. --Data_.sharedCounter;
  63. Data_.mutex.Release();
  64. }
  65. FAIL_ASSERT(Data_.sharedCounter == 1);
  66. --Data_.sharedCounter;
  67. Data_.mutex.Release();
  68. }
  69. #undef FAIL_ASSERT
  70. private:
  71. PFunc Func_;
  72. TSharedData& Data_;
  73. size_t Id_;
  74. };
  75. private:
  76. #define RUN_CYCLE(what, count) \
  77. Q_.Start(count); \
  78. for (size_t i = 0; i < count; ++i) { \
  79. UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, Data_, i))); \
  80. } \
  81. Q_.Stop(); \
  82. bool b = Data_.failed; \
  83. Data_.failed = false; \
  84. UNIT_ASSERT(!b);
  85. void TestBasics() {
  86. RUN_CYCLE(RunBasics, 5);
  87. UNIT_ASSERT(Data_.sharedCounter == 10);
  88. Data_.sharedCounter = 0;
  89. }
  90. void TestFake() {
  91. RUN_CYCLE(RunFakeMutex, 3);
  92. }
  93. void TestRecursive() {
  94. RUN_CYCLE(RunRecursiveMutex, 4);
  95. }
  96. #undef RUN_CYCLE
  97. private:
  98. TSharedData Data_;
  99. TThreadPool Q_;
  100. };
  101. UNIT_TEST_SUITE_REGISTRATION(TMutexTest)