#include "pch.h" #define NO_MAIN #include #include #include #include "CppUnitTest.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace FrameworkTests { TEST_CLASS (ReadWriteLockTest) { public: ReadWriteLockTest() { Framework::initFramework(0); } ~ReadWriteLockTest() { Framework::releaseFramework(); } TEST_METHOD (testLockRead) { Framework::ReadWriteLock lock; Assert::IsTrue(Framework::getCurrentThreadLockCount() == 0, L"The current threads lock holding count should be 0 at the " L"beginning"); Assert::IsTrue(lock.getReadThreadCount() == 0, L"Initialized ReadWriteLock should not have any readers."); lock.lockRead(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 1, L"The current threads lock holding count should be 1 after " L"lockRead() was called"); Assert::IsTrue(lock.getReadThreadCount() == 1, L"ReadWriteLock should have exactly one reader after " L"lockRead() was called."); Assert::IsTrue( lock.getReadThread(0) == Framework::getCurrentThreadId(), L"Current thread id is not present in reader threads after " L"lockRead() was called"); Assert::IsTrue( lock.getReadLockCount(Framework::getCurrentThreadId()) == 1, L"Lock count should be 1 after lockRead() was called once"); lock.lockRead(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 2, L"The current threads lock holding count should be 2 after " L"lockRead() was called twice"); Assert::IsTrue(lock.getReadThreadCount() == 1, L"ReadWriteLock should have exactly one reader after " L"lockRead() was called twice by the same thread."); Assert::IsTrue( lock.getReadThread(0) == Framework::getCurrentThreadId(), L"Current thread id is not present in reader threads after " L"lockRead() was called twice by the same thread"); Assert::IsTrue( lock.getReadLockCount(Framework::getCurrentThreadId()) == 2, L"Lock count should be 1 after lockRead() was called twice"); } TEST_METHOD (testUnlockRead) { Framework::ReadWriteLock lock; lock.lockRead(); lock.lockRead(); lock.unlockRead(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 1, L"The current threads lock holding count should be 1 after " L"lockRead() was called twice and unlockRead() once"); Assert::IsTrue(lock.getReadThreadCount() == 1, L"ReadWriteLock should have exactly one reader after " L"lockRead() was called twice and unlockRead() once by the " L"same thread."); Assert::IsTrue( lock.getReadThread(0) == Framework::getCurrentThreadId(), L"Current thread id is not present in reader threads after " L"lockRead() was called twice and unlockRead() once by the " L"same thread."); Assert::IsTrue( lock.getReadLockCount(Framework::getCurrentThreadId()) == 1, L"Lock count should be 1 after lockRead() was called twice and " L"unlockRead() once by the same thread."); lock.unlockRead(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 0, L"The current threads lock holding count should be 0 after " L"lockRead() was called twice and unlockRead() twice"); Assert::IsTrue(lock.getReadThreadCount() == 0, L"ReadWriteLock should have 0 readers after " L"lockRead() was called twice and unlockRead() twice by the " L"same thread."); lock.lockRead(); Assert::IsTrue(lock.getReadThreadCount() == 1, L"ReadWriteLock should have exactly one reader after " L"lockRead() was called 3 times and unlockRead() twice by the " L"same thread."); lock.unlockRead(); Assert::IsTrue(lock.getReadThreadCount() == 0, L"ReadWriteLock should have 0 readers after " L"lockRead() was called 3 times and unlockRead() 3 times by " L"the " L"same thread."); } TEST_METHOD (testLockWrite) { Framework::ReadWriteLock lock; Assert::IsTrue(lock.getWriteLockCount() == 0, L"The write lock count should be 0 at the beginning"); lock.lockWrite(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 1, L"The current threads lock holding count should be 1 after " L"lockWrite() was called"); Assert::IsTrue(lock.getWriteLockCount() == 1, L"write lock count should be 1 after " L"lockWrite() was called."); Assert::IsTrue( lock.getWriteLockThread() == Framework::getCurrentThreadId(), L"Current thread should be the writer thread after " L"lockWrite() was called"); lock.lockWrite(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 2, L"The current threads lock holding count should be 2 after " L"lockWrite() was called twice"); Assert::IsTrue(lock.getWriteLockCount() == 2, L"write lock count should be 2 after " L"lockWrite() was called twice"); Assert::IsTrue( lock.getWriteLockThread() == Framework::getCurrentThreadId(), L"Current thread should be the writer thread after " L"lockWrite() was called twice"); } TEST_METHOD (testUnlockWrite) { Framework::ReadWriteLock lock; lock.lockWrite(); lock.lockWrite(); lock.unlockWrite(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 1, L"The current threads lock holding count should be 1 after " L"lockWrite() was called twice and unlockWrite() once"); Assert::IsTrue(lock.getWriteLockCount() == 1, L"write lock count should be one reader after " L"lockWrite() was called twice and unlockWrite() once by the " L"same thread."); Assert::IsTrue( lock.getWriteLockThread() == Framework::getCurrentThreadId(), L"Current thread id should be the writer thread after " L"lockWrite() was called twice and unlockWrite() once by the " L"same thread."); lock.unlockWrite(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 0, L"The current threads lock holding count should be 0 after " L"lockWrite() was called twice and unlockWrite() twice"); Assert::IsTrue(lock.getWriteLockCount() == 0, L"write lock count should be 0 after " L"lockWrite() was called twice and unlockWrite() twice by the " L"same thread."); lock.lockWrite(); Assert::IsTrue(lock.getWriteLockCount() == 1, L"write lock count should be exactly one after " L"lockWrite() was called 3 times and unlockWrite() twice by " L"the " L"same thread."); lock.unlockWrite(); Assert::IsTrue(lock.getWriteLockCount() == 0, L"write lock count should be 0 after " L"lockWrite() was called 3 times and unlockWrite() 3 times by " L"the " L"same thread."); } TEST_METHOD (testUpgrade) { Framework::ReadWriteLock lock; lock.lockRead(); lock.lockWrite(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 2, L"The current threads lock holding count should be 2 after " L"lockRead() and lockWrite() was called"); Assert::IsTrue(lock.getWriteLockCount() == 1, L"write lock count should be 1 after " L"lockWrite() was called."); Assert::IsTrue( lock.getWriteLockThread() == Framework::getCurrentThreadId(), L"Current thread should be the writer thread after " L"lockWrite() was called"); Assert::IsTrue(lock.getReadThreadCount() == 1, L"ReadWriteLock should have exactly one reader after " L"lockRead() was called."); Assert::IsTrue( lock.getReadThread(0) == Framework::getCurrentThreadId(), L"Current thread id is not present in reader threads after " L"lockRead() was called"); Assert::IsTrue( lock.getReadLockCount(Framework::getCurrentThreadId()) == 1, L"Lock count should be 1 after lockRead() was called once"); lock.unlockWrite(); lock.unlockRead(); Assert::IsTrue(Framework::getCurrentThreadLockCount() == 0, L"The current threads lock holding count should be 0 after " L"lockRead() and lockWrite() and unlockWrite() and " L"unlockRead() was called"); Assert::IsTrue(lock.getWriteLockCount() == 0, L"write lock count should be 0 after " L"lockWrite() and unlockWrite() was called"); Assert::IsTrue(lock.getReadThreadCount() == 0, L"write lock count should be 0 after " L"lockRead() and unlockRead() was called"); } TEST_METHOD (testReadMultithreading) { Framework::ReadWriteLock lock; lock.lockRead(); bool finished = 0; new Framework::AsynchronCall( [&lock]() { lock.lockRead(); lock.unlockRead(); }, &finished); while (!finished) { Sleep(10); } lock.unlockRead(); } TEST_METHOD (testWriteMultithreading) { Framework::ReadWriteLock lock; lock.lockWrite(); bool finished = 0; bool lockAvailable = 0; new Framework::AsynchronCall( [&lock, &lockAvailable]() { lockAvailable = lock.tryLockWrite(); }, &finished); while (!finished) { Sleep(10); } lock.unlockWrite(); Assert::IsFalse(lockAvailable, L"Write lock should not be available when another thread is " L"using it"); } TEST_METHOD (testWriteReadMultithreading) { Framework::ReadWriteLock lock; lock.lockWrite(); bool finished = 0; bool lockAvailable = 0; new Framework::AsynchronCall( [&lock, &lockAvailable]() { lockAvailable = lock.tryLockRead(); }, &finished); while (!finished) { Sleep(10); } lock.unlockWrite(); Assert::IsFalse(lockAvailable, L"Read lock should not be available when another thread is " L"writing"); } TEST_METHOD (testReadWriteMultithreading) { Framework::ReadWriteLock lock; lock.lockRead(); bool finished = 0; bool lockAvailable = 0; new Framework::AsynchronCall( [&lock, &lockAvailable]() { lockAvailable = lock.tryLockWrite(); }, &finished); while (!finished) { Sleep(10); } lock.unlockRead(); Assert::IsFalse(lockAvailable, L"Write lock should not be available when another thread is " L"reading"); } }; } // namespace FrameworkTests