// DynamicMethodTest.cs - NUnit Test Cases for the DynamicMethod class
//
// Gert Driesen (drieseng@users.sourceforge.net)
+// Konrad Kruczynski
//
// (C) 2006 Novell
-#if NET_2_0
using System;
using System.Reflection;
using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Diagnostics;
+using System.Runtime.ExceptionServices;
using NUnit.Framework;
}
}
+ [Test]
+ public void OwnerCantBeArray ()
+ {
+ TestOwner (typeof (int[]));
+ }
+
+ [Test]
+ public void OwnerCantBeInterface ()
+ {
+ TestOwner (typeof (global::System.Collections.IEnumerable));
+ }
+
+ private void TestOwner (Type owner)
+ {
+ try {
+ new DynamicMethod ("Name", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
+ typeof(void), new Type[] { }, owner, true);
+ Assert.Fail (string.Format ("Created dynamic method with owner being {0}.", owner));
+ } catch (ArgumentException) {
+ }
+ }
+
[Test] // bug #78253
public void DynamicMethodReference ()
{
m1.Invoke(null, new object[] { 5 });
}
+
+ // Disabl known warning, the Field is never used directly from C#
+ #pragma warning disable 414
+ class Host {
+ static string Field = "foo";
+ }
+ #pragma warning restore 414
+ [Test]
+ [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297416
+ public void TestOwnerMemberAccess ()
+ {
+ DynamicMethod method = new DynamicMethod ("GetField",
+ typeof (string), new Type [0], typeof (Host));
+
+ ILGenerator il = method.GetILGenerator ();
+ il.Emit (OpCodes.Ldsfld, typeof (Host).GetField (
+ "Field", BindingFlags.Static | BindingFlags.NonPublic));
+ il.Emit (OpCodes.Ret);
+
+ string ret = (string) method.Invoke (null, new object [] {});
+ Assert.AreEqual ("foo", ret, "#1");
+ }
+
+ [Test]
+ public void AnonHosted ()
+ {
+ DynamicMethod hello = new DynamicMethod ("Hello",
+ typeof (int),
+ new Type[] { typeof (string) });
+ ILGenerator helloIL = hello.GetILGenerator ();
+ helloIL.Emit (OpCodes.Ldc_I4_2);
+ helloIL.Emit (OpCodes.Ret);
+
+ HelloInvoker hi =
+ (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
+ int ret = hi ("Hello, World!");
+ Assert.AreEqual (2, ret);
+
+ object[] invokeArgs = { "Hello, World!" };
+ object objRet = hello.Invoke (null, invokeArgs);
+ Assert.AreEqual (2, objRet);
+ }
+
+ public delegate int IntInvoker();
+
+ public class Foo<T> {
+ public virtual int Test () { return 99; }
+ }
+
+ [Test]
+ public void ConstrainedPrexixDoesntCrash () //bug #529238
+ {
+ Type foo = typeof (Foo<int>);
+
+ DynamicMethod dm = new DynamicMethod ("Hello", typeof (int), null);
+ ILGenerator ilgen = dm.GetILGenerator ();
+ ilgen.DeclareLocal (foo);
+ ilgen.Emit (OpCodes.Newobj, foo.GetConstructor (new Type [0]));
+ ilgen.Emit (OpCodes.Stloc_0);
+ ilgen.Emit (OpCodes.Ldloca_S, 0);
+ ilgen.Emit (OpCodes.Constrained, foo);
+ ilgen.Emit (OpCodes.Callvirt, foo.GetMethod ("Test"));
+ ilgen.Emit (OpCodes.Ret);
+
+ IntInvoker hi = (IntInvoker) dm.CreateDelegate (typeof (IntInvoker));
+ Assert.AreEqual (99, hi (), "#1");
+ }
+
+ // #575955
+ [Test]
+ public void Module_GetMethod () {
+ AssemblyName assemblyName = new AssemblyName ();
+ assemblyName.Name = "foo";
+
+ AssemblyBuilder assembly =
+ AppDomain.CurrentDomain.DefineDynamicAssembly (
+ assemblyName, AssemblyBuilderAccess.RunAndSave);
+
+ ModuleBuilder module = assembly.DefineDynamicModule ("foo.dll");
+
+ var d = new DynamicMethod ("foo", typeof (int), new Type [] { typeof (int[,]) }, module);
+ var ig = d.GetILGenerator ();
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldc_I4, 1);
+ ig.Emit (OpCodes.Ldc_I4, 1);
+ ig.Emit (OpCodes.Call, module.GetArrayMethod (typeof (int[,]), "Get", CallingConventions.Standard, typeof (int), new Type [] { typeof (int), typeof (int) }));
+ ig.Emit (OpCodes.Ret);
+
+ var del = (Func<int[,], int>)d.CreateDelegate (typeof (Func<int[,], int>));
+ int[,] arr = new int [10, 10];
+ arr [1, 1] = 5;
+ Assert.AreEqual (5, del (arr));
+ }
+
+ [Test]
+ [Category ("NotWorking")]
+ public void InvalidUnicodeName ()
+ {
+ var name = new StringBuilder ().Append ('\udf45').Append ('\ud808');
+ var method = new DynamicMethod (name.ToString (), typeof (bool), new Type [0]);
+ var il = method.GetILGenerator ();
+ il.Emit (OpCodes.Ldc_I4_1);
+ il.Emit (OpCodes.Ret);
+
+ var function = (Func<bool>) method.CreateDelegate (typeof (Func<bool>));
+
+ Assert.IsTrue (function ());
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidOperationException))]
+ public void GetMethodBody ()
+ {
+ var method = new DynamicMethod ("method", typeof (object), new Type [] { typeof (object) });
+
+ var il = method.GetILGenerator ();
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Ret);
+
+ var f = (Func<object, object>) method.CreateDelegate (typeof (Func<object, object>));
+ f.Method.GetMethodBody ();
+ }
+
+ public delegate object RetObj();
+ [Test] //#640702
+ public void GetCurrentMethodWorksWithDynamicMethods ()
+ {
+ DynamicMethod dm = new DynamicMethod("Foo", typeof(object), null);
+ ILGenerator ilgen = dm.GetILGenerator();
+ ilgen.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod"));
+ ilgen.Emit(OpCodes.Ret);
+ RetObj del = (RetObj)dm.CreateDelegate(typeof(RetObj));
+ MethodInfo res = (MethodInfo)del();
+ Assert.AreEqual (dm.Name, res.Name, "#1");
+
+ }
+
+ [StructLayout (LayoutKind.Explicit)]
+ struct SizeOfTarget {
+ [FieldOffset (0)] public int X;
+ [FieldOffset (4)] public int Y;
+ }
+
+ [Test]
+ public void SizeOf ()
+ {
+ var method = new DynamicMethod ("", typeof (int), Type.EmptyTypes);
+ var il = method.GetILGenerator ();
+ il.Emit (OpCodes.Sizeof, typeof (SizeOfTarget));
+ il.Emit (OpCodes.Ret);
+
+ var func = (Func<int>) method.CreateDelegate (typeof (Func<int>));
+ var point_size = func ();
+
+ Assert.AreEqual (8, point_size);
+ }
+
+ class TypedRefTarget {
+ public string Name;
+ }
+
+ class ExceptionHandling_Test_Support
+ {
+ public static Exception Caught;
+ public static string CaughtStackTrace;
+
+ public static void ThrowMe ()
+ {
+ Caught = null;
+ CaughtStackTrace = null;
+ throw new Exception("test");
+ }
+
+ public static void Handler (Exception e)
+ {
+ Caught = e;
+ CaughtStackTrace = e.StackTrace.ToString ();
+ }
+ }
+
+ [Test]
+ public void ExceptionHandling ()
+ {
+ var method = new DynamicMethod ("", typeof(void), new[] { typeof(int) }, typeof (DynamicMethodTest));
+ var ig = method.GetILGenerator ();
+
+ ig.BeginExceptionBlock();
+ ig.Emit(OpCodes.Call, typeof(ExceptionHandling_Test_Support).GetMethod("ThrowMe"));
+
+ ig.BeginCatchBlock(typeof(Exception));
+ ig.Emit(OpCodes.Call, typeof(ExceptionHandling_Test_Support).GetMethod("Handler"));
+ ig.EndExceptionBlock();
+
+ ig.Emit(OpCodes.Ret);
+
+ var invoke = (Action<int>) method.CreateDelegate (typeof(Action<int>));
+ invoke (456324);
+
+ Assert.IsNotNull (ExceptionHandling_Test_Support.Caught, "#1");
+ Assert.AreEqual (2, ExceptionHandling_Test_Support.CaughtStackTrace.Split (new[] { Environment.NewLine }, StringSplitOptions.None).Length, "#2");
+
+ var st = new StackTrace (ExceptionHandling_Test_Support.Caught, 0, true);
+
+ // Caught stack trace when dynamic method is gone
+ Assert.AreEqual (ExceptionHandling_Test_Support.CaughtStackTrace, st.ToString (), "#3");
+
+ // Catch handler stack trace inside dynamic method match
+ Assert.AreEqual (ExceptionHandling_Test_Support.Caught.StackTrace, st.ToString (), "#4");
+ }
+
+ class ExceptionHandlingWithExceptionDispatchInfo_Test_Support
+ {
+ public static Exception Caught;
+ public static string CaughtStackTrace;
+
+ public static void ThrowMe ()
+ {
+ Caught = null;
+ CaughtStackTrace = null;
+
+ Exception e;
+ try {
+ throw new Exception("test");
+ } catch (Exception e2) {
+ e = e2;
+ }
+
+ var edi = ExceptionDispatchInfo.Capture(e);
+
+ edi.Throw();
+ }
+
+ public static void Handler (Exception e)
+ {
+ var split = e.StackTrace.Split (new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
+ Assert.AreEqual (5, split.Length, "#1");
+ Assert.IsTrue (split [1].Contains ("---"), "#2");
+ }
+ }
+
+ [Test]
+ public void ExceptionHandlingWithExceptionDispatchInfo ()
+ {
+ var method = new DynamicMethod ("", typeof(void), new[] { typeof(int) }, typeof (DynamicMethodTest));
+ var ig = method.GetILGenerator ();
+
+ ig.BeginExceptionBlock();
+ ig.Emit(OpCodes.Call, typeof(ExceptionHandlingWithExceptionDispatchInfo_Test_Support).GetMethod("ThrowMe"));
+
+ ig.BeginCatchBlock(typeof(Exception));
+ ig.Emit(OpCodes.Call, typeof(ExceptionHandlingWithExceptionDispatchInfo_Test_Support).GetMethod("Handler"));
+ ig.EndExceptionBlock();
+
+ ig.Emit(OpCodes.Ret);
+
+ var invoke = (Action<int>) method.CreateDelegate (typeof(Action<int>));
+ invoke (444);
+ }
+
+#if !MONODROID
+ // RUNTIME: crash
+ [Test]
+ public void TypedRef ()
+ {
+ var method = new DynamicMethod ("", typeof (TypedRefTarget), new [] {typeof (TypedRefTarget)}, true);
+ var il = method.GetILGenerator ();
+ var tr = il.DeclareLocal (typeof (TypedReference));
+
+ il.Emit (OpCodes.Ldarga, 0);
+ il.Emit (OpCodes.Mkrefany, typeof (TypedRefTarget));
+ il.Emit (OpCodes.Stloc, tr);
+
+ il.Emit (OpCodes.Ldloc, tr);
+ il.Emit (OpCodes.Call, GetType ().GetMethod ("AssertTypedRef", BindingFlags.NonPublic | BindingFlags.Static));
+
+ il.Emit (OpCodes.Ldloc, tr);
+ il.Emit (OpCodes.Refanyval, typeof (TypedRefTarget));
+ il.Emit (OpCodes.Ldobj, typeof (TypedRefTarget));
+ il.Emit (OpCodes.Ret);
+
+ var f = (Func<TypedRefTarget, TypedRefTarget>) method.CreateDelegate (typeof (Func<TypedRefTarget, TypedRefTarget>));
+
+ var target = new TypedRefTarget { Name = "Foo" };
+ var rt = f (target);
+
+ Assert.AreEqual (target, rt);
+ }
+
+ private static void AssertTypedRef (TypedReference tr)
+ {
+ Assert.AreEqual (typeof (TypedRefTarget), TypedReference.GetTargetType (tr));
+ }
+#endif
}
}
-#endif