Correctly handle abandoned mutexes on non-Windows platforms
[mono.git] / mcs / class / corlib / Test / System.Threading / MutexTest.cs
1 // MutexTest.cs - NUnit Test Cases for System.Threading.Mutex\r
2 //\r
3 // Eduardo Garcia Cebollero <kiwnix@yahoo.es>\r
4 //\r
5 // (C) Eduardo Garcia Cebollero\r
6 // \r
7 \r
8 using System;\r
9 using System.Threading;\r
10 \r
11 using NUnit.Framework;\r
12 \r
13 namespace MonoTests.System.Threading\r
14 {\r
15         [TestFixture]\r
16         public class MutexTest\r
17         {\r
18                 //Auxiliary Classes (Future Threads)\r
19                 private class ConcClass\r
20                 {\r
21                         public int id;\r
22                         public Mutex mut;\r
23                         public bool abandoned_exception;\r
24                         public ConcClass(int id,Mutex mut)\r
25                         {\r
26                                 this.id = id;\r
27                                 this.mut = mut;\r
28                         }\r
29                         public void Wait()\r
30                         {\r
31                                 mut.WaitOne();\r
32                         }\r
33                         public void Signal()\r
34                         {\r
35                                 mut.ReleaseMutex();\r
36                         }\r
37                 }\r
38                 private class ConcClassLoop: ConcClass\r
39                 {\r
40                         public int marker;\r
41 \r
42                         public ConcClassLoop(int id,Mutex mut) : \r
43                                 base(id,mut) \r
44                                 {\r
45                                         this.marker = 0;\r
46                                 }\r
47                         \r
48                         public void WithoutWait()\r
49                         {\r
50                                 this.marker = this.id;\r
51                                 this.Signal();\r
52                         }\r
53 \r
54 \r
55                         public void Loop()\r
56                         {\r
57                                 while (this.marker<100)\r
58                                 {\r
59                                         this.Wait();\r
60                                         this.marker++;\r
61                                         this.Signal();\r
62                                 }\r
63                         }\r
64 \r
65                         public void WaitAndForget()\r
66                         {\r
67                                 try {\r
68                                         this.Wait();\r
69                                 } catch (AbandonedMutexException) {\r
70                                         this.abandoned_exception = true;\r
71                                 }\r
72 \r
73                                 this.marker = id;\r
74                         }\r
75                         public void WaitAndWait()\r
76                         {\r
77                                 mut.WaitOne();\r
78                                 this.marker = this.id;\r
79                                 mut.WaitOne();\r
80                                 this.marker = this.id+1;\r
81                         }\r
82                 }\r
83 \r
84                 [Test]\r
85                 public void TestCtor1()\r
86                 {\r
87                         Mutex Sem = new Mutex();\r
88                 }\r
89 \r
90 // These tests produce mutex release errors\r
91 /**\r
92                 [Test]\r
93                 public void TestCtorDefaultValue()\r
94                 {\r
95                         Mutex Sem = new Mutex();\r
96                         ConcClassLoop class1 = new ConcClassLoop(1,Sem);\r
97                         Thread thread1 = new Thread(new ThreadStart(class1.WithoutWait));\r
98                         thread1.Start();\r
99                         while(thread1.IsAlive);\r
100                         Assert.AreEqual(class1.id,class1.marker);\r
101                 }\r
102 \r
103                 [Test]\r
104                 public void TestCtorCtor2()\r
105                 {\r
106                         Mutex Sem = new Mutex(false);\r
107                         ConcClassLoop class1 = new ConcClassLoop(1,Sem);\r
108                         Thread thread1 = new Thread(new ThreadStart(class1.WithoutWait));\r
109                         thread1.Start();\r
110                         while(thread1.IsAlive);\r
111                         Assert.AreEqual(class1.id,class1.marker);\r
112                 }\r
113         \r
114                 [Test]\r
115                 public void TestCtorCtor3()\r
116                 {\r
117                         Mutex Sem = new Mutex(true);\r
118                         ConcClassLoop class1 = new ConcClassLoop(1,Sem);\r
119                         Thread thread1 = new Thread(new ThreadStart(class1.WithoutWait));\r
120                         thread1.Start();\r
121                         while(thread1.IsAlive);\r
122                         Assert.AreEqual(class1.id,class1.marker);\r
123                 }\r
124 */\r
125 \r
126                 [Test]\r
127                 public void TestWaitAndSignal1()\r
128                 {\r
129                         Mutex Sem = new Mutex (false);\r
130                         ConcClassLoop class1 = new ConcClassLoop (1, Sem);\r
131                         Thread thread1 = new Thread (new ThreadStart (class1.Loop));\r
132                         try {\r
133                                 thread1.Start ();\r
134                                 TestUtil.WaitForNotAlive (thread1, "");\r
135                                 Assert.AreEqual (100, class1.marker);\r
136                         } finally {\r
137 #if MONO_FEATURE_THREAD_ABORT\r
138                                 thread1.Abort ();\r
139 #else\r
140                                 thread1.Interrupt ();\r
141 #endif\r
142                         }\r
143                 }\r
144 \r
145                 [Test]\r
146                 public void TestWaitAndForget1()\r
147                 {\r
148                         Mutex Sem = new Mutex(false);\r
149                         ConcClassLoop class1 = new ConcClassLoop(1,Sem);\r
150                         ConcClassLoop class2 = new ConcClassLoop(2,Sem);\r
151                         Thread thread1 = new Thread(new ThreadStart(class1.WaitAndForget));\r
152                         Thread thread2 = new Thread(new ThreadStart(class2.WaitAndForget));\r
153                         \r
154                         try {\r
155                                 thread1.Start();\r
156                                 TestUtil.WaitForNotAlive (thread1, "t1");\r
157                                 Assert.IsFalse (class1.abandoned_exception, "e1");\r
158         \r
159                                 thread2.Start();\r
160                                 TestUtil.WaitForNotAlive (thread2, "t2");\r
161                                 Assert.IsTrue (class2.abandoned_exception, "e2");\r
162                         \r
163                                 Assert.AreEqual (class2.id, class2.marker);\r
164                         } finally {\r
165 #if MONO_FEATURE_THREAD_ABORT\r
166                                 thread1.Abort ();\r
167                                 thread2.Abort ();\r
168 #else\r
169                                 thread1.Interrupt ();\r
170                                 thread2.Interrupt ();\r
171 #endif\r
172                         }\r
173                 }\r
174 \r
175                 [Test]\r
176                 public void TestHandle()\r
177                 {\r
178                         Mutex Sem = new Mutex();\r
179                         IntPtr Handle = Sem.Handle;\r
180                 }\r
181 \r
182                 [Test] // bug #79358\r
183                 public void DoubleRelease ()\r
184                 {\r
185                         Mutex mutex = new Mutex ();\r
186                         mutex.WaitOne ();\r
187                         mutex.ReleaseMutex ();\r
188 \r
189                         try {\r
190                                 mutex.ReleaseMutex ();\r
191                                 Assert.Fail ("#1");\r
192                         } catch (ApplicationException ex) {\r
193                                 Assert.AreEqual (typeof (ApplicationException), ex.GetType (), "#2");\r
194                         }\r
195                 }\r
196         }\r
197 }\r