2 // DynamicMethodTest.cs - NUnit Test Cases for the DynamicMethod class
4 // Gert Driesen (drieseng@users.sourceforge.net)
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Runtime.InteropServices;
16 using NUnit.Framework;
18 namespace MonoTests.System.Reflection.Emit
21 public class DynamicMethodTest
23 private delegate int HelloInvoker (string msg);
26 public void Constructor1_Name_Null ()
29 new DynamicMethod (null,
31 new Type[] { typeof (string) },
32 typeof (DynamicMethodTest).Module);
34 } catch (ArgumentNullException ex) {
35 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
36 Assert.AreEqual ("name", ex.ParamName, "#3");
37 Assert.IsNull (ex.InnerException, "#4");
42 public void Constructor2_Name_Null ()
45 new DynamicMethod (null,
47 new Type[] { typeof (string) },
48 typeof (DynamicMethodTest));
50 } catch (ArgumentNullException ex) {
51 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
52 Assert.AreEqual ("name", ex.ParamName, "#3");
53 Assert.IsNull (ex.InnerException, "#4");
58 public void Constructor3_Name_Null ()
61 new DynamicMethod (null,
63 new Type[] { typeof (string) },
64 typeof (DynamicMethodTest).Module, true);
66 } catch (ArgumentNullException ex) {
67 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
68 Assert.AreEqual ("name", ex.ParamName, "#3");
69 Assert.IsNull (ex.InnerException, "#4");
74 public void Constructor4_Name_Null ()
77 new DynamicMethod (null,
79 new Type[] { typeof (string) },
80 typeof (DynamicMethodTest), true);
82 } catch (ArgumentNullException ex) {
83 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
84 Assert.AreEqual ("name", ex.ParamName, "#3");
85 Assert.IsNull (ex.InnerException, "#4");
90 public void Constructor5_Name_Null ()
93 new DynamicMethod (null,
94 MethodAttributes.Public | MethodAttributes.Static,
95 CallingConventions.Standard,
97 new Type[] { typeof (string) },
98 typeof (DynamicMethodTest).Module, true);
100 } catch (ArgumentNullException ex) {
101 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
102 Assert.AreEqual ("name", ex.ParamName, "#3");
103 Assert.IsNull (ex.InnerException, "#4");
108 public void Constructor6_Name_Null ()
111 new DynamicMethod (null,
112 MethodAttributes.Public | MethodAttributes.Static,
113 CallingConventions.Standard,
115 new Type[] { typeof (string) },
116 typeof (DynamicMethodTest), true);
118 } catch (ArgumentNullException ex) {
119 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
120 Assert.AreEqual ("name", ex.ParamName, "#3");
121 Assert.IsNull (ex.InnerException, "#4");
126 public void OwnerCantBeArray ()
128 TestOwner (typeof (int[]));
132 public void OwnerCantBeInterface ()
134 TestOwner (typeof (global::System.Collections.IEnumerable));
137 private void TestOwner (Type owner)
140 new DynamicMethod ("Name", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
141 typeof(void), new Type[] { }, owner, true);
142 Assert.Fail (string.Format ("Created dynamic method with owner being {0}.", owner));
143 } catch (ArgumentException) {
148 public void DynamicMethodReference ()
150 DynamicMethod hello = new DynamicMethod ("Hello",
152 new Type[] { typeof (string) },
153 typeof (DynamicMethodTest).Module);
154 Assert.IsNull (hello.DeclaringType, "#1");
156 DynamicMethod write = new DynamicMethod ("Write",
158 new Type[] { typeof (string) },
159 typeof (DynamicMethodTest));
160 Assert.IsNull (hello.DeclaringType, "#2");
162 MethodInfo invokeWrite = write.GetBaseDefinition ();
164 ILGenerator helloIL = hello.GetILGenerator ();
165 helloIL.Emit (OpCodes.Ldarg_0);
166 helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
167 helloIL.Emit (OpCodes.Ret);
169 ILGenerator writeIL = write.GetILGenerator ();
170 writeIL.Emit (OpCodes.Ldc_I4_2);
171 writeIL.Emit (OpCodes.Ret);
174 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
175 int ret = hi ("Hello, World!");
176 Assert.AreEqual (2, ret, "#3");
178 object[] invokeArgs = { "Hello, World!" };
179 object objRet = hello.Invoke (null, invokeArgs);
180 Assert.AreEqual (2, objRet, "#4");
184 public void EmptyMethodBody ()
186 DynamicMethod hello = new DynamicMethod ("Hello",
188 new Type[] { typeof (string) },
189 typeof (DynamicMethodTest).Module);
190 object[] invokeArgs = { "Hello, World!" };
194 hello.Invoke (null, invokeArgs);
196 } catch (InvalidOperationException) {
200 hello.GetILGenerator ();
202 hello.Invoke (null, invokeArgs);
204 } catch (InvalidOperationException) {
208 private delegate string ReturnString (string msg);
209 private delegate void DoNothing (string msg);
211 private static string private_method (string s) {
216 public void SkipVisibility ()
218 DynamicMethod hello = new DynamicMethod ("Hello",
220 new Type[] { typeof (string) },
221 typeof (DynamicMethodTest).Module, true);
223 ILGenerator helloIL = hello.GetILGenerator ();
224 helloIL.Emit (OpCodes.Ldarg_0);
225 helloIL.EmitCall (OpCodes.Call, typeof (DynamicMethodTest).GetMethod ("private_method", BindingFlags.Static|BindingFlags.NonPublic), null);
226 helloIL.Emit (OpCodes.Ret);
229 (ReturnString) hello.CreateDelegate (typeof (ReturnString));
230 Assert.AreEqual ("ABCD", del ("ABCD"));
234 public void ReturnType_Null ()
236 DynamicMethod hello = new DynamicMethod ("Hello",
238 new Type[] { typeof (string) },
239 typeof (DynamicMethodTest).Module, true);
240 Assert.AreEqual (typeof (void), hello.ReturnType, "#1");
242 ILGenerator helloIL = hello.GetILGenerator ();
243 helloIL.Emit (OpCodes.Ret);
245 DoNothing dn = (DoNothing) hello.CreateDelegate (typeof (DoNothing));
248 object[] invokeArgs = { "Hello, World!" };
249 object objRet = hello.Invoke (null, invokeArgs);
250 Assert.IsNull (objRet, "#2");
254 public void Name_Empty ()
256 DynamicMethod hello = new DynamicMethod (string.Empty,
258 new Type[] { typeof (string) },
259 typeof (DynamicMethodTest).Module);
260 Assert.AreEqual (string.Empty, hello.Name, "#1");
262 DynamicMethod write = new DynamicMethod ("Write",
264 new Type[] { typeof (string) },
265 typeof (DynamicMethodTest));
267 MethodInfo invokeWrite = write.GetBaseDefinition ();
269 ILGenerator helloIL = hello.GetILGenerator ();
270 helloIL.Emit (OpCodes.Ldarg_0);
271 helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
272 helloIL.Emit (OpCodes.Ret);
274 ILGenerator writeIL = write.GetILGenerator ();
275 writeIL.Emit (OpCodes.Ldc_I4_2);
276 writeIL.Emit (OpCodes.Ret);
279 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
280 int ret = hi ("Hello, World!");
281 Assert.AreEqual (2, ret, "#2");
283 object[] invokeArgs = { "Hello, World!" };
284 object objRet = hello.Invoke (null, invokeArgs);
285 Assert.AreEqual (2, objRet, "#3");
289 public void Circular_Refs () {
290 DynamicMethod m1 = new DynamicMethod("f1", typeof(int), new Type[] { typeof (int) },
292 DynamicMethod m2 = new DynamicMethod("f2", typeof(int), new Type[] { typeof (int) },
295 ILGenerator il1 = m1.GetILGenerator();
296 ILGenerator il2 = m2.GetILGenerator();
298 Label l = il1.DefineLabel ();
299 //il1.EmitWriteLine ("f1");
300 il1.Emit (OpCodes.Ldarg_0);
301 il1.Emit (OpCodes.Ldc_I4_0);
302 il1.Emit (OpCodes.Bne_Un, l);
303 il1.Emit (OpCodes.Ldarg_0);
304 il1.Emit (OpCodes.Ret);
306 il1.Emit (OpCodes.Ldarg_0);
307 il1.Emit (OpCodes.Ldc_I4_1);
308 il1.Emit (OpCodes.Sub);
309 il1.Emit (OpCodes.Call, m2);
310 il1.Emit (OpCodes.Ret);
312 //il2.EmitWriteLine("f2");
313 il2.Emit(OpCodes.Ldarg_0);
314 il2.Emit(OpCodes.Call, m1);
315 il2.Emit(OpCodes.Ret);
317 m1.Invoke(null, new object[] { 5 });
320 // Disabl known warning, the Field is never used directly from C#
321 #pragma warning disable 414
323 static string Field = "foo";
325 #pragma warning restore 414
327 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297416
328 public void TestOwnerMemberAccess ()
330 DynamicMethod method = new DynamicMethod ("GetField",
331 typeof (string), new Type [0], typeof (Host));
333 ILGenerator il = method.GetILGenerator ();
334 il.Emit (OpCodes.Ldsfld, typeof (Host).GetField (
335 "Field", BindingFlags.Static | BindingFlags.NonPublic));
336 il.Emit (OpCodes.Ret);
338 string ret = (string) method.Invoke (null, new object [] {});
339 Assert.AreEqual ("foo", ret, "#1");
343 public void AnonHosted ()
345 DynamicMethod hello = new DynamicMethod ("Hello",
347 new Type[] { typeof (string) });
348 ILGenerator helloIL = hello.GetILGenerator ();
349 helloIL.Emit (OpCodes.Ldc_I4_2);
350 helloIL.Emit (OpCodes.Ret);
353 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
354 int ret = hi ("Hello, World!");
355 Assert.AreEqual (2, ret);
357 object[] invokeArgs = { "Hello, World!" };
358 object objRet = hello.Invoke (null, invokeArgs);
359 Assert.AreEqual (2, objRet);
362 public delegate int IntInvoker();
364 public class Foo<T> {
365 public virtual int Test () { return 99; }
369 public void ConstrainedPrexixDoesntCrash () //bug #529238
371 Type foo = typeof (Foo<int>);
373 DynamicMethod dm = new DynamicMethod ("Hello", typeof (int), null);
374 ILGenerator ilgen = dm.GetILGenerator ();
375 ilgen.DeclareLocal (foo);
376 ilgen.Emit (OpCodes.Newobj, foo.GetConstructor (new Type [0]));
377 ilgen.Emit (OpCodes.Stloc_0);
378 ilgen.Emit (OpCodes.Ldloca_S, 0);
379 ilgen.Emit (OpCodes.Constrained, foo);
380 ilgen.Emit (OpCodes.Callvirt, foo.GetMethod ("Test"));
381 ilgen.Emit (OpCodes.Ret);
383 IntInvoker hi = (IntInvoker) dm.CreateDelegate (typeof (IntInvoker));
384 Assert.AreEqual (99, hi (), "#1");
389 public void Module_GetMethod () {
390 AssemblyName assemblyName = new AssemblyName ();
391 assemblyName.Name = "foo";
393 AssemblyBuilder assembly =
394 AppDomain.CurrentDomain.DefineDynamicAssembly (
395 assemblyName, AssemblyBuilderAccess.RunAndSave);
397 ModuleBuilder module = assembly.DefineDynamicModule ("foo.dll");
399 var d = new DynamicMethod ("foo", typeof (int), new Type [] { typeof (int[,]) }, module);
400 var ig = d.GetILGenerator ();
401 ig.Emit (OpCodes.Ldarg_0);
402 ig.Emit (OpCodes.Ldc_I4, 1);
403 ig.Emit (OpCodes.Ldc_I4, 1);
404 ig.Emit (OpCodes.Call, module.GetArrayMethod (typeof (int[,]), "Get", CallingConventions.Standard, typeof (int), new Type [] { typeof (int), typeof (int) }));
405 ig.Emit (OpCodes.Ret);
407 var del = (Func<int[,], int>)d.CreateDelegate (typeof (Func<int[,], int>));
408 int[,] arr = new int [10, 10];
410 Assert.AreEqual (5, del (arr));
414 [Category ("NotWorking")]
415 public void InvalidUnicodeName ()
417 var name = new StringBuilder ().Append ('\udf45').Append ('\ud808');
418 var method = new DynamicMethod (name.ToString (), typeof (bool), new Type [0]);
419 var il = method.GetILGenerator ();
420 il.Emit (OpCodes.Ldc_I4_1);
421 il.Emit (OpCodes.Ret);
423 var function = (Func<bool>) method.CreateDelegate (typeof (Func<bool>));
425 Assert.IsTrue (function ());
429 [ExpectedException (typeof (InvalidOperationException))]
430 public void GetMethodBody ()
432 var method = new DynamicMethod ("method", typeof (object), new Type [] { typeof (object) });
434 var il = method.GetILGenerator ();
435 il.Emit (OpCodes.Ldarg_0);
436 il.Emit (OpCodes.Ret);
438 var f = (Func<object, object>) method.CreateDelegate (typeof (Func<object, object>));
439 f.Method.GetMethodBody ();
442 public delegate object RetObj();
444 public void GetCurrentMethodWorksWithDynamicMethods ()
446 DynamicMethod dm = new DynamicMethod("Foo", typeof(object), null);
447 ILGenerator ilgen = dm.GetILGenerator();
448 ilgen.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod"));
449 ilgen.Emit(OpCodes.Ret);
450 RetObj del = (RetObj)dm.CreateDelegate(typeof(RetObj));
451 MethodInfo res = (MethodInfo)del();
452 Assert.AreEqual (dm.Name, res.Name, "#1");
456 [StructLayout (LayoutKind.Explicit)]
457 struct SizeOfTarget {
458 [FieldOffset (0)] public int X;
459 [FieldOffset (4)] public int Y;
463 public void SizeOf ()
465 var method = new DynamicMethod ("", typeof (int), Type.EmptyTypes);
466 var il = method.GetILGenerator ();
467 il.Emit (OpCodes.Sizeof, typeof (SizeOfTarget));
468 il.Emit (OpCodes.Ret);
470 var func = (Func<int>) method.CreateDelegate (typeof (Func<int>));
471 var point_size = func ();
473 Assert.AreEqual (8, point_size);
476 class TypedRefTarget {
481 public void TypedRef ()
483 var method = new DynamicMethod ("", typeof (TypedRefTarget), new [] {typeof (TypedRefTarget)}, true);
484 var il = method.GetILGenerator ();
485 var tr = il.DeclareLocal (typeof (TypedReference));
487 il.Emit (OpCodes.Ldarga, 0);
488 il.Emit (OpCodes.Mkrefany, typeof (TypedRefTarget));
489 il.Emit (OpCodes.Stloc, tr);
491 il.Emit (OpCodes.Ldloc, tr);
492 il.Emit (OpCodes.Call, GetType ().GetMethod ("AssertTypedRef", BindingFlags.NonPublic | BindingFlags.Static));
494 il.Emit (OpCodes.Ldloc, tr);
495 il.Emit (OpCodes.Refanyval, typeof (TypedRefTarget));
496 il.Emit (OpCodes.Ldobj, typeof (TypedRefTarget));
497 il.Emit (OpCodes.Ret);
499 var f = (Func<TypedRefTarget, TypedRefTarget>) method.CreateDelegate (typeof (Func<TypedRefTarget, TypedRefTarget>));
501 var target = new TypedRefTarget { Name = "Foo" };
504 Assert.AreEqual (target, rt);
507 private static void AssertTypedRef (TypedReference tr)
509 Assert.AreEqual (typeof (TypedRefTarget), TypedReference.GetTargetType (tr));