Merge pull request #301 from directhex/master
[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                 static GCHandle handle;
22
23                 [Test]
24                 public void DefaultZeroValue_Allocated ()
25                 {
26                         Assert.IsFalse (handle.IsAllocated, "IsAllocated");
27                 }
28
29                 [Test]
30                 [ExpectedException (typeof (InvalidOperationException))]
31                 public void DefaultZeroValue_Target ()
32                 {
33                         Assert.IsNull (handle.Target, "Target");
34                 }
35
36                 [Test]
37                 public void AllocNull ()
38                 {
39                         IntPtr ptr = (IntPtr) GCHandle.Alloc (null);
40                         Assert.IsFalse (ptr == IntPtr.Zero, "ptr");
41                         GCHandle gch = (GCHandle) ptr;
42                         Assert.IsTrue (gch.IsAllocated, "IsAllocated");
43                         Assert.IsNull (gch.Target, "Target");
44                 }
45
46                 [Test]
47                 public void AllocNullWeakTrack ()
48                 {
49                         GCHandle gch = GCHandle.Alloc (null, GCHandleType.WeakTrackResurrection);
50                         Assert.IsTrue (gch.IsAllocated, "IsAllocated");
51                         Assert.IsNull (gch.Target, "Target");
52                 }
53
54                 [Test]
55                 [ExpectedException (typeof (InvalidOperationException))]
56                 public void AddrOfPinnedObjectNormal ()
57                 {
58                         GCHandle handle = GCHandle.Alloc (new Object (), GCHandleType.Normal);
59                         try {
60                                 IntPtr ptr = handle.AddrOfPinnedObject();
61                         }
62                         finally {
63                                 handle.Free();
64                         }
65                 }
66
67                 [Test]
68                 [ExpectedException (typeof (InvalidOperationException))]
69                 public void AddrOfPinnedObjectWeak ()
70                 {
71                         GCHandle handle = GCHandle.Alloc (new Object (), GCHandleType.Weak);
72                         try {
73                                 IntPtr ptr = handle.AddrOfPinnedObject();
74                         }
75                         finally {
76                                 handle.Free();
77                         }
78                 }
79
80                 [Test]
81                 [ExpectedException (typeof (InvalidOperationException))]
82                 public void AddrOfPinnedObjectWeakTrackResurrection ()
83                 {
84                         GCHandle handle = GCHandle.Alloc (new Object (), GCHandleType.WeakTrackResurrection);
85                         try {
86                                 IntPtr ptr = handle.AddrOfPinnedObject();
87                         }
88                         finally {
89                                 handle.Free();
90                         }
91                 }
92
93                 [Test]
94                 public void AddrOfPinnedObjectNull ()
95                 {
96                         GCHandle handle = GCHandle.Alloc (null, GCHandleType.Pinned);
97                         try {
98                                 IntPtr ptr = handle.AddrOfPinnedObject();
99                                 Assert.AreEqual (new IntPtr (0), ptr);
100                         }
101                         finally {
102                                 handle.Free();
103                         }
104                 }
105
106                 [Test]
107                 [Ignore ("throw non-catchable ExecutionEngineException")]
108                 [ExpectedException (typeof (ExecutionEngineException))]
109                 public void AllocMinusOne ()
110                 {
111                         // -1 is a special value used by the mono runtime
112                         // looks like it's special too in MS CLR (since it will crash)
113                         GCHandle.Alloc (null, (GCHandleType) (-1));
114                 }
115
116                 [Test]
117                 public void AllocInvalidType ()
118                 {
119                         GCHandle gch = GCHandle.Alloc (null, (GCHandleType) Int32.MinValue);
120                         try {
121                                 Assert.IsTrue (gch.IsAllocated, "IsAllocated");
122                                 Assert.IsNull (gch.Target, "Target");
123                         }
124                         finally {
125                                 gch.Free ();
126                         }
127                 }
128
129                 [Test]
130                 public void WeakHandleWorksOnNonRootDomain ()
131                 {
132                         //Console.WriteLine("current app domain: " + AppDomain.CurrentDomain.Id);
133                         AppDomain domain = AppDomain.CreateDomain("testdomain");
134
135                         Assembly ea = Assembly.GetExecutingAssembly ();
136                         domain.CreateInstanceFrom (ea.CodeBase,
137                                 typeof (AssemblyResolveHandler).FullName,
138                                 false,
139                                 BindingFlags.Public | BindingFlags.Instance,
140                                 null,
141                                 new object [] { ea.Location, ea.FullName },
142                                 CultureInfo.InvariantCulture,
143                                 null,
144                                 null);
145
146
147                         var testerType = typeof (CrossDomainGCHandleRunner);
148                         var r = (CrossDomainGCHandleRunner)domain.CreateInstanceAndUnwrap (
149                                 testerType.Assembly.FullName, testerType.FullName, false,
150                                 BindingFlags.Public | BindingFlags.Instance, null, new object [0],
151                                 CultureInfo.InvariantCulture, new object [0], null);
152
153
154                         Assert.IsTrue (r.RunTest (), "#1");
155                         AppDomain.Unload (domain);
156                 }
157
158                 public class CrossDomainGCHandleRunner : MarshalByRefObject {
159                         public bool RunTest () {
160                                 object o = new object();
161                                 GCHandle gcHandle = GCHandle.Alloc (o, GCHandleType.Weak);
162                                 IntPtr intPtr = (IntPtr)gcHandle;
163                                 
164                                 try {
165                                         object target = GCHandle.FromIntPtr(intPtr).Target;
166                                         return true;
167                                 } catch (Exception) {}
168                                 return false;
169                         }
170                 }
171                 
172                 [Serializable ()]
173                 class AssemblyResolveHandler
174                 {
175                         public AssemblyResolveHandler (string assemblyFile, string assemblyName)
176                         {
177                                 _assemblyFile = assemblyFile;
178                                 _assemblyName = assemblyName;
179
180                                 AppDomain.CurrentDomain.AssemblyResolve +=
181                                         new ResolveEventHandler (ResolveAssembly);
182                         }
183
184                         private Assembly ResolveAssembly (object sender, ResolveEventArgs args)
185                         {
186                                 if (args.Name == _assemblyName)
187                                         return Assembly.LoadFrom (_assemblyFile);
188
189                                 return null;
190                         }
191
192                         private readonly string _assemblyFile;
193                         private readonly string _assemblyName;
194                 }
195         }
196
197 }
198