[tests] Runtime segfaults on Android, probably due to AppDomain.Unload
[mono.git] / mcs / class / corlib / Test / System.Runtime.InteropServices / GCHandleTest.cs
1 //
2 // System.Runtime.InteropServices.GCHandle Test Cases
3 //
4 // Authors:
5 //      Paolo Molaro (lupus@ximian.com)
6 //
7 // Copyright (C) 2005, 2009 Novell, Inc (http://www.novell.com)
8 //
9
10 using NUnit.Framework;
11 using System;
12 using System.Reflection;
13 using System.Runtime.InteropServices;
14 using System.Globalization;
15
16 namespace MonoTests.System.Runtime.InteropServices
17 {
18         [TestFixture]
19         public class GCHandleTest
20         {
21                 // Expected warning, the tests that reference this handle are testing for the default values of the object
22                 #pragma warning disable 649
23                 static GCHandle handle;
24                 #pragma warning restore 649
25                 
26                 [Test]
27                 public void DefaultZeroValue_Allocated ()
28                 {
29                         Assert.IsFalse (handle.IsAllocated, "IsAllocated");
30                 }
31
32                 [Test]
33                 [ExpectedException (typeof (InvalidOperationException))]
34                 public void DefaultZeroValue_Target ()
35                 {
36                         Assert.IsNull (handle.Target, "Target");
37                 }
38
39                 [Test]
40                 public void AllocNull ()
41                 {
42                         IntPtr ptr = (IntPtr) GCHandle.Alloc (null);
43                         Assert.IsFalse (ptr == IntPtr.Zero, "ptr");
44                         GCHandle gch = (GCHandle) ptr;
45                         Assert.IsTrue (gch.IsAllocated, "IsAllocated");
46                         Assert.IsNull (gch.Target, "Target");
47                 }
48
49                 [Test]
50                 public void AllocNullWeakTrack ()
51                 {
52                         GCHandle gch = GCHandle.Alloc (null, GCHandleType.WeakTrackResurrection);
53                         Assert.IsTrue (gch.IsAllocated, "IsAllocated");
54                         Assert.IsNull (gch.Target, "Target");
55                 }
56
57                 [Test]
58                 [ExpectedException (typeof (InvalidOperationException))]
59                 public void AddrOfPinnedObjectNormal ()
60                 {
61                         GCHandle handle = GCHandle.Alloc (new Object (), GCHandleType.Normal);
62                         try {
63                                 IntPtr ptr = handle.AddrOfPinnedObject();
64                         }
65                         finally {
66                                 handle.Free();
67                         }
68                 }
69
70                 [Test]
71                 [ExpectedException (typeof (InvalidOperationException))]
72                 public void AddrOfPinnedObjectWeak ()
73                 {
74                         GCHandle handle = GCHandle.Alloc (new Object (), GCHandleType.Weak);
75                         try {
76                                 IntPtr ptr = handle.AddrOfPinnedObject();
77                         }
78                         finally {
79                                 handle.Free();
80                         }
81                 }
82
83                 [Test]
84                 [ExpectedException (typeof (InvalidOperationException))]
85                 public void AddrOfPinnedObjectWeakTrackResurrection ()
86                 {
87                         GCHandle handle = GCHandle.Alloc (new Object (), GCHandleType.WeakTrackResurrection);
88                         try {
89                                 IntPtr ptr = handle.AddrOfPinnedObject();
90                         }
91                         finally {
92                                 handle.Free();
93                         }
94                 }
95
96                 [Test]
97                 public void AddrOfPinnedObjectNull ()
98                 {
99                         GCHandle handle = GCHandle.Alloc (null, GCHandleType.Pinned);
100                         try {
101                                 IntPtr ptr = handle.AddrOfPinnedObject();
102                                 Assert.AreEqual (new IntPtr (0), ptr);
103                         }
104                         finally {
105                                 handle.Free();
106                         }
107                 }
108
109                 [Test]
110                 [Ignore ("throw non-catchable ExecutionEngineException")]
111                 [ExpectedException (typeof (ExecutionEngineException))]
112                 public void AllocMinusOne ()
113                 {
114                         // -1 is a special value used by the mono runtime
115                         // looks like it's special too in MS CLR (since it will crash)
116                         GCHandle.Alloc (null, (GCHandleType) (-1));
117                 }
118
119                 [Test]
120                 public void AllocInvalidType ()
121                 {
122                         GCHandle gch = GCHandle.Alloc (null, (GCHandleType) Int32.MinValue);
123                         try {
124                                 Assert.IsTrue (gch.IsAllocated, "IsAllocated");
125                                 Assert.IsNull (gch.Target, "Target");
126                         }
127                         finally {
128                                 gch.Free ();
129                         }
130                 }
131 #if !MONOTOUCH
132                 [Test]
133                 [Category("MobileNotWorking")] // SIGSEGV, probably on AppDomain.Unload
134                 public void WeakHandleWorksOnNonRootDomain ()
135                 {
136                         //Console.WriteLine("current app domain: " + AppDomain.CurrentDomain.Id);
137                         AppDomain domain = AppDomain.CreateDomain("testdomain");
138
139                         Assembly ea = Assembly.GetExecutingAssembly ();
140                         domain.CreateInstanceFrom (ea.CodeBase,
141                                 typeof (AssemblyResolveHandler).FullName,
142                                 false,
143                                 BindingFlags.Public | BindingFlags.Instance,
144                                 null,
145                                 new object [] { ea.Location, ea.FullName },
146                                 CultureInfo.InvariantCulture,
147                                 null,
148                                 null);
149
150
151                         var testerType = typeof (CrossDomainGCHandleRunner);
152                         var r = (CrossDomainGCHandleRunner)domain.CreateInstanceAndUnwrap (
153                                 testerType.Assembly.FullName, testerType.FullName, false,
154                                 BindingFlags.Public | BindingFlags.Instance, null, new object [0],
155                                 CultureInfo.InvariantCulture, new object [0], null);
156
157
158                         Assert.IsTrue (r.RunTest (), "#1");
159                         AppDomain.Unload (domain);
160                 }
161
162                 public class CrossDomainGCHandleRunner : MarshalByRefObject {
163                         public bool RunTest () {
164                                 object o = new object();
165                                 GCHandle gcHandle = GCHandle.Alloc (o, GCHandleType.Weak);
166                                 IntPtr intPtr = (IntPtr)gcHandle;
167                                 
168                                 try {
169                                         object target = GCHandle.FromIntPtr(intPtr).Target;
170                                         return true;
171                                 } catch (Exception) {}
172                                 return false;
173                         }
174                 }
175                 
176                 [Serializable ()]
177                 class AssemblyResolveHandler
178                 {
179                         public AssemblyResolveHandler (string assemblyFile, string assemblyName)
180                         {
181                                 _assemblyFile = assemblyFile;
182                                 _assemblyName = assemblyName;
183
184                                 AppDomain.CurrentDomain.AssemblyResolve +=
185                                         new ResolveEventHandler (ResolveAssembly);
186                         }
187
188                         private Assembly ResolveAssembly (object sender, ResolveEventArgs args)
189                         {
190                                 if (args.Name == _assemblyName)
191                                         return Assembly.LoadFrom (_assemblyFile);
192
193                                 return null;
194                         }
195
196                         private readonly string _assemblyFile;
197                         private readonly string _assemblyName;
198                 }
199 #endif
200         }
201
202 }
203