diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/system/mutex_ut.cpp |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/system/mutex_ut.cpp')
-rw-r--r-- | util/system/mutex_ut.cpp | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/util/system/mutex_ut.cpp b/util/system/mutex_ut.cpp new file mode 100644 index 00000000000..c8d7caafa1a --- /dev/null +++ b/util/system/mutex_ut.cpp @@ -0,0 +1,129 @@ +#include "mutex.h" +#include "atomic.h" + +#include <library/cpp/testing/unittest/registar.h> + +#include <util/thread/pool.h> +#include <util/random/random.h> + +class TMutexTest: public TTestBase { + UNIT_TEST_SUITE(TMutexTest); + UNIT_TEST(TestBasics) + UNIT_TEST(TestFake) + UNIT_TEST(TestRecursive) + UNIT_TEST_SUITE_END(); + + struct TSharedData { + TSharedData() + : sharedCounter(0) + , failed(false) + { + } + + volatile ui32 sharedCounter; + TMutex mutex; + TFakeMutex fakeMutex; + + bool failed; + }; + + class TThreadTask: public IObjectInQueue { + public: + using PFunc = void (TThreadTask::*)(void); + + TThreadTask(PFunc func, TSharedData& data, size_t id) + : Func_(func) + , Data_(data) + , Id_(id) + { + } + + void Process(void*) override { + THolder<TThreadTask> This(this); + + (this->*Func_)(); + } + +#define FAIL_ASSERT(cond) \ + if (!(cond)) { \ + Data_.failed = true; \ + } + void RunBasics() { + Data_.mutex.Acquire(); + + ui32 oldCounter = ui32(Data_.sharedCounter + Id_); + Data_.sharedCounter = oldCounter; + usleep(10 + RandomNumber<ui32>() % 10); + FAIL_ASSERT(Data_.sharedCounter == oldCounter); + + Data_.mutex.Release(); + } + + void RunFakeMutex() { + bool res = Data_.fakeMutex.TryAcquire(); + FAIL_ASSERT(res); + } + + void RunRecursiveMutex() { + for (size_t i = 0; i < Id_ + 1; ++i) { + Data_.mutex.Acquire(); + ++Data_.sharedCounter; + usleep(1); + } + FAIL_ASSERT(Data_.sharedCounter == Id_ + 1); + + bool res = Data_.mutex.TryAcquire(); + FAIL_ASSERT(res); + Data_.mutex.Release(); + + for (size_t i = 0; i < Id_; ++i) { + --Data_.sharedCounter; + Data_.mutex.Release(); + } + FAIL_ASSERT(Data_.sharedCounter == 1); + --Data_.sharedCounter; + Data_.mutex.Release(); + } + +#undef FAIL_ASSERT + + private: + PFunc Func_; + TSharedData& Data_; + size_t Id_; + }; + +private: +#define RUN_CYCLE(what, count) \ + Q_.Start(count); \ + for (size_t i = 0; i < count; ++i) { \ + UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, Data_, i))); \ + } \ + Q_.Stop(); \ + bool b = Data_.failed; \ + Data_.failed = false; \ + UNIT_ASSERT(!b); + + void TestBasics() { + RUN_CYCLE(RunBasics, 5); + + UNIT_ASSERT(Data_.sharedCounter == 10); + Data_.sharedCounter = 0; + } + + void TestFake() { + RUN_CYCLE(RunFakeMutex, 3); + } + + void TestRecursive() { + RUN_CYCLE(RunRecursiveMutex, 4); + } + +#undef RUN_CYCLE + +private: + TSharedData Data_; + TThreadPool Q_; +}; + +UNIT_TEST_SUITE_REGISTRATION(TMutexTest) |