9d1790e16ff43bac799e9a30ad5a6143ee007a99
[mono.git] / mono / tests / appdomain-unload.cs
1 using System;
2 using System.Threading;
3 using System.Reflection;
4 using System.Runtime.Remoting;
5
6 [Serializable]
7 public class Foo {
8
9         ~Foo () {
10                 Console.WriteLine ("FINALIZING IN DOMAIN " + AppDomain.CurrentDomain.FriendlyName + ": " + AppDomain.CurrentDomain.IsFinalizingForUnload ());
11         }
12 }
13
14 public class Bar : MarshalByRefObject {
15         public int test (int x) {
16                 Console.WriteLine ("in " + Thread.GetDomain ().FriendlyName);
17                 return x + 1;
18         }
19
20         public void start_wait () {
21                 Action a = delegate () {
22                         Thread.Sleep (10000);
23                 };
24                 a.BeginInvoke (null, null);
25         }
26 }
27
28 [Serializable]
29 public class SlowFinalize {
30
31         ~SlowFinalize () {
32                 Console.WriteLine ("FINALIZE1.");
33                 try {
34                         Thread.Sleep (500);
35                 }
36                 catch (Exception ex) {
37                         Console.WriteLine ("A: " + ex);
38                 }
39                 Console.WriteLine ("FINALIZE2.");
40         }
41 }
42
43 [Serializable]
44 public class AThread {
45
46         public AThread () {
47                 new Thread (new ThreadStart (Run)).Start ();
48         }
49
50         public void Run () {
51                 try {
52                         while (true)
53                                 Thread.Sleep (100);
54                 }
55                 catch (ThreadAbortException ex) {
56                         Console.WriteLine ("Thread aborted correctly.");
57                 }
58         }
59 }
60
61 // A Thread which refuses to die
62 public class BThread : MarshalByRefObject {
63
64         bool stop;
65
66         public BThread () {
67                 new Thread (new ThreadStart (Run)).Start ();
68         }
69
70         public void Stop () {
71                 stop = true;
72         }
73
74         public void Run () {
75                 try {
76                         while (true)
77                                 Thread.Sleep (100);
78                 }
79                 catch (ThreadAbortException ex) {
80                         while (!stop)
81                                 Thread.Sleep (100);
82                 }
83         }
84 }
85
86 public class UnloadThread {
87
88         AppDomain domain;
89
90         public UnloadThread (AppDomain domain) {
91                 this.domain = domain;
92         }
93
94         public void Run () {
95                 Console.WriteLine ("UNLOAD1");
96                 AppDomain.Unload (domain);
97                 Console.WriteLine ("UNLOAD2");
98         }
99 }
100
101 class CrossDomainTester : MarshalByRefObject
102 {
103 }
104
105 public class Tests
106 {
107         public static int Main(string[] args) {
108                 if (args.Length == 0)
109                         return TestDriver.RunTests (typeof (Tests), new String[] { "-v" });
110                 else
111                         return TestDriver.RunTests (typeof (Tests), args);
112         }
113
114         public static int test_0_unload () {
115                 for (int i = 0; i < 10; ++i) {
116                         AppDomain appDomain = AppDomain.CreateDomain("Test-unload" + i);
117
118                         appDomain.CreateInstanceAndUnwrap (
119                                 typeof (CrossDomainTester).Assembly.FullName, "CrossDomainTester");
120
121                         AppDomain.Unload(appDomain);
122                 }
123
124                 return 0;
125         }
126
127         public static int test_0_unload_default () {
128                 try {
129                         AppDomain.Unload (Thread.GetDomain ());
130                 }
131                 catch (CannotUnloadAppDomainException) {
132                         return 0;
133                 }
134                 return 1;
135         }
136
137         public static int test_0_unload_after_unload () {
138                 AppDomain domain = AppDomain.CreateDomain ("Test2");
139                 AppDomain.Unload (domain);
140
141                 try {
142                         AppDomain.Unload (domain);
143                 }
144                 catch (Exception) {
145                         return 0;
146                 }
147
148                 return 1;
149         }
150
151         public static int test_0_is_finalizing () {
152                 AppDomain domain = AppDomain.CreateDomain ("Test-is-finalizing");
153                 object o = domain.CreateInstanceFromAndUnwrap (typeof (Tests).Assembly.Location, "Foo");
154
155                 if (domain.IsFinalizingForUnload ())
156                         return 1;
157
158                 AppDomain.Unload (domain);
159
160                 return 0;
161         }
162
163         public static int test_0_unload_with_active_threads () {
164                 AppDomain domain = AppDomain.CreateDomain ("Test3");
165                 object o = domain.CreateInstanceFromAndUnwrap (typeof (Tests).Assembly.Location, "AThread");
166                 Thread.Sleep (100);
167
168                 AppDomain.Unload (domain);
169
170                 return 0;
171         }
172
173         /* In recent mono versions, there is no unload timeout */
174         /*
175         public static int test_0_unload_with_active_threads_timeout () {
176                 AppDomain domain = AppDomain.CreateDomain ("Test4");
177                 BThread o = (BThread)domain.CreateInstanceFromAndUnwrap (typeof (Tests).Assembly.Location, "BThread");
178                 Thread.Sleep (100);
179
180                 try {
181                         AppDomain.Unload (domain);
182                 }
183                 catch (Exception) {
184                         // Try again
185                         o.Stop ();
186                         AppDomain.Unload (domain);
187                         return 0;
188                 }
189
190                 return 1;
191         }
192         */
193
194         static void Worker (object x) {
195                 Thread.Sleep (100000);
196         }
197
198         public static void invoke_workers () {
199                 for (int i = 0; i < 1; i ++)
200                         ThreadPool.QueueUserWorkItem (Worker);
201         }
202
203         public static int test_0_unload_with_threadpool () {
204                 AppDomain domain = AppDomain.CreateDomain ("test_0_unload_with_threadpool");
205
206                 domain.DoCallBack (new CrossAppDomainDelegate (invoke_workers));
207                 AppDomain.Unload (domain);
208
209                 return 0;
210         }
211
212         /*
213          * This test is not very deterministic since the thread which enqueues
214          * the work item might or might not be inside the domain when the unload
215          * happens. So disable this for now.
216          */
217         /*
218         public static void DoUnload (object state) {
219                 AppDomain.Unload (AppDomain.CurrentDomain);
220         }
221
222         public static void Callback () {
223                 Console.WriteLine (AppDomain.CurrentDomain);
224                 WaitCallback unloadDomainCallback = new WaitCallback (DoUnload);
225                 ThreadPool.QueueUserWorkItem (unloadDomainCallback);
226         }               
227
228         public static int test_0_unload_inside_appdomain_async () {
229                 AppDomain domain = AppDomain.CreateDomain ("Test3");
230
231                 domain.DoCallBack (new CrossAppDomainDelegate (Callback));
232
233                 return 0;
234         }
235         */
236
237         public static void SyncCallback () {
238                 AppDomain.Unload (AppDomain.CurrentDomain);
239         }               
240
241         public static int test_0_unload_inside_appdomain_sync () {
242                 AppDomain domain = AppDomain.CreateDomain ("Test3");
243                 bool caught = false;
244
245                 try {
246                         domain.DoCallBack (new CrossAppDomainDelegate (SyncCallback));
247                 }
248                 catch (AppDomainUnloadedException ex) {
249                         caught = true;
250                 }
251
252                 if (!caught)
253                         return 1;
254
255                 return 0;
256         }
257
258         public static int test_0_invoke_after_unload () {
259                 AppDomain domain = AppDomain.CreateDomain ("DeadInvokeTest");
260                 Bar bar = (Bar)domain.CreateInstanceAndUnwrap (typeof (Tests).Assembly.FullName, "Bar");
261                 int x;
262
263                 if (!RemotingServices.IsTransparentProxy(bar))
264                         return 3;
265
266                 AppDomain.Unload (domain);
267
268                 try {
269                         x = bar.test (123);
270                         if (x == 124)
271                                 return 1;
272                         return 2;
273                 } catch (Exception e) {
274                         return 0;
275                 }
276         }
277
278         public static int test_0_abort_wait () {
279                 AppDomain domain = AppDomain.CreateDomain ("AbortWait");
280                 Bar bar = (Bar)domain.CreateInstanceAndUnwrap (typeof (Tests).Assembly.FullName, "Bar");
281                 int x;
282
283                 bar.start_wait ();
284                 AppDomain.Unload (domain);
285                 return 0;
286         }
287
288         // FIXME: This does not work yet, because the thread is finalized too
289         // early
290         /*
291         public static int test_0_unload_during_unload () {
292                 AppDomain domain = AppDomain.CreateDomain ("Test3");
293                 object o = domain.CreateInstanceFromAndUnwrap (typeof (Tests).Assembly.Location, "SlowFinalize");
294
295                 UnloadThread t = new UnloadThread (domain);
296
297                 // Start unloading in a separate thread
298                 new Thread (new ThreadStart (t.Run)).Start ();
299
300                 Thread.Sleep (100);
301
302                 try {
303                         AppDomain.Unload (domain);
304                 }
305                 catch (Exception) {
306                         Console.WriteLine ("OK");
307                 }
308
309                 return 0;
310         }       
311 */
312 }
313