blob: a9c5c45123a168c39f7be0f726e35c5569f76d06 (
plain) (
tree)
|
|
#include "mutex.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)
|