2 // DynamicMethodTest.cs - NUnit Test Cases for the DynamicMethod class
4 // Gert Driesen (drieseng@users.sourceforge.net)
12 using System.Reflection;
13 using System.Reflection.Emit;
14 using System.Runtime.InteropServices;
17 using NUnit.Framework;
19 namespace MonoTests.System.Reflection.Emit
22 public class DynamicMethodTest
24 private delegate int HelloInvoker (string msg);
27 public void Constructor1_Name_Null ()
30 new DynamicMethod (null,
32 new Type[] { typeof (string) },
33 typeof (DynamicMethodTest).Module);
35 } catch (ArgumentNullException ex) {
36 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
37 Assert.AreEqual ("name", ex.ParamName, "#3");
38 Assert.IsNull (ex.InnerException, "#4");
43 public void Constructor2_Name_Null ()
46 new DynamicMethod (null,
48 new Type[] { typeof (string) },
49 typeof (DynamicMethodTest));
51 } catch (ArgumentNullException ex) {
52 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
53 Assert.AreEqual ("name", ex.ParamName, "#3");
54 Assert.IsNull (ex.InnerException, "#4");
59 public void Constructor3_Name_Null ()
62 new DynamicMethod (null,
64 new Type[] { typeof (string) },
65 typeof (DynamicMethodTest).Module, true);
67 } catch (ArgumentNullException ex) {
68 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
69 Assert.AreEqual ("name", ex.ParamName, "#3");
70 Assert.IsNull (ex.InnerException, "#4");
75 public void Constructor4_Name_Null ()
78 new DynamicMethod (null,
80 new Type[] { typeof (string) },
81 typeof (DynamicMethodTest), true);
83 } catch (ArgumentNullException ex) {
84 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
85 Assert.AreEqual ("name", ex.ParamName, "#3");
86 Assert.IsNull (ex.InnerException, "#4");
91 public void Constructor5_Name_Null ()
94 new DynamicMethod (null,
95 MethodAttributes.Public | MethodAttributes.Static,
96 CallingConventions.Standard,
98 new Type[] { typeof (string) },
99 typeof (DynamicMethodTest).Module, true);
101 } catch (ArgumentNullException ex) {
102 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
103 Assert.AreEqual ("name", ex.ParamName, "#3");
104 Assert.IsNull (ex.InnerException, "#4");
109 public void Constructor6_Name_Null ()
112 new DynamicMethod (null,
113 MethodAttributes.Public | MethodAttributes.Static,
114 CallingConventions.Standard,
116 new Type[] { typeof (string) },
117 typeof (DynamicMethodTest), true);
119 } catch (ArgumentNullException ex) {
120 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
121 Assert.AreEqual ("name", ex.ParamName, "#3");
122 Assert.IsNull (ex.InnerException, "#4");
127 public void OwnerCantBeArray ()
129 TestOwner (typeof (int[]));
133 public void OwnerCantBeInterface ()
135 TestOwner (typeof (global::System.Collections.IEnumerable));
138 private void TestOwner (Type owner)
141 new DynamicMethod ("Name", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
142 typeof(void), new Type[] { }, owner, true);
143 Assert.Fail (string.Format ("Created dynamic method with owner being {0}.", owner));
144 } catch (ArgumentException) {
149 public void DynamicMethodReference ()
151 DynamicMethod hello = new DynamicMethod ("Hello",
153 new Type[] { typeof (string) },
154 typeof (DynamicMethodTest).Module);
155 Assert.IsNull (hello.DeclaringType, "#1");
157 DynamicMethod write = new DynamicMethod ("Write",
159 new Type[] { typeof (string) },
160 typeof (DynamicMethodTest));
161 Assert.IsNull (hello.DeclaringType, "#2");
163 MethodInfo invokeWrite = write.GetBaseDefinition ();
165 ILGenerator helloIL = hello.GetILGenerator ();
166 helloIL.Emit (OpCodes.Ldarg_0);
167 helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
168 helloIL.Emit (OpCodes.Ret);
170 ILGenerator writeIL = write.GetILGenerator ();
171 writeIL.Emit (OpCodes.Ldc_I4_2);
172 writeIL.Emit (OpCodes.Ret);
175 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
176 int ret = hi ("Hello, World!");
177 Assert.AreEqual (2, ret, "#3");
179 object[] invokeArgs = { "Hello, World!" };
180 object objRet = hello.Invoke (null, invokeArgs);
181 Assert.AreEqual (2, objRet, "#4");
185 public void EmptyMethodBody ()
187 DynamicMethod hello = new DynamicMethod ("Hello",
189 new Type[] { typeof (string) },
190 typeof (DynamicMethodTest).Module);
191 object[] invokeArgs = { "Hello, World!" };
195 hello.Invoke (null, invokeArgs);
197 } catch (InvalidOperationException) {
201 hello.GetILGenerator ();
203 hello.Invoke (null, invokeArgs);
205 } catch (InvalidOperationException) {
209 private delegate string ReturnString (string msg);
210 private delegate void DoNothing (string msg);
212 private static string private_method (string s) {
217 public void SkipVisibility ()
219 DynamicMethod hello = new DynamicMethod ("Hello",
221 new Type[] { typeof (string) },
222 typeof (DynamicMethodTest).Module, true);
224 ILGenerator helloIL = hello.GetILGenerator ();
225 helloIL.Emit (OpCodes.Ldarg_0);
226 helloIL.EmitCall (OpCodes.Call, typeof (DynamicMethodTest).GetMethod ("private_method", BindingFlags.Static|BindingFlags.NonPublic), null);
227 helloIL.Emit (OpCodes.Ret);
230 (ReturnString) hello.CreateDelegate (typeof (ReturnString));
231 Assert.AreEqual ("ABCD", del ("ABCD"));
235 public void ReturnType_Null ()
237 DynamicMethod hello = new DynamicMethod ("Hello",
239 new Type[] { typeof (string) },
240 typeof (DynamicMethodTest).Module, true);
241 Assert.AreEqual (typeof (void), hello.ReturnType, "#1");
243 ILGenerator helloIL = hello.GetILGenerator ();
244 helloIL.Emit (OpCodes.Ret);
246 DoNothing dn = (DoNothing) hello.CreateDelegate (typeof (DoNothing));
249 object[] invokeArgs = { "Hello, World!" };
250 object objRet = hello.Invoke (null, invokeArgs);
251 Assert.IsNull (objRet, "#2");
255 public void Name_Empty ()
257 DynamicMethod hello = new DynamicMethod (string.Empty,
259 new Type[] { typeof (string) },
260 typeof (DynamicMethodTest).Module);
261 Assert.AreEqual (string.Empty, hello.Name, "#1");
263 DynamicMethod write = new DynamicMethod ("Write",
265 new Type[] { typeof (string) },
266 typeof (DynamicMethodTest));
268 MethodInfo invokeWrite = write.GetBaseDefinition ();
270 ILGenerator helloIL = hello.GetILGenerator ();
271 helloIL.Emit (OpCodes.Ldarg_0);
272 helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
273 helloIL.Emit (OpCodes.Ret);
275 ILGenerator writeIL = write.GetILGenerator ();
276 writeIL.Emit (OpCodes.Ldc_I4_2);
277 writeIL.Emit (OpCodes.Ret);
280 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
281 int ret = hi ("Hello, World!");
282 Assert.AreEqual (2, ret, "#2");
284 object[] invokeArgs = { "Hello, World!" };
285 object objRet = hello.Invoke (null, invokeArgs);
286 Assert.AreEqual (2, objRet, "#3");
290 public void Circular_Refs () {
291 DynamicMethod m1 = new DynamicMethod("f1", typeof(int), new Type[] { typeof (int) },
293 DynamicMethod m2 = new DynamicMethod("f2", typeof(int), new Type[] { typeof (int) },
296 ILGenerator il1 = m1.GetILGenerator();
297 ILGenerator il2 = m2.GetILGenerator();
299 Label l = il1.DefineLabel ();
300 //il1.EmitWriteLine ("f1");
301 il1.Emit (OpCodes.Ldarg_0);
302 il1.Emit (OpCodes.Ldc_I4_0);
303 il1.Emit (OpCodes.Bne_Un, l);
304 il1.Emit (OpCodes.Ldarg_0);
305 il1.Emit (OpCodes.Ret);
307 il1.Emit (OpCodes.Ldarg_0);
308 il1.Emit (OpCodes.Ldc_I4_1);
309 il1.Emit (OpCodes.Sub);
310 il1.Emit (OpCodes.Call, m2);
311 il1.Emit (OpCodes.Ret);
313 //il2.EmitWriteLine("f2");
314 il2.Emit(OpCodes.Ldarg_0);
315 il2.Emit(OpCodes.Call, m1);
316 il2.Emit(OpCodes.Ret);
318 m1.Invoke(null, new object[] { 5 });
321 // Disabl known warning, the Field is never used directly from C#
322 #pragma warning disable 414
324 static string Field = "foo";
326 #pragma warning restore 414
328 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297416
329 public void TestOwnerMemberAccess ()
331 DynamicMethod method = new DynamicMethod ("GetField",
332 typeof (string), new Type [0], typeof (Host));
334 ILGenerator il = method.GetILGenerator ();
335 il.Emit (OpCodes.Ldsfld, typeof (Host).GetField (
336 "Field", BindingFlags.Static | BindingFlags.NonPublic));
337 il.Emit (OpCodes.Ret);
339 string ret = (string) method.Invoke (null, new object [] {});
340 Assert.AreEqual ("foo", ret, "#1");
344 public void AnonHosted ()
346 DynamicMethod hello = new DynamicMethod ("Hello",
348 new Type[] { typeof (string) });
349 ILGenerator helloIL = hello.GetILGenerator ();
350 helloIL.Emit (OpCodes.Ldc_I4_2);
351 helloIL.Emit (OpCodes.Ret);
354 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
355 int ret = hi ("Hello, World!");
356 Assert.AreEqual (2, ret);
358 object[] invokeArgs = { "Hello, World!" };
359 object objRet = hello.Invoke (null, invokeArgs);
360 Assert.AreEqual (2, objRet);
363 public delegate int IntInvoker();
365 public class Foo<T> {
366 public virtual int Test () { return 99; }
370 public void ConstrainedPrexixDoesntCrash () //bug #529238
372 Type foo = typeof (Foo<int>);
374 DynamicMethod dm = new DynamicMethod ("Hello", typeof (int), null);
375 ILGenerator ilgen = dm.GetILGenerator ();
376 ilgen.DeclareLocal (foo);
377 ilgen.Emit (OpCodes.Newobj, foo.GetConstructor (new Type [0]));
378 ilgen.Emit (OpCodes.Stloc_0);
379 ilgen.Emit (OpCodes.Ldloca_S, 0);
380 ilgen.Emit (OpCodes.Constrained, foo);
381 ilgen.Emit (OpCodes.Callvirt, foo.GetMethod ("Test"));
382 ilgen.Emit (OpCodes.Ret);
384 IntInvoker hi = (IntInvoker) dm.CreateDelegate (typeof (IntInvoker));
385 Assert.AreEqual (99, hi (), "#1");
390 public void Module_GetMethod () {
391 AssemblyName assemblyName = new AssemblyName ();
392 assemblyName.Name = "foo";
394 AssemblyBuilder assembly =
395 AppDomain.CurrentDomain.DefineDynamicAssembly (
396 assemblyName, AssemblyBuilderAccess.RunAndSave);
398 ModuleBuilder module = assembly.DefineDynamicModule ("foo.dll");
400 var d = new DynamicMethod ("foo", typeof (int), new Type [] { typeof (int[,]) }, module);
401 var ig = d.GetILGenerator ();
402 ig.Emit (OpCodes.Ldarg_0);
403 ig.Emit (OpCodes.Ldc_I4, 1);
404 ig.Emit (OpCodes.Ldc_I4, 1);
405 ig.Emit (OpCodes.Call, module.GetArrayMethod (typeof (int[,]), "Get", CallingConventions.Standard, typeof (int), new Type [] { typeof (int), typeof (int) }));
406 ig.Emit (OpCodes.Ret);
408 var del = (Func<int[,], int>)d.CreateDelegate (typeof (Func<int[,], int>));
409 int[,] arr = new int [10, 10];
411 Assert.AreEqual (5, del (arr));
415 [Category ("NotWorking")]
416 public void InvalidUnicodeName ()
418 var name = new StringBuilder ().Append ('\udf45').Append ('\ud808');
419 var method = new DynamicMethod (name.ToString (), typeof (bool), new Type [0]);
420 var il = method.GetILGenerator ();
421 il.Emit (OpCodes.Ldc_I4_1);
422 il.Emit (OpCodes.Ret);
424 var function = (Func<bool>) method.CreateDelegate (typeof (Func<bool>));
426 Assert.IsTrue (function ());
430 [ExpectedException (typeof (InvalidOperationException))]
431 public void GetMethodBody ()
433 var method = new DynamicMethod ("method", typeof (object), new Type [] { typeof (object) });
435 var il = method.GetILGenerator ();
436 il.Emit (OpCodes.Ldarg_0);
437 il.Emit (OpCodes.Ret);
439 var f = (Func<object, object>) method.CreateDelegate (typeof (Func<object, object>));
440 f.Method.GetMethodBody ();
443 public delegate object RetObj();
445 public void GetCurrentMethodWorksWithDynamicMethods ()
447 DynamicMethod dm = new DynamicMethod("Foo", typeof(object), null);
448 ILGenerator ilgen = dm.GetILGenerator();
449 ilgen.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod"));
450 ilgen.Emit(OpCodes.Ret);
451 RetObj del = (RetObj)dm.CreateDelegate(typeof(RetObj));
452 MethodInfo res = (MethodInfo)del();
453 Assert.AreEqual (dm.Name, res.Name, "#1");
457 [StructLayout (LayoutKind.Explicit)]
458 struct SizeOfTarget {
459 [FieldOffset (0)] public int X;
460 [FieldOffset (4)] public int Y;
464 public void SizeOf ()
466 var method = new DynamicMethod ("", typeof (int), Type.EmptyTypes);
467 var il = method.GetILGenerator ();
468 il.Emit (OpCodes.Sizeof, typeof (SizeOfTarget));
469 il.Emit (OpCodes.Ret);
471 var func = (Func<int>) method.CreateDelegate (typeof (Func<int>));
472 var point_size = func ();
474 Assert.AreEqual (8, point_size);
477 class TypedRefTarget {
482 public void TypedRef ()
484 var method = new DynamicMethod ("", typeof (TypedRefTarget), new [] {typeof (TypedRefTarget)}, true);
485 var il = method.GetILGenerator ();
486 var tr = il.DeclareLocal (typeof (TypedReference));
488 il.Emit (OpCodes.Ldarga, 0);
489 il.Emit (OpCodes.Mkrefany, typeof (TypedRefTarget));
490 il.Emit (OpCodes.Stloc, tr);
492 il.Emit (OpCodes.Ldloc, tr);
493 il.Emit (OpCodes.Call, GetType ().GetMethod ("AssertTypedRef", BindingFlags.NonPublic | BindingFlags.Static));
495 il.Emit (OpCodes.Ldloc, tr);
496 il.Emit (OpCodes.Refanyval, typeof (TypedRefTarget));
497 il.Emit (OpCodes.Ldobj, typeof (TypedRefTarget));
498 il.Emit (OpCodes.Ret);
500 var f = (Func<TypedRefTarget, TypedRefTarget>) method.CreateDelegate (typeof (Func<TypedRefTarget, TypedRefTarget>));
502 var target = new TypedRefTarget { Name = "Foo" };
505 Assert.AreEqual (target, rt);
508 private static void AssertTypedRef (TypedReference tr)
510 Assert.AreEqual (typeof (TypedRefTarget), TypedReference.GetTargetType (tr));