#include #include "../../../global/process_watchdog.h" #include "../../../global/ipc_named_mutex.h" #include #include #include #if defined(_WIN32) && defined(_UNICODE) extern "C" int wmain(int argc, wchar_t* argv[]) #else extern "C" int main(int argc, char* argv[]) #endif { CProcessWatchdog watchdog; ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } TEST(NamedMutexTest, Construction) { ipc::named_mutex mtx("HELLO"); EXPECT_NE(mtx.native_handle(), nullptr); } TEST(NamedMutexTest, CritSectSyncManualLock) { // Counter function check for correct counter value. // The checking is manipulated by the bEnable flag. When disabled, no sync will be done and the check will fail. When enabled, // sync will be done and the check will succeed. int32_t iCnt = 0; std::atomic_bool bSuccess = true; std::atomic_bool bEnable = false; auto fn = [&]() { ipc::named_mutex mtx("HELLO"); if (bEnable) mtx.lock(); bSuccess = bSuccess && (iCnt == 0); iCnt++; std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 100)); iCnt--; bSuccess = bSuccess && (iCnt == 0); if (bEnable) mtx.unlock(); }; // Test no sync std::thread rgThreads[100]; for (std::thread& rthread : rgThreads) rthread = std::thread(fn); for (std::thread& rthread : rgThreads) rthread.join(); EXPECT_FALSE(bSuccess); // Test sync iCnt = 0; bSuccess = true; bEnable = true; for (std::thread& rthread : rgThreads) rthread = std::thread(fn); for (std::thread& rthread : rgThreads) rthread.join(); EXPECT_TRUE(bSuccess); } TEST(NamedMutexTest, CritSectSyncAutoLock) { // Counter function check for correct counter value. int32_t iCnt = 0; std::atomic_bool bSuccess = true; auto fn = [&]() { ipc::named_mutex mtx("HELLO"); std::unique_lock lock(mtx); bSuccess = bSuccess && (iCnt == 0); iCnt++; std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 100)); iCnt--; bSuccess = bSuccess && (iCnt == 0); }; // Test sync std::thread rgThreads[100]; for (std::thread& rthread : rgThreads) rthread = std::thread(fn); for (std::thread& rthread : rgThreads) rthread.join(); EXPECT_TRUE(bSuccess); } TEST(NamedMutexTest, TryLock) { std::atomic_bool bRunning = false; auto fn = [&]() { ipc::named_mutex mtx("HELLO"); mtx.lock(); while (bRunning) std::this_thread::sleep_for(std::chrono::milliseconds(1)); mtx.unlock(); }; bRunning = true; std::thread thread(fn); std::this_thread::sleep_for(std::chrono::milliseconds(250)); // Try locking; doesn't work since thread still locks. ipc::named_mutex mtx2("HELLO"); EXPECT_FALSE(mtx2.try_lock()); bRunning = false; thread.join(); // Try locking; this works. Thread has ended. EXPECT_TRUE(mtx2.try_lock()); mtx2.unlock(); } TEST(NamedMutexTest, Naming) { ipc::named_mutex mtx1("HELLO"); EXPECT_FALSE(mtx1.name().empty()); ipc::named_mutex mtx2(nullptr); EXPECT_FALSE(mtx2.name().empty()); }