| 
									
										
										
										
											2014-08-13 10:39:27 +01:00
										 |  |  | // | 
					
						
							|  |  |  | // System.Runtime.InteropServices.GCHandle Test Cases | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Authors: | 
					
						
							|  |  |  | // 	Paolo Molaro (lupus@ximian.com) | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Copyright (C) 2005, 2009 Novell, Inc (http://www.novell.com) | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using NUnit.Framework; | 
					
						
							|  |  |  | using System; | 
					
						
							|  |  |  | using System.Reflection; | 
					
						
							|  |  |  | using System.Runtime.InteropServices; | 
					
						
							|  |  |  | using System.Globalization; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace MonoTests.System.Runtime.InteropServices | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	[TestFixture] | 
					
						
							|  |  |  | 	public class GCHandleTest | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2015-01-13 10:44:36 +00:00
										 |  |  | 		// Expected warning, the tests that reference this handle are testing for the default values of the object | 
					
						
							|  |  |  | 		#pragma warning disable 649 | 
					
						
							| 
									
										
										
										
											2014-08-13 10:39:27 +01:00
										 |  |  | 		static GCHandle handle; | 
					
						
							| 
									
										
										
										
											2015-01-13 10:44:36 +00:00
										 |  |  | 		#pragma warning restore 649 | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2014-08-13 10:39:27 +01:00
										 |  |  | 		[Test] | 
					
						
							|  |  |  | 		public void DefaultZeroValue_Allocated () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Assert.IsFalse (handle.IsAllocated, "IsAllocated"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		[Test] | 
					
						
							|  |  |  | 		[ExpectedException (typeof (InvalidOperationException))] | 
					
						
							|  |  |  | 		public void DefaultZeroValue_Target () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Assert.IsNull (handle.Target, "Target"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		[Test] | 
					
						
							|  |  |  | 		public void AllocNull () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			IntPtr ptr = (IntPtr) GCHandle.Alloc (null); | 
					
						
							|  |  |  | 			Assert.IsFalse (ptr == IntPtr.Zero, "ptr"); | 
					
						
							|  |  |  | 			GCHandle gch = (GCHandle) ptr; | 
					
						
							|  |  |  | 			Assert.IsTrue (gch.IsAllocated, "IsAllocated"); | 
					
						
							|  |  |  | 			Assert.IsNull (gch.Target, "Target"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		[Test] | 
					
						
							|  |  |  | 		public void AllocNullWeakTrack () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			GCHandle gch = GCHandle.Alloc (null, GCHandleType.WeakTrackResurrection); | 
					
						
							|  |  |  | 			Assert.IsTrue (gch.IsAllocated, "IsAllocated"); | 
					
						
							|  |  |  | 			Assert.IsNull (gch.Target, "Target"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		[Test] | 
					
						
							|  |  |  | 		[ExpectedException (typeof (InvalidOperationException))] | 
					
						
							|  |  |  | 		public void AddrOfPinnedObjectNormal () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			GCHandle handle = GCHandle.Alloc (new Object (), GCHandleType.Normal); | 
					
						
							|  |  |  | 			try { | 
					
						
							|  |  |  | 				IntPtr ptr = handle.AddrOfPinnedObject(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			finally { | 
					
						
							|  |  |  | 				handle.Free(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		[Test] | 
					
						
							|  |  |  | 		[ExpectedException (typeof (InvalidOperationException))] | 
					
						
							|  |  |  | 		public void AddrOfPinnedObjectWeak () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			GCHandle handle = GCHandle.Alloc (new Object (), GCHandleType.Weak); | 
					
						
							|  |  |  | 			try { | 
					
						
							|  |  |  | 				IntPtr ptr = handle.AddrOfPinnedObject(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			finally { | 
					
						
							|  |  |  | 				handle.Free(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		[Test] | 
					
						
							|  |  |  | 		[ExpectedException (typeof (InvalidOperationException))] | 
					
						
							|  |  |  | 		public void AddrOfPinnedObjectWeakTrackResurrection () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			GCHandle handle = GCHandle.Alloc (new Object (), GCHandleType.WeakTrackResurrection); | 
					
						
							|  |  |  | 			try { | 
					
						
							|  |  |  | 				IntPtr ptr = handle.AddrOfPinnedObject(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			finally { | 
					
						
							|  |  |  | 				handle.Free(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		[Test] | 
					
						
							|  |  |  | 		public void AddrOfPinnedObjectNull () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			GCHandle handle = GCHandle.Alloc (null, GCHandleType.Pinned); | 
					
						
							|  |  |  | 			try { | 
					
						
							|  |  |  | 				IntPtr ptr = handle.AddrOfPinnedObject(); | 
					
						
							|  |  |  | 				Assert.AreEqual (new IntPtr (0), ptr); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			finally { | 
					
						
							|  |  |  | 				handle.Free(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		[Test] | 
					
						
							|  |  |  | 		[Ignore ("throw non-catchable ExecutionEngineException")] | 
					
						
							|  |  |  | 		[ExpectedException (typeof (ExecutionEngineException))] | 
					
						
							|  |  |  | 		public void AllocMinusOne () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			// -1 is a special value used by the mono runtime | 
					
						
							|  |  |  | 			// looks like it's special too in MS CLR (since it will crash) | 
					
						
							|  |  |  | 			GCHandle.Alloc (null, (GCHandleType) (-1)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		[Test] | 
					
						
							|  |  |  | 		public void AllocInvalidType () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			GCHandle gch = GCHandle.Alloc (null, (GCHandleType) Int32.MinValue); | 
					
						
							|  |  |  | 			try { | 
					
						
							|  |  |  | 				Assert.IsTrue (gch.IsAllocated, "IsAllocated"); | 
					
						
							|  |  |  | 				Assert.IsNull (gch.Target, "Target"); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			finally { | 
					
						
							|  |  |  | 				gch.Free (); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-10 11:41:01 +00:00
										 |  |  | #if !MONOTOUCH && !FULL_AOT_RUNTIME | 
					
						
							| 
									
										
										
										
											2014-08-13 10:39:27 +01:00
										 |  |  | 		[Test] | 
					
						
							| 
									
										
										
										
											2015-08-26 07:17:56 -04:00
										 |  |  | 		[Category("MobileNotWorking")] // SIGSEGV, probably on AppDomain.Unload | 
					
						
							| 
									
										
										
										
											2014-08-13 10:39:27 +01:00
										 |  |  | 		public void WeakHandleWorksOnNonRootDomain () | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			//Console.WriteLine("current app domain: " + AppDomain.CurrentDomain.Id); | 
					
						
							|  |  |  | 			AppDomain domain = AppDomain.CreateDomain("testdomain"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Assembly ea = Assembly.GetExecutingAssembly (); | 
					
						
							|  |  |  | 			domain.CreateInstanceFrom (ea.CodeBase, | 
					
						
							|  |  |  | 				typeof (AssemblyResolveHandler).FullName, | 
					
						
							|  |  |  | 				false, | 
					
						
							|  |  |  | 				BindingFlags.Public | BindingFlags.Instance, | 
					
						
							|  |  |  | 				null, | 
					
						
							|  |  |  | 				new object [] { ea.Location, ea.FullName }, | 
					
						
							|  |  |  | 				CultureInfo.InvariantCulture, | 
					
						
							|  |  |  | 				null, | 
					
						
							|  |  |  | 				null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var testerType = typeof (CrossDomainGCHandleRunner); | 
					
						
							|  |  |  | 			var r = (CrossDomainGCHandleRunner)domain.CreateInstanceAndUnwrap ( | 
					
						
							|  |  |  | 				testerType.Assembly.FullName, testerType.FullName, false, | 
					
						
							|  |  |  | 				BindingFlags.Public | BindingFlags.Instance, null, new object [0], | 
					
						
							|  |  |  | 				CultureInfo.InvariantCulture, new object [0], null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Assert.IsTrue (r.RunTest (), "#1"); | 
					
						
							|  |  |  | 			AppDomain.Unload (domain); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		public class CrossDomainGCHandleRunner : MarshalByRefObject { | 
					
						
							|  |  |  | 			public bool RunTest () { | 
					
						
							|  |  |  | 				object o = new object(); | 
					
						
							|  |  |  | 				GCHandle gcHandle = GCHandle.Alloc (o, GCHandleType.Weak); | 
					
						
							|  |  |  | 				IntPtr intPtr = (IntPtr)gcHandle; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				try { | 
					
						
							|  |  |  | 					object target = GCHandle.FromIntPtr(intPtr).Target; | 
					
						
							|  |  |  | 					return true; | 
					
						
							|  |  |  | 				} catch (Exception) {} | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		[Serializable ()] | 
					
						
							|  |  |  | 		class AssemblyResolveHandler | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			public AssemblyResolveHandler (string assemblyFile, string assemblyName) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				_assemblyFile = assemblyFile; | 
					
						
							|  |  |  | 				_assemblyName = assemblyName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				AppDomain.CurrentDomain.AssemblyResolve += | 
					
						
							|  |  |  | 					new ResolveEventHandler (ResolveAssembly); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			private Assembly ResolveAssembly (object sender, ResolveEventArgs args) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (args.Name == _assemblyName) | 
					
						
							|  |  |  | 					return Assembly.LoadFrom (_assemblyFile); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return null; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			private readonly string _assemblyFile; | 
					
						
							|  |  |  | 			private readonly string _assemblyName; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |