Implement MachineKey.Protect and MachineKey.Unprotect
[mono.git] / mcs / class / System.Core / Test / System.Threading / ReaderWriterLockSlimTest.cs
1 //
2 // ReaderWriterLockSlimTest.cs
3 //
4 // Authors:
5 //      Marek Safar (marek.safar@gmail.com)
6 //
7 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using NUnit.Framework;
31 using System.Threading;
32 using System.Linq;
33 #if NET_4_0
34 using System.Threading.Tasks;
35 #endif
36
37 namespace MonoTests.System.Threading
38 {
39         [TestFixture]
40         public class ReaderWriterLockSlimTests
41         {
42                 [Test]
43                 public void DefaultValues ()
44                 {
45                         var v = new ReaderWriterLockSlim ();
46                         Assert.AreEqual (0, v.CurrentReadCount, "1");
47                         Assert.AreEqual (false, v.IsReadLockHeld, "2");
48                         Assert.AreEqual (false, v.IsUpgradeableReadLockHeld, "3");
49                         Assert.AreEqual (false, v.IsWriteLockHeld, "4");
50                         Assert.AreEqual (LockRecursionPolicy.NoRecursion, v.RecursionPolicy, "5");
51                         Assert.AreEqual (0, v.RecursiveReadCount, "6");
52                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "7");
53                         Assert.AreEqual (0, v.RecursiveWriteCount, "8");
54                         Assert.AreEqual (0, v.WaitingReadCount, "9");
55                         Assert.AreEqual (0, v.WaitingUpgradeCount, "10");
56                         Assert.AreEqual (0, v.WaitingWriteCount, "11");
57                 }
58
59                 [Test]
60                 public void Dispose_Errors ()
61                 {
62                         var v = new ReaderWriterLockSlim ();
63                         v.Dispose ();
64
65                         try {
66                                 v.EnterUpgradeableReadLock ();
67                                 Assert.Fail ("1");
68                         } catch (ObjectDisposedException) {
69                         }
70
71                         try {
72                                 v.EnterReadLock ();
73                                 Assert.Fail ("2");
74                         } catch (ObjectDisposedException) {
75                         }
76
77                         try {
78                                 v.EnterWriteLock ();
79                                 Assert.Fail ("3");
80                         } catch (ObjectDisposedException) {
81                         }
82                 }
83
84                 [Test]
85                 public void Dispose_WithReadLock ()
86                 {
87                         var rwl = new ReaderWriterLockSlim ();
88                         rwl.EnterReadLock ();
89                         try {
90                                 rwl.Dispose ();
91                                 Assert.Fail ("1");
92                         } catch (SynchronizationLockException) {
93                         }
94                 }
95
96                 [Test]
97                 public void Dispose_WithWriteLock ()
98                 {
99                         var rwl = new ReaderWriterLockSlim ();
100                         rwl.EnterWriteLock ();
101                         try {
102                                 rwl.Dispose ();
103                                 Assert.Fail ("1");
104                         } catch (SynchronizationLockException) {
105                         }
106                 }
107
108                 [Test]
109                 public void Dispose_UpgradeableReadLock ()
110                 {
111                         var rwl = new ReaderWriterLockSlim ();
112                         rwl.EnterUpgradeableReadLock ();
113                         try {
114                                 rwl.Dispose ();
115                                 Assert.Fail ("1");
116                         } catch (SynchronizationLockException) {
117                         }
118                 }
119
120                 [Test]
121                 public void TryEnterReadLock_OutOfRange ()
122                 {
123                         var v = new ReaderWriterLockSlim ();
124                         try {
125                                 v.TryEnterReadLock (-2);
126                                 Assert.Fail ("1");
127                         } catch (ArgumentOutOfRangeException) {
128                         }
129
130                         try {
131                                 v.TryEnterReadLock (TimeSpan.MaxValue);
132                                 Assert.Fail ("2");
133                         } catch (ArgumentOutOfRangeException) {
134                         }
135
136                         try {
137                                 v.TryEnterReadLock (TimeSpan.MinValue);
138                                 Assert.Fail ("3");
139                         } catch (ArgumentOutOfRangeException) {
140                         }
141                 }
142
143                 [Test]
144                 public void TryEnterUpgradeableReadLock_OutOfRange ()
145                 {
146                         var v = new ReaderWriterLockSlim ();
147                         try {
148                                 v.TryEnterUpgradeableReadLock (-2);
149                                 Assert.Fail ("1");
150                         } catch (ArgumentOutOfRangeException) {
151                         }
152
153                         try {
154                                 v.TryEnterUpgradeableReadLock (TimeSpan.MaxValue);
155                                 Assert.Fail ("2");
156                         } catch (ArgumentOutOfRangeException) {
157                         }
158
159                         try {
160                                 v.TryEnterUpgradeableReadLock (TimeSpan.MinValue);
161                                 Assert.Fail ("3");
162                         } catch (ArgumentOutOfRangeException) {
163                         }
164                 }
165
166                 [Test]
167                 public void TryEnterWriteLock_OutOfRange ()
168                 {
169                         var v = new ReaderWriterLockSlim ();
170                         try {
171                                 v.TryEnterWriteLock (-2);
172                                 Assert.Fail ("1");
173                         } catch (ArgumentOutOfRangeException) {
174                         }
175
176                         try {
177                                 v.TryEnterWriteLock (TimeSpan.MaxValue);
178                                 Assert.Fail ("2");
179                         } catch (ArgumentOutOfRangeException) {
180                         }
181
182                         try {
183                                 v.TryEnterWriteLock (TimeSpan.MinValue);
184                                 Assert.Fail ("3");
185                         } catch (ArgumentOutOfRangeException) {
186                         }
187                 }
188
189                 [Test, ExpectedException (typeof (SynchronizationLockException))]
190                 public void ExitReadLock ()
191                 {
192                         var v = new ReaderWriterLockSlim ();
193                         v.ExitReadLock ();
194                 }
195
196                 [Test, ExpectedException (typeof (SynchronizationLockException))]
197                 public void ExitWriteLock ()
198                 {
199                         var v = new ReaderWriterLockSlim ();
200                         v.ExitWriteLock ();
201                 }
202
203                 [Test]
204                 public void EnterReadLock_NoRecursionError ()
205                 {
206                         var v = new ReaderWriterLockSlim ();
207                         v.EnterReadLock ();
208                         Assert.AreEqual (1, v.RecursiveReadCount);
209
210                         try {
211                                 v.EnterReadLock ();
212                                 Assert.Fail ("1");
213                         } catch (LockRecursionException) {
214                         }
215
216                         try {
217                                 v.EnterWriteLock ();
218                                 Assert.Fail ("2");
219                         } catch (LockRecursionException) {
220                         }
221                 }
222
223                 [Test]
224                 public void EnterReadLock ()
225                 {
226                         var v = new ReaderWriterLockSlim ();
227
228                         v.EnterReadLock ();
229                         Assert.IsTrue (v.IsReadLockHeld, "A");
230                         Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
231                         Assert.AreEqual (1, v.RecursiveReadCount, "A2");
232                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
233                         Assert.AreEqual (0, v.WaitingReadCount, "A4");
234                         Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
235                         Assert.AreEqual (0, v.WaitingWriteCount, "A6");
236                         v.ExitReadLock ();
237
238                         v.EnterReadLock ();
239                         Assert.IsTrue (v.IsReadLockHeld, "B");
240                         Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
241                         Assert.AreEqual (1, v.RecursiveReadCount, "B2");
242                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
243                         Assert.AreEqual (0, v.WaitingReadCount, "B4");
244                         Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
245                         Assert.AreEqual (0, v.WaitingWriteCount, "B6");
246                         v.ExitReadLock ();
247                 }
248
249                 [Test]
250                 public void EnterWriteLock_NoRecursionError ()
251                 {
252                         var v = new ReaderWriterLockSlim ();
253                         v.EnterWriteLock ();
254                         Assert.AreEqual (1, v.RecursiveWriteCount);
255
256                         try {
257                                 v.EnterWriteLock ();
258                                 Assert.Fail ("1");
259                         } catch (LockRecursionException) {
260                         }
261
262                         try {
263                                 v.EnterReadLock ();
264                                 Assert.Fail ("2");
265                         } catch (LockRecursionException) {
266                         }
267                 }
268
269                 [Test]
270                 public void EnterWriteLock ()
271                 {
272                         var v = new ReaderWriterLockSlim ();
273
274                         v.EnterWriteLock ();
275                         Assert.IsTrue (v.IsWriteLockHeld, "A");
276                         Assert.AreEqual (1, v.RecursiveWriteCount, "A1");
277                         Assert.AreEqual (0, v.RecursiveReadCount, "A2");
278                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
279                         Assert.AreEqual (0, v.WaitingReadCount, "A4");
280                         Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
281                         Assert.AreEqual (0, v.WaitingWriteCount, "A6");
282                         v.ExitWriteLock ();
283
284                         v.EnterWriteLock ();
285                         Assert.IsTrue (v.IsWriteLockHeld, "B");
286                         Assert.AreEqual (1, v.RecursiveWriteCount, "B1");
287                         Assert.AreEqual (0, v.RecursiveReadCount, "B2");
288                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
289                         Assert.AreEqual (0, v.WaitingReadCount, "B4");
290                         Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
291                         Assert.AreEqual (0, v.WaitingWriteCount, "B6");
292                         v.ExitWriteLock ();
293                 }
294
295                 [Test]
296                 public void EnterUpgradeableReadLock_NoRecursionError ()
297                 {
298                         var v = new ReaderWriterLockSlim ();
299                         v.EnterUpgradeableReadLock ();
300                         Assert.AreEqual (1, v.RecursiveUpgradeCount);
301
302                         try {
303                                 v.EnterUpgradeableReadLock ();
304                                 Assert.Fail ("2");
305                         } catch (LockRecursionException) {
306                         }
307                 }
308
309                 [Test]
310                 public void EnterUpgradeableReadLock ()
311                 {
312                         var v = new ReaderWriterLockSlim ();
313
314                         v.EnterUpgradeableReadLock ();
315                         Assert.IsTrue (v.IsUpgradeableReadLockHeld, "A");
316                         Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
317                         Assert.AreEqual (0, v.RecursiveReadCount, "A2");
318                         Assert.AreEqual (1, v.RecursiveUpgradeCount, "A3");
319                         Assert.AreEqual (0, v.WaitingReadCount, "A4");
320                         Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
321                         Assert.AreEqual (0, v.WaitingWriteCount, "A6");
322                         v.ExitUpgradeableReadLock ();
323
324                         v.EnterUpgradeableReadLock ();
325                         Assert.IsTrue (v.IsUpgradeableReadLockHeld, "B");
326                         Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
327                         Assert.AreEqual (0, v.RecursiveReadCount, "B2");
328                         Assert.AreEqual (1, v.RecursiveUpgradeCount, "B3");
329                         Assert.AreEqual (0, v.WaitingReadCount, "B4");
330                         Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
331                         Assert.AreEqual (0, v.WaitingWriteCount, "B6");
332
333                         v.EnterReadLock ();
334                         v.ExitUpgradeableReadLock ();
335
336                         Assert.IsTrue (v.IsReadLockHeld, "C");
337                         Assert.AreEqual (0, v.RecursiveWriteCount, "C1");
338                         Assert.AreEqual (1, v.RecursiveReadCount, "C2");
339                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "C3");
340                         Assert.AreEqual (0, v.WaitingReadCount, "C4");
341                         Assert.AreEqual (0, v.WaitingUpgradeCount, "C5");
342                         Assert.AreEqual (0, v.WaitingWriteCount, "C6");
343
344                         v.ExitReadLock ();
345                 }
346
347                 [Test]
348                 public void EnterReadLock_MultiRead ()
349                 {
350                         var v = new ReaderWriterLockSlim ();
351                         int local = 10;
352
353                         var r = from i in Enumerable.Range (1, 30) select new Thread (() => {
354
355                                 // Just to cause some contention
356                                 Thread.Sleep (100);
357
358                                 v.EnterReadLock ();
359
360                                 Assert.AreEqual (10, local);
361                         });
362
363                         var threads = r.ToList ();
364
365                         foreach (var t in threads) {
366                                 t.Start ();
367                         }
368
369                         foreach (var t in threads) {
370                                 // Console.WriteLine (t.ThreadState);
371                                 t.Join ();
372                         }
373                 }
374
375                 [Test]
376                 public void TryEnterWriteLock_WhileReading ()
377                 {
378                         var v = new ReaderWriterLockSlim ();
379                         AutoResetEvent ev = new AutoResetEvent (false);
380                         AutoResetEvent ev2 = new AutoResetEvent (false);
381
382                         Thread t1 = new Thread (() => {
383                                 v.EnterReadLock ();
384                                 ev2.Set ();
385                                 ev.WaitOne ();
386                                 v.ExitReadLock ();
387                         });
388
389                         t1.Start ();
390                         ev2.WaitOne ();
391
392                         Assert.IsFalse (v.TryEnterWriteLock (100));
393                         ev.Set ();
394                         t1.Join ();
395
396                         Assert.IsTrue (v.TryEnterWriteLock (100));
397                 }
398
399                 [Test]
400                 public void EnterWriteLock_MultiRead ()
401                 {
402                         var v = new ReaderWriterLockSlim ();
403                         int local = 10;
404
405                         var r = from i in Enumerable.Range (1, 10) select new Thread (() => {
406                                 v.EnterReadLock ();
407
408                                 Assert.AreEqual (11, local);
409                         });
410
411                         v.EnterWriteLock ();
412
413                         var threads = r.ToList ();
414                         foreach (var t in threads) {
415                                 t.Start ();
416                         }
417
418                         Thread.Sleep (200);
419                         local = 11;
420
421                         // FIXME: Don't rely on Thread.Sleep (200)
422                         Assert.AreEqual (0, v.WaitingWriteCount, "in waiting write");
423                         Assert.AreEqual (10, v.WaitingReadCount, "in waiting read");
424                         Assert.AreEqual (0, v.WaitingUpgradeCount, "in waiting upgrade");
425                         v.ExitWriteLock ();
426
427                         foreach (var t in threads) {
428                                 // Console.WriteLine (t.ThreadState);
429                                 t.Join ();
430                         }
431                 }
432
433                 [Test]
434                 public void EnterWriteLock_After_ExitUpgradeableReadLock ()
435                 {
436                         var v = new ReaderWriterLockSlim ();
437
438                         v.EnterUpgradeableReadLock ();
439                         Assert.IsTrue (v.TryEnterWriteLock (100));
440                         v.ExitWriteLock ();
441                         v.ExitUpgradeableReadLock ();
442                         Assert.IsTrue (v.TryEnterWriteLock (100));
443                         v.ExitWriteLock ();
444                 }
445 #if NET_4_0
446                 [Test]
447                 public void EnterWriteLockWhileInUpgradeAndOtherWaiting ()
448                 {
449                         var v = new ReaderWriterLockSlim ();
450
451                         var task2 = new Task(() => {
452                 v.EnterWriteLock();
453                 v.ExitWriteLock();
454             });
455
456             var task1 = new Task(() =>
457             {
458                 v.EnterUpgradeableReadLock ();
459                 task2.Start ();
460                 Thread.Sleep (100);
461                 v.EnterWriteLock ();
462                 v.ExitWriteLock ();
463                 v.ExitUpgradeableReadLock ();
464             });
465             task1.Start ();
466
467             Assert.IsTrue (task1.Wait (500));
468                 }
469 #endif
470                 [Test]
471                 public void RecursiveReadLockTest ()
472                 {
473                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
474
475                         Assert.IsTrue (v.TryEnterReadLock (100), "#1");
476                         Assert.IsTrue (v.TryEnterReadLock (100), "#2");
477                         Assert.IsTrue (v.TryEnterReadLock (100), "#3");
478
479                         Assert.AreEqual (3, v.RecursiveReadCount);
480                 }
481
482                 [Test]
483                 public void RecursiveReadPlusWriteLockTest ()
484                 {
485                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
486
487                         try {
488                                 v.EnterReadLock ();
489                                 v.EnterWriteLock ();
490                                 Assert.Fail ("1");
491                         } catch (LockRecursionException ex) {
492                                 Assert.IsNotNull (ex, "#1");
493                         }
494                 }
495
496                 [Test]
497                 public void RecursiveReadPlusUpgradeableLockTest ()
498                 {
499                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
500
501                         try {
502                                 v.EnterReadLock ();
503                                 v.EnterUpgradeableReadLock ();
504                                 Assert.Fail ("1");
505                         } catch (LockRecursionException ex) {
506                                 Assert.IsNotNull (ex, "#1");
507                         }
508                 }
509
510                 [Test]
511                 public void RecursiveWriteLockTest ()
512                 {
513                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
514
515                         Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
516                         Assert.IsTrue (v.TryEnterWriteLock (100), "#2");
517                         Assert.IsTrue (v.TryEnterWriteLock (100), "#3");
518
519                         Assert.AreEqual (3, v.RecursiveWriteCount);
520                 }
521
522                 [Test]
523                 public void RecursiveWritePlusReadLockTest ()
524                 {
525                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
526
527                         Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
528                         Assert.AreEqual (1, v.RecursiveWriteCount, "1b");
529                         Assert.AreEqual (0, v.RecursiveReadCount, "1c");
530
531                         Assert.IsTrue (v.TryEnterReadLock (100), "#2");
532                         Assert.AreEqual (1, v.RecursiveWriteCount, "2b");
533                         Assert.AreEqual (1, v.RecursiveReadCount, "2c");
534
535                         Assert.IsTrue (v.TryEnterReadLock (100), "#3");
536                         Assert.AreEqual (1, v.RecursiveWriteCount, "3b");
537                         Assert.AreEqual (2, v.RecursiveReadCount, "3c");
538
539                         v.ExitReadLock ();
540                         Assert.AreEqual (1, v.RecursiveWriteCount, "4b");
541                         Assert.AreEqual (1, v.RecursiveReadCount, "4c");
542                 }
543
544                 [Test]
545                 public void RecursiveUpgradeableReadLockTest ()
546                 {
547                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
548
549                         Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#1");
550                         Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#2");
551                         Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#3");
552
553                         Assert.AreEqual (3, v.RecursiveUpgradeCount);
554                 }
555
556                 [Test]
557                 public void RecursiveReadPropertiesTest ()
558                 {
559                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
560
561                         v.EnterReadLock ();
562                         v.EnterReadLock ();
563
564                         Assert.AreEqual (true, v.IsReadLockHeld, "#1a");
565                         Assert.AreEqual (1, v.CurrentReadCount, "#2a");
566                         Assert.AreEqual (2, v.RecursiveReadCount, "#3a");
567
568                         bool rLock = true;
569                         int cReadCount = -1, rReadCount = -1;
570
571                         Thread t = new Thread ((_) => {
572                                         rLock = v.IsReadLockHeld;
573                                         cReadCount = v.CurrentReadCount;
574                                         rReadCount = v.RecursiveReadCount;
575                                 });
576
577                         t.Start ();
578                         t.Join ();
579
580                         Assert.AreEqual (false, rLock, "#1b");
581                         Assert.AreEqual (1, cReadCount, "#2b");
582                         Assert.AreEqual (0, rReadCount, "#3b");
583                 }
584
585                 [Test]
586                 public void RecursiveUpgradePropertiesTest ()
587                 {
588                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
589
590                         v.EnterUpgradeableReadLock ();
591                         v.EnterUpgradeableReadLock ();
592
593                         Assert.AreEqual (true, v.IsUpgradeableReadLockHeld, "#1a");
594                         Assert.AreEqual (false, v.IsReadLockHeld, "#11a");
595                         Assert.AreEqual (0, v.CurrentReadCount, "#2a");
596                         Assert.AreEqual (2, v.RecursiveUpgradeCount, "#3a");
597
598                         bool upLock = false, rLock = false;
599                         int rCount = -1, rUCount = -1;
600
601                         Thread t = new Thread ((_) => {
602                                         upLock = v.IsUpgradeableReadLockHeld;
603                                         rLock = v.IsReadLockHeld;
604                                         rCount = v.CurrentReadCount;
605                                         rUCount = v.RecursiveUpgradeCount;
606                                 });
607
608                         t.Start ();
609                         t.Join ();
610
611                         Assert.AreEqual (false, upLock, "#1b");
612                         Assert.AreEqual (false, rLock, "#11b");
613                         Assert.AreEqual (0, rCount, "#2b");
614                         Assert.AreEqual (0, rUCount, "#3b");
615                 }
616
617                 [Test]
618                 public void RecursiveWritePropertiesTest ()
619                 {
620                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
621
622                         v.EnterWriteLock ();
623                         v.EnterWriteLock ();
624
625                         Assert.AreEqual (true, v.IsWriteLockHeld, "#1a");
626                         Assert.AreEqual (2, v.RecursiveWriteCount, "#3a");
627
628                         bool wLock = false;
629                         int rWrite = -1;
630
631                         Thread t = new Thread ((_) => {
632                                         wLock = v.IsWriteLockHeld;
633                                         rWrite = v.RecursiveWriteCount;
634                                 });
635
636                         t.Start ();
637                         t.Join ();
638
639                         Assert.AreEqual (false, wLock, "#1b");
640                         Assert.AreEqual (0, rWrite, "#3b");
641                 }
642
643                 [Test]
644                 public void RecursiveEnterExitReadTest ()
645                 {
646                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
647
648                         v.EnterReadLock ();
649                         v.EnterReadLock ();
650                         v.EnterReadLock ();
651
652                         Assert.IsTrue (v.IsReadLockHeld);
653                         Assert.AreEqual (3, v.RecursiveReadCount);
654
655                         v.ExitReadLock ();
656
657                         Assert.IsTrue (v.IsReadLockHeld);
658                         Assert.AreEqual (2, v.RecursiveReadCount);
659                 }
660
661                 [Test]
662                 public void RecursiveEnterExitWriteTest ()
663                 {
664                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
665
666                         v.EnterWriteLock ();
667                         v.EnterWriteLock ();
668                         v.EnterWriteLock ();
669
670                         Assert.IsTrue (v.IsWriteLockHeld);
671                         Assert.AreEqual (3, v.RecursiveWriteCount);
672
673                         v.ExitWriteLock ();
674                         v.ExitWriteLock ();
675
676                         Assert.IsTrue (v.IsWriteLockHeld);
677                         Assert.AreEqual (1, v.RecursiveWriteCount);
678                 }
679
680                 [Test]
681                 public void RecursiveEnterExitUpgradableTest ()
682                 {
683                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
684
685                         v.EnterUpgradeableReadLock ();
686                         v.EnterUpgradeableReadLock ();
687                         v.EnterUpgradeableReadLock ();
688
689                         Assert.IsTrue (v.IsUpgradeableReadLockHeld);
690                         Assert.AreEqual (3, v.RecursiveUpgradeCount);
691
692                         v.ExitUpgradeableReadLock ();
693
694                         Assert.IsTrue (v.IsUpgradeableReadLockHeld);
695                         Assert.AreEqual (2, v.RecursiveUpgradeCount);
696                 }
697
698                 [Test]
699                 public void RecursiveWriteUpgradeReadTest ()
700                 {
701                         var rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
702
703                         rwlock.EnterWriteLock ();
704                         Assert.IsTrue (rwlock.IsWriteLockHeld);
705                         rwlock.EnterUpgradeableReadLock ();
706                         Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
707                         rwlock.EnterReadLock ();
708                         Assert.IsTrue (rwlock.IsReadLockHeld);
709                         rwlock.ExitUpgradeableReadLock();
710                         Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
711                         Assert.IsTrue (rwlock.IsReadLockHeld);
712                         Assert.IsTrue (rwlock.IsWriteLockHeld);
713
714                         rwlock.ExitReadLock ();
715                         Assert.IsTrue (rwlock.IsWriteLockHeld);
716                 }
717
718                 [Test]
719                 public void RecursiveWriteUpgradeTest ()
720                 {
721                         ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
722
723                         rwlock.EnterWriteLock ();
724                         Assert.IsTrue (rwlock.IsWriteLockHeld);
725                         rwlock.EnterUpgradeableReadLock ();
726                         Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
727                         rwlock.ExitUpgradeableReadLock ();
728                         Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
729                         Assert.IsTrue (rwlock.IsWriteLockHeld);
730                         rwlock.ExitWriteLock ();
731                         Assert.IsFalse (rwlock.IsWriteLockHeld);
732                         rwlock.EnterWriteLock ();
733                         Assert.IsTrue (rwlock.IsWriteLockHeld);
734                 }
735
736                 [Test]
737                 public void RecursiveWriteReadAcquisitionInterleaving ()
738                 {
739                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
740
741                         v.EnterWriteLock ();
742                         Assert.IsTrue (v.IsWriteLockHeld, "#1");
743
744                         bool result = true;
745                         var t = new Thread (delegate () {
746                                         result = v.TryEnterReadLock (100);
747                                 });
748                         t.Start ();
749                         t.Join ();
750                         Assert.IsFalse (result, "#2");
751
752                         v.ExitWriteLock ();
753                         t = new Thread (delegate () {
754                                         result = v.TryEnterReadLock (100);
755                                 });
756                         t.Start ();
757                         t.Join ();
758                         Assert.IsTrue (result, "#3");
759                 }
760         }
761 }