Apply Gert's version of the AutoResetEvent, and merge his test
[mono.git] / mcs / class / corlib / Test / System.Threading / ReaderWriterLockTest.cs
1 //\r
2 // ReaderWriterLockTest.cs - NUnit Test Cases for System.Threading.ReaderWriterLock\r
3 //\r
4 // Author:\r
5 //   Lluis Sanchez Gual (lluis@ximian.com)\r
6 //\r
7 // (C) 2004 Novell, Inc (http://www.novell.com)\r
8 // \r
9 \r
10 using NUnit.Framework;\r
11 using System;\r
12 using System.Threading;\r
13 \r
14 namespace MonoTests.System.Threading\r
15 {\r
16         [TestFixture]
17         // DISABLED due to random hangs. Do not renable until you can run this
18         // a few thousand times on an SMP box.
19         [Category ("NotWorking")]
20         public class ReaderWriterLockTest : Assertion\r
21         {\r
22                 ReaderWriterLock rwlock;\r
23                 \r
24                 class ThreadRunner\r
25                 {\r
26                         public ThreadStart SecondaryThread;\r
27                         public Exception ResultException;\r
28                         public Thread RunningThread;\r
29                         \r
30                         public void Run ()\r
31                         {\r
32                                 try\r
33                                 {\r
34                                         SecondaryThread();\r
35                                 }\r
36                                 catch (Exception ex)\r
37                                 {\r
38                                         ResultException = ex;\r
39                                 }\r
40                         }\r
41                         \r
42                         public void Join ()\r
43                         {\r
44                                 RunningThread.Join (5000);\r
45                                 if (ResultException != null) throw ResultException;\r
46                         }\r
47                 }\r
48                 \r
49                 void RunThread (ThreadStart ts)\r
50                 {\r
51                         ThreadRunner tr = StartThread (ts);\r
52                         tr.Join ();\r
53                 }\r
54                 \r
55                 ThreadRunner StartThread (ThreadStart ts)\r
56                 {\r
57                         ThreadRunner tr = new ThreadRunner();\r
58                         tr.SecondaryThread = ts;\r
59                         Thread t = new Thread (new ThreadStart (tr.Run));\r
60                         tr.RunningThread = t;\r
61                         t.Start ();\r
62                         return tr;\r
63                 }\r
64                 \r
65                 [Test]
66                 public void TestIsReaderLockHeld ()\r
67                 {\r
68                         rwlock = new ReaderWriterLock ();\r
69                         Assert ("a1", !rwlock.IsReaderLockHeld);\r
70                         rwlock.AcquireReaderLock (500);\r
71                         Assert ("a2", rwlock.IsReaderLockHeld);\r
72                         RunThread (new ThreadStart (IsReaderLockHeld_2));\r
73                         rwlock.ReleaseReaderLock ();\r
74                 }\r
75                 \r
76                 private void IsReaderLockHeld_2 ()\r
77                 {\r
78                         Assert ("a3", !rwlock.IsReaderLockHeld);\r
79                 }\r
80                 \r
81                 [Test]\r
82                 public void TestIsWriterLockHeld ()\r
83                 {\r
84                         rwlock = new ReaderWriterLock ();\r
85                         Assert ("a1", !rwlock.IsWriterLockHeld);\r
86                         rwlock.AcquireWriterLock (500);\r
87                         Assert ("a2", rwlock.IsWriterLockHeld);\r
88                         RunThread (new ThreadStart (IsWriterLockHeld_2));\r
89                         rwlock.ReleaseWriterLock ();\r
90                 }\r
91                 \r
92                 private void IsWriterLockHeld_2 ()\r
93                 {\r
94                         Assert ("a3", !rwlock.IsWriterLockHeld);\r
95                 }\r
96                                 \r
97                 [Test]\r
98                 public void TestAcquireLocks ()\r
99                 {\r
100                         rwlock = new ReaderWriterLock ();\r
101                         rwlock.AcquireReaderLock (500);\r
102                         rwlock.AcquireReaderLock (500);\r
103                         rwlock.ReleaseReaderLock ();\r
104                         Assert ("a1", rwlock.IsReaderLockHeld);                 \r
105                         RunThread (new ThreadStart (AcquireLock_readerWorks));\r
106                         Assert ("a2", rwlock.IsReaderLockHeld);\r
107                         \r
108                         RunThread (new ThreadStart (AcquireLock_writerFails));\r
109                         rwlock.ReleaseReaderLock ();\r
110                         Assert ("a6", !rwlock.IsReaderLockHeld);\r
111                         \r
112                         RunThread (new ThreadStart (AcquireLock_writerWorks));\r
113                         \r
114                         rwlock.AcquireWriterLock (200);\r
115                         RunThread (new ThreadStart (AcquireLock_writerFails));\r
116                         RunThread (new ThreadStart (AcquireLock_readerFails));\r
117                         rwlock.ReleaseWriterLock ();\r
118                 }\r
119                 \r
120                 void AcquireLock_readerWorks ()\r
121                 {\r
122                         rwlock.AcquireReaderLock (200);\r
123                         rwlock.AcquireReaderLock (200);\r
124                         rwlock.ReleaseReaderLock ();\r
125                         Assert ("a3", rwlock.IsReaderLockHeld);\r
126                         rwlock.ReleaseReaderLock ();\r
127                         Assert ("a4", !rwlock.IsReaderLockHeld);\r
128                 }\r
129                 \r
130                 void AcquireLock_writerFails ()\r
131                 {\r
132                         try\r
133                         {\r
134                                 rwlock.AcquireWriterLock (200);\r
135                                 rwlock.ReleaseWriterLock ();\r
136                                 throw new Exception ("Should not get writer lock");\r
137                         }\r
138                         catch (Exception)\r
139                         {\r
140                         }\r
141                 }\r
142                 \r
143                 void AcquireLock_writerWorks ()\r
144                 {\r
145                         rwlock.AcquireWriterLock (200);\r
146                         rwlock.ReleaseWriterLock ();\r
147                 }\r
148                 \r
149                 void AcquireLock_readerFails ()\r
150                 {\r
151                         try\r
152                         {\r
153                                 rwlock.AcquireReaderLock (200);\r
154                                 rwlock.ReleaseReaderLock ();\r
155                                 throw new Exception ("Should not get reader lock");\r
156                         }\r
157                         catch (Exception)\r
158                         {\r
159                         }\r
160                 }\r
161                 \r
162                 [Test]\r
163                 public void TestReleaseRestoreReaderLock ()\r
164                 {\r
165                         rwlock = new ReaderWriterLock ();\r
166                         rwlock.AcquireReaderLock (500);\r
167                         rwlock.AcquireReaderLock (500);\r
168                         Assert ("r1", rwlock.IsReaderLockHeld);\r
169                         \r
170                         LockCookie co = rwlock.ReleaseLock ();\r
171                         RunThread (new ThreadStart (AcquireLock_writerWorks));\r
172                         \r
173                         rwlock.RestoreLock (ref co);\r
174                         RunThread (new ThreadStart (AcquireLock_writerFails));\r
175                         \r
176                         rwlock.ReleaseReaderLock ();\r
177                         Assert ("r2", rwlock.IsReaderLockHeld);\r
178                         rwlock.ReleaseReaderLock ();\r
179                         Assert ("r3", !rwlock.IsReaderLockHeld);\r
180                 }\r
181                 \r
182                 [Test]\r
183                 public void TestReleaseRestoreWriterLock ()\r
184                 {\r
185                         rwlock = new ReaderWriterLock ();\r
186                         rwlock.AcquireWriterLock (500);\r
187                         rwlock.AcquireWriterLock (500);\r
188                         Assert ("w1", rwlock.IsWriterLockHeld);\r
189                         \r
190                         LockCookie co = rwlock.ReleaseLock ();\r
191                         RunThread (new ThreadStart (AcquireLock_readerWorks));\r
192                         \r
193                         rwlock.RestoreLock (ref co);\r
194                         RunThread (new ThreadStart (AcquireLock_readerFails));\r
195                         \r
196                         rwlock.ReleaseWriterLock ();\r
197                         Assert ("w2", rwlock.IsWriterLockHeld);\r
198                         rwlock.ReleaseWriterLock ();\r
199                         Assert ("w3", !rwlock.IsWriterLockHeld);\r
200                 }\r
201                 \r
202                 [Test]\r
203                 public void TestUpgradeDowngradeLock ()\r
204                 {\r
205                         rwlock = new ReaderWriterLock ();\r
206                         rwlock.AcquireReaderLock (200);\r
207                         rwlock.AcquireReaderLock (200);\r
208                         \r
209                         LockCookie co = rwlock.UpgradeToWriterLock (200);\r
210                         Assert ("u1", !rwlock.IsReaderLockHeld);\r
211                         Assert ("u2", rwlock.IsWriterLockHeld);\r
212                         RunThread (new ThreadStart (AcquireLock_writerFails));\r
213                         \r
214                         rwlock.DowngradeFromWriterLock (ref co);\r
215                         Assert ("u3", rwlock.IsReaderLockHeld);\r
216                         Assert ("u4", !rwlock.IsWriterLockHeld);\r
217                         RunThread (new ThreadStart (AcquireLock_readerWorks));\r
218                         \r
219                         rwlock.ReleaseReaderLock ();\r
220                         Assert ("u5", rwlock.IsReaderLockHeld);\r
221                         rwlock.ReleaseReaderLock ();\r
222                         Assert ("u6", !rwlock.IsReaderLockHeld);\r
223                 }\r
224                 \r
225                 [Test]\r
226                 public void TestReaderInsideWriter ()\r
227                 {\r
228                         // Reader acquires and releases work like the writer equivalent\r
229                         \r
230                         rwlock = new ReaderWriterLock ();\r
231                         rwlock.AcquireWriterLock (-1);\r
232                         rwlock.AcquireReaderLock (-1);\r
233                         Assert ("u1", !rwlock.IsReaderLockHeld);\r
234                         Assert ("u2", rwlock.IsWriterLockHeld);\r
235                         rwlock.AcquireReaderLock (-1);\r
236                         Assert ("u3", !rwlock.IsReaderLockHeld);\r
237                         Assert ("u4", rwlock.IsWriterLockHeld);\r
238                         rwlock.ReleaseWriterLock ();\r
239                         Assert ("u5", !rwlock.IsReaderLockHeld);\r
240                         Assert ("u6", rwlock.IsWriterLockHeld);\r
241                         rwlock.ReleaseReaderLock ();\r
242                         Assert ("u7", !rwlock.IsReaderLockHeld);\r
243                         Assert ("u8", rwlock.IsWriterLockHeld);\r
244                         rwlock.ReleaseReaderLock ();\r
245                         Assert ("u9", !rwlock.IsReaderLockHeld);\r
246                         Assert ("u10", !rwlock.IsWriterLockHeld);\r
247                 }\r
248                 \r
249                 [Test]\r
250                 public void TestReaderMustWaitWriter ()\r
251                 {\r
252                         // A thread cannot get the reader lock if there are other threads\r
253                         // waiting for the writer lock.\r
254                         \r
255                         rwlock = new ReaderWriterLock ();\r
256                         rwlock.AcquireWriterLock (200);\r
257                         \r
258                         ThreadRunner tr = StartThread (new ThreadStart (ReaderMustWaitWriter_2));\r
259                         Thread.Sleep (200);\r
260                         \r
261                         RunThread (new ThreadStart (AcquireLock_readerFails));\r
262                         \r
263                         rwlock.ReleaseReaderLock ();\r
264                         tr.Join ();\r
265                 }\r
266                 \r
267                 void ReaderMustWaitWriter_2 ()\r
268                 {\r
269                         rwlock.AcquireWriterLock (2000);\r
270                         rwlock.ReleaseWriterLock ();\r
271                 }\r
272                 \r
273                 [Test]\r
274                 public void TestBug_55911 ()\r
275                 {\r
276                         rwlock = new ReaderWriterLock ();\r
277                         \r
278                         rwlock.AcquireReaderLock (Timeout.Infinite);\r
279                         try {\r
280                                 LockCookie lc = rwlock.UpgradeToWriterLock (Timeout.Infinite);\r
281                         }\r
282                         finally { rwlock.ReleaseReaderLock(); }\r
283                         \r
284                         rwlock.AcquireReaderLock (Timeout.Infinite);\r
285                         try {\r
286                                 LockCookie lc = rwlock.UpgradeToWriterLock (Timeout.Infinite);\r
287                         }\r
288                         finally { rwlock.ReleaseReaderLock(); }\r
289                 }\r
290                 \r
291                 [Test]\r
292                 public void TestBug_55909 ()\r
293                 {\r
294                         rwlock = new ReaderWriterLock ();\r
295                         ThreadRunner tr = StartThread (new ThreadStart(Bug_55909_Thread2));\r
296                         Thread.Sleep (200);\r
297                         rwlock.AcquireReaderLock (Timeout.Infinite);\r
298                         try {\r
299                                 LockCookie lc = rwlock.UpgradeToWriterLock (Timeout.Infinite);\r
300                                 Thread.Sleep (500);\r
301                         }\r
302                         finally { rwlock.ReleaseReaderLock(); }\r
303                         \r
304                         tr.Join ();\r
305                 }\r
306                 \r
307                 public void Bug_55909_Thread2 ()\r
308                 {\r
309                         rwlock.AcquireReaderLock(Timeout.Infinite);\r
310                         try {\r
311                                 Thread.Sleep (1000);\r
312                                 LockCookie lc = rwlock.UpgradeToWriterLock (Timeout.Infinite);\r
313                                 Thread.Sleep (500);\r
314                         }\r
315                         finally { rwlock.ReleaseReaderLock(); }\r
316                 }\r
317                 \r
318                 [Test]\r
319                 public void TestBug_55909_bis ()\r
320                 {\r
321                         rwlock = new ReaderWriterLock ();\r
322                         ThreadRunner tr1 = StartThread (new ThreadStart(Bug_55909_bis_ReaderWriter));\r
323                         Thread.Sleep(100);\r
324                         ThreadRunner tr2 = StartThread (new ThreadStart(Bug_55909_bis_Reader));\r
325                         Thread.Sleep(100);\r
326                         ThreadRunner tr3 = StartThread (new ThreadStart(Bug_55909_bis_Writer));\r
327                         Thread.Sleep(100);\r
328                         ThreadRunner tr4 = StartThread (new ThreadStart(Bug_55909_bis_Reader));\r
329                         tr1.Join ();\r
330                         tr2.Join ();\r
331                         tr3.Join ();\r
332                         tr4.Join ();\r
333                 }\r
334                 \r
335                 void Bug_55909_bis_Reader ()\r
336                 {\r
337                         rwlock.AcquireReaderLock(-1);\r
338                         Thread.Sleep(2000);\r
339                         rwlock.ReleaseReaderLock();\r
340                 }\r
341 \r
342                 void Bug_55909_bis_ReaderWriter ()\r
343                 {\r
344                         rwlock.AcquireReaderLock(-1);\r
345                         LockCookie lc = rwlock.UpgradeToWriterLock(-1);\r
346                         Thread.Sleep(1000);\r
347                         rwlock.DowngradeFromWriterLock(ref lc);\r
348                         rwlock.ReleaseReaderLock();\r
349                 }\r
350 \r
351                 void Bug_55909_bis_Writer ()\r
352                 {\r
353                         rwlock.AcquireWriterLock(-1);\r
354                         rwlock.ReleaseWriterLock();\r
355                 }\r
356                 \r
357         }\r
358 }