[Mono.Posix] Add Syscall.getgrouplist().
[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 TryEnterReadLock_OutOfRange ()
86                 {
87                         var v = new ReaderWriterLockSlim ();
88                         try {
89                                 v.TryEnterReadLock (-2);
90                                 Assert.Fail ("1");
91                         } catch (ArgumentOutOfRangeException) {
92                         }
93
94                         try {
95                                 v.TryEnterReadLock (TimeSpan.MaxValue);
96                                 Assert.Fail ("2");
97                         } catch (ArgumentOutOfRangeException) {
98                         }
99
100                         try {
101                                 v.TryEnterReadLock (TimeSpan.MinValue);
102                                 Assert.Fail ("3");
103                         } catch (ArgumentOutOfRangeException) {
104                         }
105                 }
106
107                 [Test]
108                 public void TryEnterUpgradeableReadLock_OutOfRange ()
109                 {
110                         var v = new ReaderWriterLockSlim ();
111                         try {
112                                 v.TryEnterUpgradeableReadLock (-2);
113                                 Assert.Fail ("1");
114                         } catch (ArgumentOutOfRangeException) {
115                         }
116
117                         try {
118                                 v.TryEnterUpgradeableReadLock (TimeSpan.MaxValue);
119                                 Assert.Fail ("2");
120                         } catch (ArgumentOutOfRangeException) {
121                         }
122
123                         try {
124                                 v.TryEnterUpgradeableReadLock (TimeSpan.MinValue);
125                                 Assert.Fail ("3");
126                         } catch (ArgumentOutOfRangeException) {
127                         }
128                 }
129
130                 [Test]
131                 public void TryEnterWriteLock_OutOfRange ()
132                 {
133                         var v = new ReaderWriterLockSlim ();
134                         try {
135                                 v.TryEnterWriteLock (-2);
136                                 Assert.Fail ("1");
137                         } catch (ArgumentOutOfRangeException) {
138                         }
139
140                         try {
141                                 v.TryEnterWriteLock (TimeSpan.MaxValue);
142                                 Assert.Fail ("2");
143                         } catch (ArgumentOutOfRangeException) {
144                         }
145
146                         try {
147                                 v.TryEnterWriteLock (TimeSpan.MinValue);
148                                 Assert.Fail ("3");
149                         } catch (ArgumentOutOfRangeException) {
150                         }
151                 }
152
153                 [Test, ExpectedException (typeof (SynchronizationLockException))]
154                 public void ExitReadLock ()
155                 {
156                         var v = new ReaderWriterLockSlim ();
157                         v.ExitReadLock ();
158                 }
159
160                 [Test, ExpectedException (typeof (SynchronizationLockException))]
161                 public void ExitWriteLock ()
162                 {
163                         var v = new ReaderWriterLockSlim ();
164                         v.ExitWriteLock ();
165                 }
166
167                 [Test]
168                 public void EnterReadLock_NoRecursionError ()
169                 {
170                         var v = new ReaderWriterLockSlim ();
171                         v.EnterReadLock ();
172                         Assert.AreEqual (1, v.RecursiveReadCount);
173
174                         try {
175                                 v.EnterReadLock ();
176                                 Assert.Fail ("1");
177                         } catch (LockRecursionException) {
178                         }
179
180                         try {
181                                 v.EnterWriteLock ();
182                                 Assert.Fail ("2");
183                         } catch (LockRecursionException) {
184                         }
185                 }
186
187                 [Test]
188                 public void EnterReadLock ()
189                 {
190                         var v = new ReaderWriterLockSlim ();
191
192                         v.EnterReadLock ();
193                         Assert.IsTrue (v.IsReadLockHeld, "A");
194                         Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
195                         Assert.AreEqual (1, v.RecursiveReadCount, "A2");
196                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
197                         Assert.AreEqual (0, v.WaitingReadCount, "A4");
198                         Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
199                         Assert.AreEqual (0, v.WaitingWriteCount, "A6");
200                         v.ExitReadLock ();
201
202                         v.EnterReadLock ();
203                         Assert.IsTrue (v.IsReadLockHeld, "B");
204                         Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
205                         Assert.AreEqual (1, v.RecursiveReadCount, "B2");
206                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
207                         Assert.AreEqual (0, v.WaitingReadCount, "B4");
208                         Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
209                         Assert.AreEqual (0, v.WaitingWriteCount, "B6");
210                         v.ExitReadLock ();
211                 }
212
213                 [Test]
214                 public void EnterWriteLock_NoRecursionError ()
215                 {
216                         var v = new ReaderWriterLockSlim ();
217                         v.EnterWriteLock ();
218                         Assert.AreEqual (1, v.RecursiveWriteCount);
219
220                         try {
221                                 v.EnterWriteLock ();
222                                 Assert.Fail ("1");
223                         } catch (LockRecursionException) {
224                         }
225
226                         try {
227                                 v.EnterReadLock ();
228                                 Assert.Fail ("2");
229                         } catch (LockRecursionException) {
230                         }
231                 }
232
233                 [Test]
234                 public void EnterWriteLock ()
235                 {
236                         var v = new ReaderWriterLockSlim ();
237
238                         v.EnterWriteLock ();
239                         Assert.IsTrue (v.IsWriteLockHeld, "A");
240                         Assert.AreEqual (1, v.RecursiveWriteCount, "A1");
241                         Assert.AreEqual (0, v.RecursiveReadCount, "A2");
242                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
243                         Assert.AreEqual (0, v.WaitingReadCount, "A4");
244                         Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
245                         Assert.AreEqual (0, v.WaitingWriteCount, "A6");
246                         v.ExitWriteLock ();
247
248                         v.EnterWriteLock ();
249                         Assert.IsTrue (v.IsWriteLockHeld, "B");
250                         Assert.AreEqual (1, v.RecursiveWriteCount, "B1");
251                         Assert.AreEqual (0, v.RecursiveReadCount, "B2");
252                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
253                         Assert.AreEqual (0, v.WaitingReadCount, "B4");
254                         Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
255                         Assert.AreEqual (0, v.WaitingWriteCount, "B6");
256                         v.ExitWriteLock ();
257                 }
258
259                 [Test]
260                 public void EnterUpgradeableReadLock_NoRecursionError ()
261                 {
262                         var v = new ReaderWriterLockSlim ();
263                         v.EnterUpgradeableReadLock ();
264                         Assert.AreEqual (1, v.RecursiveUpgradeCount);
265
266                         try {
267                                 v.EnterUpgradeableReadLock ();
268                                 Assert.Fail ("2");
269                         } catch (LockRecursionException) {
270                         }
271                 }
272
273                 [Test]
274                 public void EnterUpgradeableReadLock ()
275                 {
276                         var v = new ReaderWriterLockSlim ();
277
278                         v.EnterUpgradeableReadLock ();
279                         Assert.IsTrue (v.IsUpgradeableReadLockHeld, "A");
280                         Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
281                         Assert.AreEqual (0, v.RecursiveReadCount, "A2");
282                         Assert.AreEqual (1, v.RecursiveUpgradeCount, "A3");
283                         Assert.AreEqual (0, v.WaitingReadCount, "A4");
284                         Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
285                         Assert.AreEqual (0, v.WaitingWriteCount, "A6");
286                         v.ExitUpgradeableReadLock ();
287
288                         v.EnterUpgradeableReadLock ();
289                         Assert.IsTrue (v.IsUpgradeableReadLockHeld, "B");
290                         Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
291                         Assert.AreEqual (0, v.RecursiveReadCount, "B2");
292                         Assert.AreEqual (1, v.RecursiveUpgradeCount, "B3");
293                         Assert.AreEqual (0, v.WaitingReadCount, "B4");
294                         Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
295                         Assert.AreEqual (0, v.WaitingWriteCount, "B6");
296
297                         v.EnterReadLock ();
298                         v.ExitUpgradeableReadLock ();
299
300                         Assert.IsTrue (v.IsReadLockHeld, "C");
301                         Assert.AreEqual (0, v.RecursiveWriteCount, "C1");
302                         Assert.AreEqual (1, v.RecursiveReadCount, "C2");
303                         Assert.AreEqual (0, v.RecursiveUpgradeCount, "C3");
304                         Assert.AreEqual (0, v.WaitingReadCount, "C4");
305                         Assert.AreEqual (0, v.WaitingUpgradeCount, "C5");
306                         Assert.AreEqual (0, v.WaitingWriteCount, "C6");
307
308                         v.ExitReadLock ();
309                 }
310
311                 [Test]
312                 public void EnterReadLock_MultiRead ()
313                 {
314                         var v = new ReaderWriterLockSlim ();
315                         int local = 10;
316
317                         var r = from i in Enumerable.Range (1, 30) select new Thread (() => {
318
319                                 // Just to cause some contention
320                                 Thread.Sleep (100);
321
322                                 v.EnterReadLock ();
323
324                                 Assert.AreEqual (10, local);
325                         });
326
327                         var threads = r.ToList ();
328
329                         foreach (var t in threads) {
330                                 t.Start ();
331                         }
332
333                         foreach (var t in threads) {
334                                 // Console.WriteLine (t.ThreadState);
335                                 t.Join ();
336                         }
337                 }
338
339                 [Test]
340                 public void TryEnterWriteLock_WhileReading ()
341                 {
342                         var v = new ReaderWriterLockSlim ();
343                         AutoResetEvent ev = new AutoResetEvent (false);
344                         AutoResetEvent ev2 = new AutoResetEvent (false);
345
346                         Thread t1 = new Thread (() => {
347                                 v.EnterReadLock ();
348                                 ev2.Set ();
349                                 ev.WaitOne ();
350                                 v.ExitReadLock ();
351                         });
352
353                         t1.Start ();
354                         ev2.WaitOne ();
355
356                         Assert.IsFalse (v.TryEnterWriteLock (100));
357                         ev.Set ();
358                         t1.Join ();
359
360                         Assert.IsTrue (v.TryEnterWriteLock (100));
361                 }
362
363                 [Test]
364                 public void EnterWriteLock_MultiRead ()
365                 {
366                         var v = new ReaderWriterLockSlim ();
367                         int local = 10;
368
369                         var r = from i in Enumerable.Range (1, 10) select new Thread (() => {
370                                 v.EnterReadLock ();
371
372                                 Assert.AreEqual (11, local);
373                         });
374
375                         v.EnterWriteLock ();
376
377                         var threads = r.ToList ();
378                         foreach (var t in threads) {
379                                 t.Start ();
380                         }
381
382                         Thread.Sleep (200);
383                         local = 11;
384
385                         // FIXME: Don't rely on Thread.Sleep (200)
386                         Assert.AreEqual (0, v.WaitingWriteCount, "in waiting write");
387                         Assert.AreEqual (10, v.WaitingReadCount, "in waiting read");
388                         Assert.AreEqual (0, v.WaitingUpgradeCount, "in waiting upgrade");
389                         v.ExitWriteLock ();
390
391                         foreach (var t in threads) {
392                                 // Console.WriteLine (t.ThreadState);
393                                 t.Join ();
394                         }
395                 }
396
397                 [Test]
398                 public void EnterWriteLock_After_ExitUpgradeableReadLock ()
399                 {
400                         var v = new ReaderWriterLockSlim ();
401
402                         v.EnterUpgradeableReadLock ();
403                         Assert.IsTrue (v.TryEnterWriteLock (100));
404                         v.ExitWriteLock ();
405                         v.ExitUpgradeableReadLock ();
406                         Assert.IsTrue (v.TryEnterWriteLock (100));
407                         v.ExitWriteLock ();
408                 }
409 #if NET_4_0
410                 [Test]
411                 public void EnterWriteLockWhileInUpgradeAndOtherWaiting ()
412                 {
413                         var v = new ReaderWriterLockSlim ();
414
415                         var task2 = new Task(() => {
416                 v.EnterWriteLock();
417                 v.ExitWriteLock();
418             });
419
420             var task1 = new Task(() =>
421             {
422                 v.EnterUpgradeableReadLock ();
423                 task2.Start ();
424                 Thread.Sleep (100);
425                 v.EnterWriteLock ();
426                 v.ExitWriteLock ();
427                 v.ExitUpgradeableReadLock ();
428             });
429             task1.Start ();
430
431             Assert.IsTrue (task1.Wait (500));
432                 }
433 #endif
434                 [Test]
435                 public void RecursiveReadLockTest ()
436                 {
437                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
438
439                         Assert.IsTrue (v.TryEnterReadLock (100), "#1");
440                         Assert.IsTrue (v.TryEnterReadLock (100), "#2");
441                         Assert.IsTrue (v.TryEnterReadLock (100), "#3");
442
443                         Assert.AreEqual (3, v.RecursiveReadCount);
444                 }
445
446                 [Test]
447                 public void RecursiveReadPlusWriteLockTest ()
448                 {
449                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
450
451                         try {
452                                 v.EnterReadLock ();
453                                 v.EnterWriteLock ();
454                                 Assert.Fail ("1");
455                         } catch (LockRecursionException ex) {
456                                 Assert.IsNotNull (ex, "#1");
457                         }
458                 }
459
460                 [Test]
461                 public void RecursiveReadPlusUpgradeableLockTest ()
462                 {
463                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
464
465                         try {
466                                 v.EnterReadLock ();
467                                 v.EnterUpgradeableReadLock ();
468                                 Assert.Fail ("1");
469                         } catch (LockRecursionException ex) {
470                                 Assert.IsNotNull (ex, "#1");
471                         }
472                 }
473
474                 [Test]
475                 public void RecursiveWriteLockTest ()
476                 {
477                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
478
479                         Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
480                         Assert.IsTrue (v.TryEnterWriteLock (100), "#2");
481                         Assert.IsTrue (v.TryEnterWriteLock (100), "#3");
482
483                         Assert.AreEqual (3, v.RecursiveWriteCount);
484                 }
485
486                 [Test]
487                 public void RecursiveWritePlusReadLockTest ()
488                 {
489                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
490
491                         Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
492                         Assert.AreEqual (1, v.RecursiveWriteCount, "1b");
493                         Assert.AreEqual (0, v.RecursiveReadCount, "1c");
494
495                         Assert.IsTrue (v.TryEnterReadLock (100), "#2");
496                         Assert.AreEqual (1, v.RecursiveWriteCount, "2b");
497                         Assert.AreEqual (1, v.RecursiveReadCount, "2c");
498
499                         Assert.IsTrue (v.TryEnterReadLock (100), "#3");
500                         Assert.AreEqual (1, v.RecursiveWriteCount, "3b");
501                         Assert.AreEqual (2, v.RecursiveReadCount, "3c");
502
503                         v.ExitReadLock ();
504                         Assert.AreEqual (1, v.RecursiveWriteCount, "4b");
505                         Assert.AreEqual (1, v.RecursiveReadCount, "4c");
506                 }
507
508                 [Test]
509                 public void RecursiveUpgradeableReadLockTest ()
510                 {
511                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
512
513                         Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#1");
514                         Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#2");
515                         Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#3");
516
517                         Assert.AreEqual (3, v.RecursiveUpgradeCount);
518                 }
519
520                 [Test]
521                 public void RecursiveReadPropertiesTest ()
522                 {
523                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
524
525                         v.EnterReadLock ();
526                         v.EnterReadLock ();
527
528                         Assert.AreEqual (true, v.IsReadLockHeld, "#1a");
529                         Assert.AreEqual (1, v.CurrentReadCount, "#2a");
530                         Assert.AreEqual (2, v.RecursiveReadCount, "#3a");
531
532                         bool rLock = true;
533                         int cReadCount = -1, rReadCount = -1;
534
535                         Thread t = new Thread ((_) => {
536                                         rLock = v.IsReadLockHeld;
537                                         cReadCount = v.CurrentReadCount;
538                                         rReadCount = v.RecursiveReadCount;
539                                 });
540
541                         t.Start ();
542                         t.Join ();
543
544                         Assert.AreEqual (false, rLock, "#1b");
545                         Assert.AreEqual (1, cReadCount, "#2b");
546                         Assert.AreEqual (0, rReadCount, "#3b");
547                 }
548
549                 [Test]
550                 public void RecursiveUpgradePropertiesTest ()
551                 {
552                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
553
554                         v.EnterUpgradeableReadLock ();
555                         v.EnterUpgradeableReadLock ();
556
557                         Assert.AreEqual (true, v.IsUpgradeableReadLockHeld, "#1a");
558                         Assert.AreEqual (false, v.IsReadLockHeld, "#11a");
559                         Assert.AreEqual (0, v.CurrentReadCount, "#2a");
560                         Assert.AreEqual (2, v.RecursiveUpgradeCount, "#3a");
561
562                         bool upLock = false, rLock = false;
563                         int rCount = -1, rUCount = -1;
564
565                         Thread t = new Thread ((_) => {
566                                         upLock = v.IsUpgradeableReadLockHeld;
567                                         rLock = v.IsReadLockHeld;
568                                         rCount = v.CurrentReadCount;
569                                         rUCount = v.RecursiveUpgradeCount;
570                                 });
571
572                         t.Start ();
573                         t.Join ();
574
575                         Assert.AreEqual (false, upLock, "#1b");
576                         Assert.AreEqual (false, rLock, "#11b");
577                         Assert.AreEqual (0, rCount, "#2b");
578                         Assert.AreEqual (0, rUCount, "#3b");
579                 }
580
581                 [Test]
582                 public void RecursiveWritePropertiesTest ()
583                 {
584                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
585
586                         v.EnterWriteLock ();
587                         v.EnterWriteLock ();
588
589                         Assert.AreEqual (true, v.IsWriteLockHeld, "#1a");
590                         Assert.AreEqual (2, v.RecursiveWriteCount, "#3a");
591
592                         bool wLock = false;
593                         int rWrite = -1;
594
595                         Thread t = new Thread ((_) => {
596                                         wLock = v.IsWriteLockHeld;
597                                         rWrite = v.RecursiveWriteCount;
598                                 });
599
600                         t.Start ();
601                         t.Join ();
602
603                         Assert.AreEqual (false, wLock, "#1b");
604                         Assert.AreEqual (0, rWrite, "#3b");
605                 }
606
607                 [Test]
608                 public void RecursiveEnterExitReadTest ()
609                 {
610                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
611
612                         v.EnterReadLock ();
613                         v.EnterReadLock ();
614                         v.EnterReadLock ();
615
616                         Assert.IsTrue (v.IsReadLockHeld);
617                         Assert.AreEqual (3, v.RecursiveReadCount);
618
619                         v.ExitReadLock ();
620
621                         Assert.IsTrue (v.IsReadLockHeld);
622                         Assert.AreEqual (2, v.RecursiveReadCount);
623                 }
624
625                 [Test]
626                 public void RecursiveEnterExitWriteTest ()
627                 {
628                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
629
630                         v.EnterWriteLock ();
631                         v.EnterWriteLock ();
632                         v.EnterWriteLock ();
633
634                         Assert.IsTrue (v.IsWriteLockHeld);
635                         Assert.AreEqual (3, v.RecursiveWriteCount);
636
637                         v.ExitWriteLock ();
638                         v.ExitWriteLock ();
639
640                         Assert.IsTrue (v.IsWriteLockHeld);
641                         Assert.AreEqual (1, v.RecursiveWriteCount);
642                 }
643
644                 [Test]
645                 public void RecursiveEnterExitUpgradableTest ()
646                 {
647                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
648
649                         v.EnterUpgradeableReadLock ();
650                         v.EnterUpgradeableReadLock ();
651                         v.EnterUpgradeableReadLock ();
652
653                         Assert.IsTrue (v.IsUpgradeableReadLockHeld);
654                         Assert.AreEqual (3, v.RecursiveUpgradeCount);
655
656                         v.ExitUpgradeableReadLock ();
657
658                         Assert.IsTrue (v.IsUpgradeableReadLockHeld);
659                         Assert.AreEqual (2, v.RecursiveUpgradeCount);
660                 }
661
662                 [Test]
663                 public void RecursiveWriteUpgradeReadTest ()
664                 {
665                         var rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
666
667                         rwlock.EnterWriteLock ();
668                         Assert.IsTrue (rwlock.IsWriteLockHeld);
669                         rwlock.EnterUpgradeableReadLock ();
670                         Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
671                         rwlock.EnterReadLock ();
672                         Assert.IsTrue (rwlock.IsReadLockHeld);
673                         rwlock.ExitUpgradeableReadLock();
674                         Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
675                         Assert.IsTrue (rwlock.IsReadLockHeld);
676                         Assert.IsTrue (rwlock.IsWriteLockHeld);
677
678                         rwlock.ExitReadLock ();
679                         Assert.IsTrue (rwlock.IsWriteLockHeld);
680                 }
681
682                 [Test]
683                 public void RecursiveWriteUpgradeTest ()
684                 {
685                         ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
686
687                         rwlock.EnterWriteLock ();
688                         Assert.IsTrue (rwlock.IsWriteLockHeld);
689                         rwlock.EnterUpgradeableReadLock ();
690                         Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
691                         rwlock.ExitUpgradeableReadLock ();
692                         Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
693                         Assert.IsTrue (rwlock.IsWriteLockHeld);
694                         rwlock.ExitWriteLock ();
695                         Assert.IsFalse (rwlock.IsWriteLockHeld);
696                         rwlock.EnterWriteLock ();
697                         Assert.IsTrue (rwlock.IsWriteLockHeld);
698                 }
699
700                 [Test]
701                 public void RecursiveWriteReadAcquisitionInterleaving ()
702                 {
703                         var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
704
705                         v.EnterWriteLock ();
706                         Assert.IsTrue (v.IsWriteLockHeld, "#1");
707
708                         bool result = true;
709                         var t = new Thread (delegate () {
710                                         result = v.TryEnterReadLock (100);
711                                 });
712                         t.Start ();
713                         t.Join ();
714                         Assert.IsFalse (result, "#2");
715
716                         v.ExitWriteLock ();
717                         t = new Thread (delegate () {
718                                         result = v.TryEnterReadLock (100);
719                                 });
720                         t.Start ();
721                         t.Join ();
722                         Assert.IsTrue (result, "#3");
723                 }
724         }
725 }