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