Merge pull request #1200 from akoeplinger/remove-jvm
[mono.git] / mcs / class / corlib / Test / System.Threading / ReaderWriterLockTest.cs
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                         
27                         public void Run ()
28                         {
29                                 try
30                                 {
31                                         SecondaryThread();
32                                 }
33                                 catch (Exception ex)
34                                 {
35                                         ResultException = ex;
36                                 }
37                         }
38                         
39                         public void Join ()
40                         {
41                                 RunningThread.Join (5000);
42                                 if (ResultException != null) throw ResultException;
43                         }
44                 }
45                 
46                 void RunThread (ThreadStart ts)
47                 {
48                         ThreadRunner tr = StartThread (ts);
49                         tr.Join ();
50                 }
51                 
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]
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                 
73                 private void IsReaderLockHeld_2 ()
74                 {
75                         Assert.IsTrue (!rwlock.IsReaderLockHeld);
76                 }
77                 
78                 [Test]
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                 
89                 private void IsWriterLockHeld_2 ()
90                 {
91                         Assert.IsTrue (!rwlock.IsWriterLockHeld);
92                 }
93                                 
94                 [Test]
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                 
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                 
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                 
140                 void AcquireLock_writerWorks ()
141                 {
142                         rwlock.AcquireWriterLock (200);
143                         rwlock.ReleaseWriterLock ();
144                 }
145                 
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]
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]
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]
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]
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]
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                 
264                 void ReaderMustWaitWriter_2 ()
265                 {
266                         rwlock.AcquireWriterLock (2000);
267                         rwlock.ReleaseWriterLock ();
268                 }
269                 
270                 [Test]
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]
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                 
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]
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                 
332                 void Bug_55909_bis_Reader ()
333                 {
334                         rwlock.AcquireReaderLock(-1);
335                         Thread.Sleep(2000);
336                         rwlock.ReleaseReaderLock();
337                 }
338
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
348                 void Bug_55909_bis_Writer ()
349                 {
350                         rwlock.AcquireWriterLock(-1);
351                         rwlock.ReleaseWriterLock();
352                 }
353                 
354
355                 [Test]
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]
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 }