diff --git a/tests/concurrent/ConditionVariableIntegrationTest.cpp b/tests/concurrent/ConditionVariableIntegrationTest.cpp index b8d82a92..ad74b749 100644 --- a/tests/concurrent/ConditionVariableIntegrationTest.cpp +++ b/tests/concurrent/ConditionVariableIntegrationTest.cpp @@ -5,196 +5,199 @@ class ConditionVariable : public ::testing::Test, public TestUtil { public: + ~ConditionVariable() { + delete variable; + } PIMutex m; - PIConditionVariable* variable; + PIConditionVariable* variable; protected: - void SetUp() override { - variable = new PIConditionVariable(); - adapterFunctionDefault = [&](){ - m.lock(); - variable->wait(m); - m.unlock(); - }; - } + void SetUp() override { + variable = new PIConditionVariable(); + adapterFunctionDefault = [&](){ + m.lock(); + variable->wait(m); + m.unlock(); + }; + } }; TEST_F(ConditionVariable, wait_is_block) { - createThread(); - ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); + createThread(); + ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); } TEST_F(ConditionVariable, wait_is_block_when_notifyOne_before_wait) { - variable->notifyOne(); - createThread(); - ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); + variable->notifyOne(); + createThread(); + ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); } TEST_F(ConditionVariable, wait_is_block_when_notifyAll_before_wait) { - variable->notifyAll(); - createThread(); - ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); + variable->notifyAll(); + createThread(); + ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); } TEST_F(ConditionVariable, wait_is_unblock_when_notifyOne_after_wait) { - createThread(); - variable->notifyOne(); - ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); + createThread(); + variable->notifyOne(); + ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); } TEST_F(ConditionVariable, wait_is_unblock_when_notifyAll_after_wait) { - PIVector threads; + PIVector threads; - for (int i = 0; i < THREAD_COUNT; ++i) { - threads.push_back(new PIThread([=](){ adapterFunctionDefault(); })); - } + for (int i = 0; i < THREAD_COUNT; ++i) { + threads.push_back(new PIThread([=](){ adapterFunctionDefault(); })); + } - piForeach(PIThread* thread, threads) thread->startOnce(); - piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); - variable->notifyAll(); - PITimeMeasurer measurer; - piForeach(PIThread* thread, threads) { - int timeout = WAIT_THREAD_TIME_MS * THREAD_COUNT - (int)measurer.elapsed_m(); - thread->waitForFinish(timeout > 0 ? timeout : 0); - } - for (size_t i = 0; i < threads.size(); ++i) EXPECT_FALSE(threads[i]->isRunning()) << "Thread " << i << " still running"; - piForeach(PIThread* thread, threads) delete thread; + piForeach(PIThread* thread, threads) thread->startOnce(); + piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); + variable->notifyAll(); + PITimeMeasurer measurer; + piForeach(PIThread* thread, threads) { + int timeout = WAIT_THREAD_TIME_MS * THREAD_COUNT - (int)measurer.elapsed_m(); + thread->waitForFinish(timeout > 0 ? timeout : 0); + } + for (size_t i = 0; i < threads.size(); ++i) EXPECT_FALSE(threads[i]->isRunning()) << "Thread " << i << " still running"; + piForeach(PIThread* thread, threads) delete thread; } TEST_F(ConditionVariable, wait_is_one_unblock_when_notifyOne) { - PIVector threads; + PIVector threads; - for (int i = 0; i < THREAD_COUNT; ++i) { - threads.push_back(new PIThread(adapterFunctionDefault)); - } + for (int i = 0; i < THREAD_COUNT; ++i) { + threads.push_back(new PIThread(adapterFunctionDefault)); + } - piForeach(PIThread* thread, threads) thread->startOnce(); - piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); - variable->notifyOne(); - piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); - int runningThreadCount = 0; - piForeach(PIThread* thread, threads) if (thread->isRunning()) runningThreadCount++; - ASSERT_EQ(runningThreadCount, THREAD_COUNT - 1); + piForeach(PIThread* thread, threads) thread->startOnce(); + piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); + variable->notifyOne(); + piMSleep(WAIT_THREAD_TIME_MS * THREAD_COUNT); + int runningThreadCount = 0; + piForeach(PIThread* thread, threads) if (thread->isRunning()) runningThreadCount++; + ASSERT_EQ(runningThreadCount, THREAD_COUNT - 1); } TEST_F(ConditionVariable, wait_is_protected_unblock_when_notifyOne) { - createThread([&](){ - m.lock(); - variable->wait(m); - piMSleep(2 * WAIT_THREAD_TIME_MS); - // Missing unlock - }); - variable->notifyOne(); - msleep(WAIT_THREAD_TIME_MS); - ASSERT_FALSE(m.tryLock()); + createThread([&](){ + m.lock(); + variable->wait(m); + piMSleep(2 * WAIT_THREAD_TIME_MS); + // Missing unlock + }); + variable->notifyOne(); + msleep(WAIT_THREAD_TIME_MS); + ASSERT_FALSE(m.tryLock()); } TEST_F(ConditionVariable, wait_condition_is_block) { - createThread([&](){ - m.lock(); - variable->wait(m, [](){ return false; }); - m.unlock(); - }); - ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); + createThread([&](){ + m.lock(); + variable->wait(m, [](){ return false; }); + m.unlock(); + }); + ASSERT_FALSE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); } TEST_F(ConditionVariable, wait_condition_is_check_condition_before_block) { - bool isConditionChecked = false; - createThread([&](){ - m.lock(); - variable->wait(m, [&](){ - isConditionChecked = true; - return false; - }); - m.unlock(); - }); - m.lock(); - ASSERT_TRUE(isConditionChecked); - m.unlock(); + bool isConditionChecked = false; + createThread([&](){ + m.lock(); + variable->wait(m, [&](){ + isConditionChecked = true; + return false; + }); + m.unlock(); + }); + m.lock(); + ASSERT_TRUE(isConditionChecked); + m.unlock(); } TEST_F(ConditionVariable, wait_condition_is_check_condition_when_notifyOne) { - bool isConditionChecked; - createThread([&](){ - m.lock(); - variable->wait(m, [&](){ - isConditionChecked = true; - return false; - }); - m.unlock(); - }); - m.lock(); - isConditionChecked = false; - m.unlock(); - variable->notifyOne(); - msleep(threadStartTime + 1); - m.lock(); - ASSERT_TRUE(isConditionChecked); - m.unlock(); + bool isConditionChecked; + createThread([&](){ + m.lock(); + variable->wait(m, [&](){ + isConditionChecked = true; + return false; + }); + m.unlock(); + }); + m.lock(); + isConditionChecked = false; + m.unlock(); + variable->notifyOne(); + msleep(threadStartTime + 1); + m.lock(); + ASSERT_TRUE(isConditionChecked); + m.unlock(); } TEST_F(ConditionVariable, wait_condition_is_unblock_when_condition_and_notifyOne) { - bool condition = false; - createThread([&](){ - m.lock(); - variable->wait(m, [&](){ return condition; }); - m.unlock(); - }); - m.lock(); - condition = true; - m.unlock(); - variable->notifyOne(); - ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); + bool condition = false; + createThread([&](){ + m.lock(); + variable->wait(m, [&](){ return condition; }); + m.unlock(); + }); + m.lock(); + condition = true; + m.unlock(); + variable->notifyOne(); + ASSERT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS)); } TEST_F(ConditionVariable, DISABLED_waitFor_is_block_before_timeout) { - createThread([&](){ - PITimeMeasurer measurer; - m.lock(); - variable->waitFor(m, WAIT_THREAD_TIME_MS * 2); - m.unlock(); - // Not reliable because spurious wakeup may happen - ASSERT_GE(measurer.elapsed_m(), WAIT_THREAD_TIME_MS); - }); - EXPECT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS * 3)); + createThread([&](){ + PITimeMeasurer measurer; + m.lock(); + variable->waitFor(m, WAIT_THREAD_TIME_MS * 2); + m.unlock(); + // Not reliable because spurious wakeup may happen + ASSERT_GE(measurer.elapsed_m(), WAIT_THREAD_TIME_MS); + }); + EXPECT_TRUE(thread->waitForFinish(WAIT_THREAD_TIME_MS * 3)); } TEST_F(ConditionVariable, waitFor_is_unblock_when_timeout) { - std::atomic_bool isUnblock(false); - createThread([&](){ - m.lock(); - variable->waitFor(m, WAIT_THREAD_TIME_MS); - isUnblock = true; - m.unlock(); - }); - // Test failed if suspend forever - EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); - ASSERT_TRUE(isUnblock); + std::atomic_bool isUnblock(false); + createThread([&](){ + m.lock(); + variable->waitFor(m, WAIT_THREAD_TIME_MS); + isUnblock = true; + m.unlock(); + }); + // Test failed if suspend forever + EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); + ASSERT_TRUE(isUnblock); } TEST_F(ConditionVariable, waitFor_is_false_when_timeout) { - bool waitRet = true; - createThread([&](){ - m.lock(); - waitRet = variable->waitFor(m, WAIT_THREAD_TIME_MS); - m.unlock(); - }); - EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); - ASSERT_FALSE(waitRet); + bool waitRet = true; + createThread([&](){ + m.lock(); + waitRet = variable->waitFor(m, WAIT_THREAD_TIME_MS); + m.unlock(); + }); + EXPECT_TRUE(thread->waitForFinish(2 * WAIT_THREAD_TIME_MS)); + ASSERT_FALSE(waitRet); } TEST_F(ConditionVariable, waitFor_is_unblock_when_condition_and_notifyOne) { - bool condition = false; - createThread([&](){ - m.lock(); - variable->waitFor(m, 3 * WAIT_THREAD_TIME_MS, [&](){ return condition; }); - m.unlock(); - }); - EXPECT_TRUE(thread->isRunning()); - m.lock(); - condition = true; - m.unlock(); - variable->notifyOne(); - msleep(WAIT_THREAD_TIME_MS); - ASSERT_FALSE(thread->isRunning()); + bool condition = false; + createThread([&](){ + m.lock(); + variable->waitFor(m, 3 * WAIT_THREAD_TIME_MS, [&](){ return condition; }); + m.unlock(); + }); + EXPECT_TRUE(thread->isRunning()); + m.lock(); + condition = true; + m.unlock(); + variable->notifyOne(); + msleep(WAIT_THREAD_TIME_MS); + ASSERT_FALSE(thread->isRunning()); }