1 // 2 // ReaderWriterLockTest.cs - NUnit Test Cases for System.Threading.ReaderWriterLock 3 // 4 // Author: 5 // Lluis Sanchez Gual (lluis@ximian.com) 6 // 7 // (C) 2004 Novell, Inc (http://www.novell.com) 8 // 9 10 using NUnit.Framework; 11 using System; 12 using System.Threading; 13 14 namespace MonoTests.System.Threading 15 { 16 [TestFixture] 17 public class ReaderWriterLockTest 18 { 19 ReaderWriterLock rwlock; 20 21 class ThreadRunner 22 { 23 public ThreadStart SecondaryThread; 24 public Exception ResultException; 25 public Thread RunningThread; 26 Run()27 public void Run () 28 { 29 try 30 { 31 SecondaryThread(); 32 } 33 catch (Exception ex) 34 { 35 ResultException = ex; 36 } 37 } 38 Join()39 public void Join () 40 { 41 RunningThread.Join (5000); 42 if (ResultException != null) throw ResultException; 43 } 44 } 45 RunThread(ThreadStart ts)46 void RunThread (ThreadStart ts) 47 { 48 ThreadRunner tr = StartThread (ts); 49 tr.Join (); 50 } 51 StartThread(ThreadStart ts)52 ThreadRunner StartThread (ThreadStart ts) 53 { 54 ThreadRunner tr = new ThreadRunner(); 55 tr.SecondaryThread = ts; 56 Thread t = new Thread (new ThreadStart (tr.Run)); 57 tr.RunningThread = t; 58 t.Start (); 59 return tr; 60 } 61 62 [Test] TestIsReaderLockHeld()63 public void TestIsReaderLockHeld () 64 { 65 rwlock = new ReaderWriterLock (); 66 Assert.IsTrue (!rwlock.IsReaderLockHeld, "#1"); 67 rwlock.AcquireReaderLock (500); 68 Assert.IsTrue (rwlock.IsReaderLockHeld, "#1"); 69 RunThread (new ThreadStart (IsReaderLockHeld_2)); 70 rwlock.ReleaseReaderLock (); 71 } 72 IsReaderLockHeld_2()73 private void IsReaderLockHeld_2 () 74 { 75 Assert.IsTrue (!rwlock.IsReaderLockHeld); 76 } 77 78 [Test] TestIsWriterLockHeld()79 public void TestIsWriterLockHeld () 80 { 81 rwlock = new ReaderWriterLock (); 82 Assert.IsTrue (!rwlock.IsWriterLockHeld, "#1"); 83 rwlock.AcquireWriterLock (500); 84 Assert.IsTrue (rwlock.IsWriterLockHeld, "#2"); 85 RunThread (new ThreadStart (IsWriterLockHeld_2)); 86 rwlock.ReleaseWriterLock (); 87 } 88 IsWriterLockHeld_2()89 private void IsWriterLockHeld_2 () 90 { 91 Assert.IsTrue (!rwlock.IsWriterLockHeld); 92 } 93 94 [Test] TestAcquireLocks()95 public void TestAcquireLocks () 96 { 97 rwlock = new ReaderWriterLock (); 98 rwlock.AcquireReaderLock (500); 99 rwlock.AcquireReaderLock (500); 100 rwlock.ReleaseReaderLock (); 101 Assert.IsTrue (rwlock.IsReaderLockHeld, "#1"); 102 RunThread (new ThreadStart (AcquireLock_readerWorks)); 103 Assert.IsTrue (rwlock.IsReaderLockHeld); 104 105 RunThread (new ThreadStart (AcquireLock_writerFails)); 106 rwlock.ReleaseReaderLock (); 107 Assert.IsTrue (!rwlock.IsReaderLockHeld); 108 109 RunThread (new ThreadStart (AcquireLock_writerWorks)); 110 111 rwlock.AcquireWriterLock (200); 112 RunThread (new ThreadStart (AcquireLock_writerFails)); 113 RunThread (new ThreadStart (AcquireLock_readerFails)); 114 rwlock.ReleaseWriterLock (); 115 } 116 AcquireLock_readerWorks()117 void AcquireLock_readerWorks () 118 { 119 rwlock.AcquireReaderLock (200); 120 rwlock.AcquireReaderLock (200); 121 rwlock.ReleaseReaderLock (); 122 Assert.IsTrue (rwlock.IsReaderLockHeld); 123 rwlock.ReleaseReaderLock (); 124 Assert.IsTrue (!rwlock.IsReaderLockHeld); 125 } 126 AcquireLock_writerFails()127 void AcquireLock_writerFails () 128 { 129 try 130 { 131 rwlock.AcquireWriterLock (200); 132 rwlock.ReleaseWriterLock (); 133 throw new Exception ("Should not get writer lock"); 134 } 135 catch (Exception) 136 { 137 } 138 } 139 AcquireLock_writerWorks()140 void AcquireLock_writerWorks () 141 { 142 rwlock.AcquireWriterLock (200); 143 rwlock.ReleaseWriterLock (); 144 } 145 AcquireLock_readerFails()146 void AcquireLock_readerFails () 147 { 148 try 149 { 150 rwlock.AcquireReaderLock (200); 151 rwlock.ReleaseReaderLock (); 152 throw new Exception ("Should not get reader lock"); 153 } 154 catch (Exception) 155 { 156 } 157 } 158 159 [Test] TestReleaseRestoreReaderLock()160 public void TestReleaseRestoreReaderLock () 161 { 162 rwlock = new ReaderWriterLock (); 163 rwlock.AcquireReaderLock (500); 164 rwlock.AcquireReaderLock (500); 165 Assert.IsTrue (rwlock.IsReaderLockHeld); 166 167 LockCookie co = rwlock.ReleaseLock (); 168 RunThread (new ThreadStart (AcquireLock_writerWorks)); 169 170 rwlock.RestoreLock (ref co); 171 RunThread (new ThreadStart (AcquireLock_writerFails)); 172 173 rwlock.ReleaseReaderLock (); 174 Assert.IsTrue (rwlock.IsReaderLockHeld); 175 rwlock.ReleaseReaderLock (); 176 Assert.IsTrue (!rwlock.IsReaderLockHeld); 177 } 178 179 [Test] TestReleaseRestoreWriterLock()180 public void TestReleaseRestoreWriterLock () 181 { 182 rwlock = new ReaderWriterLock (); 183 rwlock.AcquireWriterLock (500); 184 rwlock.AcquireWriterLock (500); 185 Assert.IsTrue (rwlock.IsWriterLockHeld); 186 187 LockCookie co = rwlock.ReleaseLock (); 188 RunThread (new ThreadStart (AcquireLock_readerWorks)); 189 190 rwlock.RestoreLock (ref co); 191 RunThread (new ThreadStart (AcquireLock_readerFails)); 192 193 rwlock.ReleaseWriterLock (); 194 Assert.IsTrue (rwlock.IsWriterLockHeld); 195 rwlock.ReleaseWriterLock (); 196 Assert.IsTrue (!rwlock.IsWriterLockHeld); 197 } 198 199 [Test] TestUpgradeDowngradeLock()200 public void TestUpgradeDowngradeLock () 201 { 202 rwlock = new ReaderWriterLock (); 203 rwlock.AcquireReaderLock (200); 204 rwlock.AcquireReaderLock (200); 205 206 LockCookie co = rwlock.UpgradeToWriterLock (200); 207 Assert.IsTrue (!rwlock.IsReaderLockHeld); 208 Assert.IsTrue (rwlock.IsWriterLockHeld); 209 RunThread (new ThreadStart (AcquireLock_writerFails)); 210 211 rwlock.DowngradeFromWriterLock (ref co); 212 Assert.IsTrue (rwlock.IsReaderLockHeld); 213 Assert.IsTrue (!rwlock.IsWriterLockHeld); 214 RunThread (new ThreadStart (AcquireLock_readerWorks)); 215 216 rwlock.ReleaseReaderLock (); 217 Assert.IsTrue (rwlock.IsReaderLockHeld); 218 rwlock.ReleaseReaderLock (); 219 Assert.IsTrue (!rwlock.IsReaderLockHeld); 220 } 221 222 [Test] TestReaderInsideWriter()223 public void TestReaderInsideWriter () 224 { 225 // Reader acquires and releases work like the writer equivalent 226 227 rwlock = new ReaderWriterLock (); 228 rwlock.AcquireWriterLock (-1); 229 rwlock.AcquireReaderLock (-1); 230 Assert.IsTrue (!rwlock.IsReaderLockHeld); 231 Assert.IsTrue (rwlock.IsWriterLockHeld); 232 rwlock.AcquireReaderLock (-1); 233 Assert.IsTrue (!rwlock.IsReaderLockHeld); 234 Assert.IsTrue (rwlock.IsWriterLockHeld); 235 rwlock.ReleaseWriterLock (); 236 Assert.IsTrue (!rwlock.IsReaderLockHeld); 237 Assert.IsTrue (rwlock.IsWriterLockHeld); 238 rwlock.ReleaseReaderLock (); 239 Assert.IsTrue (!rwlock.IsReaderLockHeld); 240 Assert.IsTrue (rwlock.IsWriterLockHeld); 241 rwlock.ReleaseReaderLock (); 242 Assert.IsTrue (!rwlock.IsReaderLockHeld); 243 Assert.IsTrue (!rwlock.IsWriterLockHeld); 244 } 245 246 [Test] TestReaderMustWaitWriter()247 public void TestReaderMustWaitWriter () 248 { 249 // A thread cannot get the reader lock if there are other threads 250 // waiting for the writer lock. 251 252 rwlock = new ReaderWriterLock (); 253 rwlock.AcquireWriterLock (200); 254 255 ThreadRunner tr = StartThread (new ThreadStart (ReaderMustWaitWriter_2)); 256 Thread.Sleep (200); 257 258 RunThread (new ThreadStart (AcquireLock_readerFails)); 259 260 rwlock.ReleaseReaderLock (); 261 tr.Join (); 262 } 263 ReaderMustWaitWriter_2()264 void ReaderMustWaitWriter_2 () 265 { 266 rwlock.AcquireWriterLock (2000); 267 rwlock.ReleaseWriterLock (); 268 } 269 270 [Test] TestBug_55911()271 public void TestBug_55911 () 272 { 273 rwlock = new ReaderWriterLock (); 274 275 rwlock.AcquireReaderLock (Timeout.Infinite); 276 try { 277 LockCookie lc = rwlock.UpgradeToWriterLock (Timeout.Infinite); 278 } 279 finally { rwlock.ReleaseReaderLock(); } 280 281 rwlock.AcquireReaderLock (Timeout.Infinite); 282 try { 283 LockCookie lc = rwlock.UpgradeToWriterLock (Timeout.Infinite); 284 } 285 finally { rwlock.ReleaseReaderLock(); } 286 } 287 288 [Test] TestBug_55909()289 public void TestBug_55909 () 290 { 291 rwlock = new ReaderWriterLock (); 292 ThreadRunner tr = StartThread (new ThreadStart(Bug_55909_Thread2)); 293 Thread.Sleep (200); 294 rwlock.AcquireReaderLock (Timeout.Infinite); 295 try { 296 LockCookie lc = rwlock.UpgradeToWriterLock (Timeout.Infinite); 297 Thread.Sleep (500); 298 } 299 finally { rwlock.ReleaseReaderLock(); } 300 301 tr.Join (); 302 } 303 Bug_55909_Thread2()304 public void Bug_55909_Thread2 () 305 { 306 rwlock.AcquireReaderLock(Timeout.Infinite); 307 try { 308 Thread.Sleep (1000); 309 LockCookie lc = rwlock.UpgradeToWriterLock (Timeout.Infinite); 310 Thread.Sleep (500); 311 } 312 finally { rwlock.ReleaseReaderLock(); } 313 } 314 315 [Test] TestBug_55909_bis()316 public void TestBug_55909_bis () 317 { 318 rwlock = new ReaderWriterLock (); 319 ThreadRunner tr1 = StartThread (new ThreadStart(Bug_55909_bis_ReaderWriter)); 320 Thread.Sleep(100); 321 ThreadRunner tr2 = StartThread (new ThreadStart(Bug_55909_bis_Reader)); 322 Thread.Sleep(100); 323 ThreadRunner tr3 = StartThread (new ThreadStart(Bug_55909_bis_Writer)); 324 Thread.Sleep(100); 325 ThreadRunner tr4 = StartThread (new ThreadStart(Bug_55909_bis_Reader)); 326 tr1.Join (); 327 tr2.Join (); 328 tr3.Join (); 329 tr4.Join (); 330 } 331 Bug_55909_bis_Reader()332 void Bug_55909_bis_Reader () 333 { 334 rwlock.AcquireReaderLock(-1); 335 Thread.Sleep(2000); 336 rwlock.ReleaseReaderLock(); 337 } 338 Bug_55909_bis_ReaderWriter()339 void Bug_55909_bis_ReaderWriter () 340 { 341 rwlock.AcquireReaderLock(-1); 342 LockCookie lc = rwlock.UpgradeToWriterLock(-1); 343 Thread.Sleep(1000); 344 rwlock.DowngradeFromWriterLock(ref lc); 345 rwlock.ReleaseReaderLock(); 346 } 347 Bug_55909_bis_Writer()348 void Bug_55909_bis_Writer () 349 { 350 rwlock.AcquireWriterLock(-1); 351 rwlock.ReleaseWriterLock(); 352 } 353 354 355 [Test] TestBug_475124()356 public void TestBug_475124 () 357 { 358 LockCookie lc1, lc2; 359 360 rwlock = new ReaderWriterLock (); 361 362 Assert.IsFalse (rwlock.IsReaderLockHeld, "A1"); 363 Assert.IsFalse (rwlock.IsWriterLockHeld, "A2"); 364 365 rwlock.AcquireReaderLock (Timeout.Infinite); 366 367 Assert.IsTrue (rwlock.IsReaderLockHeld, "B1"); 368 Assert.IsFalse (rwlock.IsWriterLockHeld, "B2"); 369 370 lc1 = rwlock.UpgradeToWriterLock (Timeout.Infinite); 371 372 Assert.IsFalse (rwlock.IsReaderLockHeld, "C1"); 373 Assert.IsTrue (rwlock.IsWriterLockHeld, "C2"); 374 375 rwlock.AcquireReaderLock (Timeout.Infinite); 376 377 Assert.IsFalse (rwlock.IsReaderLockHeld, "D1"); 378 Assert.IsTrue (rwlock.IsWriterLockHeld, "D2"); 379 380 lc2 = rwlock.UpgradeToWriterLock (Timeout.Infinite); 381 382 Assert.IsFalse (rwlock.IsReaderLockHeld, "E1"); 383 Assert.IsTrue (rwlock.IsWriterLockHeld, "E2"); 384 385 rwlock.DowngradeFromWriterLock (ref lc2); 386 387 Assert.IsFalse (rwlock.IsReaderLockHeld, "F1"); 388 Assert.IsTrue (rwlock.IsWriterLockHeld, "F2"); 389 390 rwlock.ReleaseReaderLock (); 391 392 Assert.IsFalse (rwlock.IsReaderLockHeld, "G1"); 393 Assert.IsTrue (rwlock.IsWriterLockHeld, "G2"); 394 395 rwlock.DowngradeFromWriterLock (ref lc1); 396 397 Assert.IsTrue (rwlock.IsReaderLockHeld, "H1"); 398 Assert.IsFalse (rwlock.IsWriterLockHeld, "H2"); 399 400 rwlock.ReleaseReaderLock (); 401 402 Assert.IsFalse (rwlock.IsReaderLockHeld, "I1"); 403 Assert.IsFalse (rwlock.IsWriterLockHeld, "I2"); 404 } 405 406 // this tests how downgrade works when multiple writer locks 407 // are acquired - as long as the LockCookie referes to an 408 // upgrade where there was already a writer lock, downgrade 409 // behaves like a non-blocking ReleaseWriterLock 410 [Test] DowngradeTest()411 public void DowngradeTest () 412 { 413 LockCookie lc1, lc2, lc3, lc4; 414 415 rwlock = new ReaderWriterLock (); 416 417 rwlock.AcquireReaderLock (Timeout.Infinite); 418 lc1 = rwlock.UpgradeToWriterLock (Timeout.Infinite); 419 rwlock.AcquireReaderLock (Timeout.Infinite); 420 lc2 = rwlock.UpgradeToWriterLock (Timeout.Infinite); 421 rwlock.AcquireReaderLock (Timeout.Infinite); 422 lc3 = rwlock.UpgradeToWriterLock (Timeout.Infinite); 423 rwlock.AcquireReaderLock (Timeout.Infinite); 424 lc4 = rwlock.UpgradeToWriterLock (Timeout.Infinite); 425 426 rwlock.DowngradeFromWriterLock (ref lc2); 427 428 Assert.IsFalse (rwlock.IsReaderLockHeld, "A1"); 429 Assert.IsTrue (rwlock.IsWriterLockHeld, "A2"); 430 431 rwlock.ReleaseReaderLock (); 432 433 Assert.IsFalse (rwlock.IsReaderLockHeld, "B1"); 434 Assert.IsTrue (rwlock.IsWriterLockHeld, "B2"); 435 436 rwlock.DowngradeFromWriterLock (ref lc4); 437 438 Assert.IsFalse (rwlock.IsReaderLockHeld, "C1"); 439 Assert.IsTrue (rwlock.IsWriterLockHeld, "C2"); 440 441 rwlock.ReleaseReaderLock (); 442 443 Assert.IsFalse (rwlock.IsReaderLockHeld, "D1"); 444 Assert.IsTrue (rwlock.IsWriterLockHeld, "D2"); 445 446 rwlock.DowngradeFromWriterLock (ref lc3); 447 448 Assert.IsFalse (rwlock.IsReaderLockHeld, "E1"); 449 Assert.IsTrue (rwlock.IsWriterLockHeld, "E2"); 450 451 rwlock.ReleaseReaderLock (); 452 453 Assert.IsFalse (rwlock.IsReaderLockHeld, "F1"); 454 Assert.IsTrue (rwlock.IsWriterLockHeld, "F2"); 455 456 rwlock.DowngradeFromWriterLock (ref lc1); 457 458 Assert.IsTrue (rwlock.IsReaderLockHeld, "G1"); 459 Assert.IsFalse (rwlock.IsWriterLockHeld, "G2"); 460 461 rwlock.ReleaseReaderLock (); 462 463 Assert.IsFalse (rwlock.IsReaderLockHeld, "H1"); 464 Assert.IsFalse (rwlock.IsWriterLockHeld, "H2"); 465 } 466 } 467 } 468