Critical.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #include "pch.h"
  2. #define NO_MAIN
  3. #include <AsynchronCall.h>
  4. #include <Critical.h>
  5. #include <Globals.h>
  6. #include "CppUnitTest.h"
  7. using namespace Microsoft::VisualStudio::CppUnitTestFramework;
  8. namespace FrameworkTests
  9. {
  10. TEST_CLASS (ReadWriteLockTest)
  11. {
  12. public:
  13. ReadWriteLockTest()
  14. {
  15. Framework::initFramework(0);
  16. }
  17. ~ReadWriteLockTest()
  18. {
  19. Framework::releaseFramework();
  20. }
  21. TEST_METHOD (testLockRead)
  22. {
  23. Framework::ReadWriteLock lock;
  24. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 0,
  25. L"The current threads lock holding count should be 0 at the "
  26. L"beginning");
  27. Assert::IsTrue(lock.getReadThreadCount() == 0,
  28. L"Initialized ReadWriteLock should not have any readers.");
  29. lock.lockRead();
  30. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 1,
  31. L"The current threads lock holding count should be 1 after "
  32. L"lockRead() was called");
  33. Assert::IsTrue(lock.getReadThreadCount() == 1,
  34. L"ReadWriteLock should have exactly one reader after "
  35. L"lockRead() was called.");
  36. Assert::IsTrue(
  37. lock.getReadThread(0) == Framework::getCurrentThreadId(),
  38. L"Current thread id is not present in reader threads after "
  39. L"lockRead() was called");
  40. Assert::IsTrue(
  41. lock.getReadLockCount(Framework::getCurrentThreadId()) == 1,
  42. L"Lock count should be 1 after lockRead() was called once");
  43. lock.lockRead();
  44. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 2,
  45. L"The current threads lock holding count should be 2 after "
  46. L"lockRead() was called twice");
  47. Assert::IsTrue(lock.getReadThreadCount() == 1,
  48. L"ReadWriteLock should have exactly one reader after "
  49. L"lockRead() was called twice by the same thread.");
  50. Assert::IsTrue(
  51. lock.getReadThread(0) == Framework::getCurrentThreadId(),
  52. L"Current thread id is not present in reader threads after "
  53. L"lockRead() was called twice by the same thread");
  54. Assert::IsTrue(
  55. lock.getReadLockCount(Framework::getCurrentThreadId()) == 2,
  56. L"Lock count should be 1 after lockRead() was called twice");
  57. }
  58. TEST_METHOD (testUnlockRead)
  59. {
  60. Framework::ReadWriteLock lock;
  61. lock.lockRead();
  62. lock.lockRead();
  63. lock.unlockRead();
  64. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 1,
  65. L"The current threads lock holding count should be 1 after "
  66. L"lockRead() was called twice and unlockRead() once");
  67. Assert::IsTrue(lock.getReadThreadCount() == 1,
  68. L"ReadWriteLock should have exactly one reader after "
  69. L"lockRead() was called twice and unlockRead() once by the "
  70. L"same thread.");
  71. Assert::IsTrue(
  72. lock.getReadThread(0) == Framework::getCurrentThreadId(),
  73. L"Current thread id is not present in reader threads after "
  74. L"lockRead() was called twice and unlockRead() once by the "
  75. L"same thread.");
  76. Assert::IsTrue(
  77. lock.getReadLockCount(Framework::getCurrentThreadId()) == 1,
  78. L"Lock count should be 1 after lockRead() was called twice and "
  79. L"unlockRead() once by the same thread.");
  80. lock.unlockRead();
  81. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 0,
  82. L"The current threads lock holding count should be 0 after "
  83. L"lockRead() was called twice and unlockRead() twice");
  84. Assert::IsTrue(lock.getReadThreadCount() == 0,
  85. L"ReadWriteLock should have 0 readers after "
  86. L"lockRead() was called twice and unlockRead() twice by the "
  87. L"same thread.");
  88. lock.lockRead();
  89. Assert::IsTrue(lock.getReadThreadCount() == 1,
  90. L"ReadWriteLock should have exactly one reader after "
  91. L"lockRead() was called 3 times and unlockRead() twice by the "
  92. L"same thread.");
  93. lock.unlockRead();
  94. Assert::IsTrue(lock.getReadThreadCount() == 0,
  95. L"ReadWriteLock should have 0 readers after "
  96. L"lockRead() was called 3 times and unlockRead() 3 times by "
  97. L"the "
  98. L"same thread.");
  99. }
  100. TEST_METHOD (testLockWrite)
  101. {
  102. Framework::ReadWriteLock lock;
  103. Assert::IsTrue(lock.getWriteLockCount() == 0,
  104. L"The write lock count should be 0 at the beginning");
  105. lock.lockWrite();
  106. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 1,
  107. L"The current threads lock holding count should be 1 after "
  108. L"lockWrite() was called");
  109. Assert::IsTrue(lock.getWriteLockCount() == 1,
  110. L"write lock count should be 1 after "
  111. L"lockWrite() was called.");
  112. Assert::IsTrue(
  113. lock.getWriteLockThread() == Framework::getCurrentThreadId(),
  114. L"Current thread should be the writer thread after "
  115. L"lockWrite() was called");
  116. lock.lockWrite();
  117. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 2,
  118. L"The current threads lock holding count should be 2 after "
  119. L"lockWrite() was called twice");
  120. Assert::IsTrue(lock.getWriteLockCount() == 2,
  121. L"write lock count should be 2 after "
  122. L"lockWrite() was called twice");
  123. Assert::IsTrue(
  124. lock.getWriteLockThread() == Framework::getCurrentThreadId(),
  125. L"Current thread should be the writer thread after "
  126. L"lockWrite() was called twice");
  127. }
  128. TEST_METHOD (testUnlockWrite)
  129. {
  130. Framework::ReadWriteLock lock;
  131. lock.lockWrite();
  132. lock.lockWrite();
  133. lock.unlockWrite();
  134. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 1,
  135. L"The current threads lock holding count should be 1 after "
  136. L"lockWrite() was called twice and unlockWrite() once");
  137. Assert::IsTrue(lock.getWriteLockCount() == 1,
  138. L"write lock count should be one reader after "
  139. L"lockWrite() was called twice and unlockWrite() once by the "
  140. L"same thread.");
  141. Assert::IsTrue(
  142. lock.getWriteLockThread() == Framework::getCurrentThreadId(),
  143. L"Current thread id should be the writer thread after "
  144. L"lockWrite() was called twice and unlockWrite() once by the "
  145. L"same thread.");
  146. lock.unlockWrite();
  147. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 0,
  148. L"The current threads lock holding count should be 0 after "
  149. L"lockWrite() was called twice and unlockWrite() twice");
  150. Assert::IsTrue(lock.getWriteLockCount() == 0,
  151. L"write lock count should be 0 after "
  152. L"lockWrite() was called twice and unlockWrite() twice by the "
  153. L"same thread.");
  154. lock.lockWrite();
  155. Assert::IsTrue(lock.getWriteLockCount() == 1,
  156. L"write lock count should be exactly one after "
  157. L"lockWrite() was called 3 times and unlockWrite() twice by "
  158. L"the "
  159. L"same thread.");
  160. lock.unlockWrite();
  161. Assert::IsTrue(lock.getWriteLockCount() == 0,
  162. L"write lock count should be 0 after "
  163. L"lockWrite() was called 3 times and unlockWrite() 3 times by "
  164. L"the "
  165. L"same thread.");
  166. }
  167. TEST_METHOD (testUpgrade)
  168. {
  169. Framework::ReadWriteLock lock;
  170. lock.lockRead();
  171. lock.lockWrite();
  172. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 2,
  173. L"The current threads lock holding count should be 2 after "
  174. L"lockRead() and lockWrite() was called");
  175. Assert::IsTrue(lock.getWriteLockCount() == 1,
  176. L"write lock count should be 1 after "
  177. L"lockWrite() was called.");
  178. Assert::IsTrue(
  179. lock.getWriteLockThread() == Framework::getCurrentThreadId(),
  180. L"Current thread should be the writer thread after "
  181. L"lockWrite() was called");
  182. Assert::IsTrue(lock.getReadThreadCount() == 1,
  183. L"ReadWriteLock should have exactly one reader after "
  184. L"lockRead() was called.");
  185. Assert::IsTrue(
  186. lock.getReadThread(0) == Framework::getCurrentThreadId(),
  187. L"Current thread id is not present in reader threads after "
  188. L"lockRead() was called");
  189. Assert::IsTrue(
  190. lock.getReadLockCount(Framework::getCurrentThreadId()) == 1,
  191. L"Lock count should be 1 after lockRead() was called once");
  192. lock.unlockWrite();
  193. lock.unlockRead();
  194. Assert::IsTrue(Framework::getCurrentThreadLockCount() == 0,
  195. L"The current threads lock holding count should be 0 after "
  196. L"lockRead() and lockWrite() and unlockWrite() and "
  197. L"unlockRead() was called");
  198. Assert::IsTrue(lock.getWriteLockCount() == 0,
  199. L"write lock count should be 0 after "
  200. L"lockWrite() and unlockWrite() was called");
  201. Assert::IsTrue(lock.getReadThreadCount() == 0,
  202. L"write lock count should be 0 after "
  203. L"lockRead() and unlockRead() was called");
  204. }
  205. TEST_METHOD (testReadMultithreading)
  206. {
  207. Framework::ReadWriteLock lock;
  208. lock.lockRead();
  209. bool finished = 0;
  210. new Framework::AsynchronCall(
  211. [&lock]() {
  212. lock.lockRead();
  213. lock.unlockRead();
  214. },
  215. &finished);
  216. while (!finished)
  217. {
  218. Sleep(10);
  219. }
  220. lock.unlockRead();
  221. }
  222. TEST_METHOD (testWriteMultithreading)
  223. {
  224. Framework::ReadWriteLock lock;
  225. lock.lockWrite();
  226. bool finished = 0;
  227. bool lockAvailable = 0;
  228. new Framework::AsynchronCall(
  229. [&lock, &lockAvailable]() {
  230. lockAvailable = lock.tryLockWrite();
  231. },
  232. &finished);
  233. while (!finished)
  234. {
  235. Sleep(10);
  236. }
  237. lock.unlockWrite();
  238. Assert::IsFalse(lockAvailable,
  239. L"Write lock should not be available when another thread is "
  240. L"using it");
  241. }
  242. TEST_METHOD (testWriteReadMultithreading)
  243. {
  244. Framework::ReadWriteLock lock;
  245. lock.lockWrite();
  246. bool finished = 0;
  247. bool lockAvailable = 0;
  248. new Framework::AsynchronCall(
  249. [&lock, &lockAvailable]() {
  250. lockAvailable = lock.tryLockRead();
  251. },
  252. &finished);
  253. while (!finished)
  254. {
  255. Sleep(10);
  256. }
  257. lock.unlockWrite();
  258. Assert::IsFalse(lockAvailable,
  259. L"Read lock should not be available when another thread is "
  260. L"writing");
  261. }
  262. TEST_METHOD (testReadWriteMultithreading)
  263. {
  264. Framework::ReadWriteLock lock;
  265. lock.lockRead();
  266. bool finished = 0;
  267. bool lockAvailable = 0;
  268. new Framework::AsynchronCall(
  269. [&lock, &lockAvailable]() {
  270. lockAvailable = lock.tryLockWrite();
  271. },
  272. &finished);
  273. while (!finished)
  274. {
  275. Sleep(10);
  276. }
  277. lock.unlockRead();
  278. Assert::IsFalse(lockAvailable,
  279. L"Write lock should not be available when another thread is "
  280. L"reading");
  281. }
  282. };
  283. } // namespace FrameworkTests