Wed Feb 24 15:47:16 CET 2010 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / DynamicMethodTest.cs
1 //
2 // DynamicMethodTest.cs - NUnit Test Cases for the DynamicMethod class
3 //
4 // Gert Driesen (drieseng@users.sourceforge.net)
5 //
6 // (C) 2006 Novell
7
8 #if NET_2_0
9
10 using System;
11 using System.Reflection;
12 using System.Reflection.Emit;
13
14 using NUnit.Framework;
15
16 namespace MonoTests.System.Reflection.Emit
17 {
18         [TestFixture]
19         public class DynamicMethodTest
20         {
21                 private delegate int HelloInvoker (string msg);
22
23                 [Test]
24                 public void Constructor1_Name_Null ()
25                 {
26                         try {
27                                 new DynamicMethod (null,
28                                         typeof (void),
29                                         new Type[] { typeof (string) },
30                                         typeof (DynamicMethodTest).Module);
31                                 Assert.Fail ("#1");
32                         } catch (ArgumentNullException ex) {
33                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
34                                 Assert.AreEqual ("name", ex.ParamName, "#3");
35                                 Assert.IsNull (ex.InnerException, "#4");
36                         }
37                 }
38
39                 [Test]
40                 public void Constructor2_Name_Null ()
41                 {
42                         try {
43                                 new DynamicMethod (null,
44                                         typeof (void),
45                                         new Type[] { typeof (string) },
46                                         typeof (DynamicMethodTest));
47                                 Assert.Fail ("#1");
48                         } catch (ArgumentNullException ex) {
49                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
50                                 Assert.AreEqual ("name", ex.ParamName, "#3");
51                                 Assert.IsNull (ex.InnerException, "#4");
52                         }
53                 }
54
55                 [Test]
56                 public void Constructor3_Name_Null ()
57                 {
58                         try {
59                                 new DynamicMethod (null,
60                                         typeof (void),
61                                         new Type[] { typeof (string) },
62                                         typeof (DynamicMethodTest).Module, true);
63                                 Assert.Fail ("#1");
64                         } catch (ArgumentNullException ex) {
65                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
66                                 Assert.AreEqual ("name", ex.ParamName, "#3");
67                                 Assert.IsNull (ex.InnerException, "#4");
68                         }
69                 }
70
71                 [Test]
72                 public void Constructor4_Name_Null ()
73                 {
74                         try {
75                                 new DynamicMethod (null,
76                                         typeof (void),
77                                         new Type[] { typeof (string) },
78                                         typeof (DynamicMethodTest), true);
79                                 Assert.Fail ("#1");
80                         } catch (ArgumentNullException ex) {
81                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
82                                 Assert.AreEqual ("name", ex.ParamName, "#3");
83                                 Assert.IsNull (ex.InnerException, "#4");
84                         }
85                 }
86
87                 [Test]
88                 public void Constructor5_Name_Null ()
89                 {
90                         try {
91                                 new DynamicMethod (null,
92                                         MethodAttributes.Public | MethodAttributes.Static,
93                                         CallingConventions.Standard,
94                                         typeof (void),
95                                         new Type[] { typeof (string) },
96                                         typeof (DynamicMethodTest).Module, true);
97                                 Assert.Fail ("#1");
98                         } catch (ArgumentNullException ex) {
99                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
100                                 Assert.AreEqual ("name", ex.ParamName, "#3");
101                                 Assert.IsNull (ex.InnerException, "#4");
102                         }
103                 }
104
105                 [Test]
106                 public void Constructor6_Name_Null ()
107                 {
108                         try {
109                                 new DynamicMethod (null,
110                                         MethodAttributes.Public | MethodAttributes.Static,
111                                         CallingConventions.Standard,
112                                         typeof (void),
113                                         new Type[] { typeof (string) },
114                                         typeof (DynamicMethodTest), true);
115                                 Assert.Fail ("#1");
116                         } catch (ArgumentNullException ex) {
117                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
118                                 Assert.AreEqual ("name", ex.ParamName, "#3");
119                                 Assert.IsNull (ex.InnerException, "#4");
120                         }
121                 }
122
123                 [Test] // bug #78253
124                 public void DynamicMethodReference ()
125                 {
126                         DynamicMethod hello = new DynamicMethod ("Hello",
127                                 typeof (int),
128                                 new Type[] { typeof (string) },
129                                 typeof (DynamicMethodTest).Module);
130                         Assert.IsNull (hello.DeclaringType, "#1");
131
132                         DynamicMethod write = new DynamicMethod ("Write",
133                                 typeof (int),
134                                 new Type[] { typeof (string) },
135                                 typeof (DynamicMethodTest));
136                         Assert.IsNull (hello.DeclaringType, "#2");
137
138                         MethodInfo invokeWrite = write.GetBaseDefinition ();
139
140                         ILGenerator helloIL = hello.GetILGenerator ();
141                         helloIL.Emit (OpCodes.Ldarg_0);
142                         helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
143                         helloIL.Emit (OpCodes.Ret);
144
145                         ILGenerator writeIL = write.GetILGenerator ();
146                         writeIL.Emit (OpCodes.Ldc_I4_2);
147                         writeIL.Emit (OpCodes.Ret);
148
149                         HelloInvoker hi =
150                                 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
151                         int ret = hi ("Hello, World!");
152                         Assert.AreEqual (2, ret, "#3");
153
154                         object[] invokeArgs = { "Hello, World!" };
155                         object objRet = hello.Invoke (null, invokeArgs);
156                         Assert.AreEqual (2, objRet, "#4");
157                 }
158
159                 [Test]
160                 public void EmptyMethodBody ()
161                 {
162                         DynamicMethod hello = new DynamicMethod ("Hello",
163                                 typeof (int),
164                                 new Type[] { typeof (string) },
165                                 typeof (DynamicMethodTest).Module);
166                         object[] invokeArgs = { "Hello, World!" };
167
168                         // no IL generator
169                         try {
170                                 hello.Invoke (null, invokeArgs);
171                                 Assert.Fail ("#1");
172                         } catch (InvalidOperationException) {
173                         }
174
175                         // empty method body
176                         hello.GetILGenerator ();
177                         try {
178                                 hello.Invoke (null, invokeArgs);
179                                 Assert.Fail ("#2");
180                         } catch (InvalidOperationException) {
181                         }
182                 }
183
184                 private delegate string ReturnString (string msg);
185                 private delegate void DoNothing (string msg);
186
187                 private static string private_method (string s) {
188                         return s;
189                 }
190
191                 [Test]
192                 public void SkipVisibility ()
193                 {
194                         DynamicMethod hello = new DynamicMethod ("Hello",
195                                 typeof (string),
196                                 new Type[] { typeof (string) },
197                                 typeof (DynamicMethodTest).Module, true);
198
199                         ILGenerator helloIL = hello.GetILGenerator ();
200                         helloIL.Emit (OpCodes.Ldarg_0);
201                         helloIL.EmitCall (OpCodes.Call, typeof (DynamicMethodTest).GetMethod ("private_method", BindingFlags.Static|BindingFlags.NonPublic), null);
202                         helloIL.Emit (OpCodes.Ret);
203
204                         ReturnString del =
205                                 (ReturnString) hello.CreateDelegate (typeof (ReturnString));
206                         Assert.AreEqual ("ABCD", del ("ABCD"));
207                 }
208
209                 [Test]
210                 public void ReturnType_Null ()
211                 {
212                         DynamicMethod hello = new DynamicMethod ("Hello",
213                                 null,
214                                 new Type[] { typeof (string) },
215                                 typeof (DynamicMethodTest).Module, true);
216                         Assert.AreEqual (typeof (void), hello.ReturnType, "#1");
217
218                         ILGenerator helloIL = hello.GetILGenerator ();
219                         helloIL.Emit (OpCodes.Ret);
220
221                         DoNothing dn = (DoNothing) hello.CreateDelegate (typeof (DoNothing));
222                         dn ("whatever");
223
224                         object[] invokeArgs = { "Hello, World!" };
225                         object objRet = hello.Invoke (null, invokeArgs);
226                         Assert.IsNull (objRet, "#2");
227                 }
228
229                 [Test]
230                 public void Name_Empty ()
231                 {
232                         DynamicMethod hello = new DynamicMethod (string.Empty,
233                                 typeof (int),
234                                 new Type[] { typeof (string) },
235                                 typeof (DynamicMethodTest).Module);
236                         Assert.AreEqual (string.Empty, hello.Name, "#1");
237
238                         DynamicMethod write = new DynamicMethod ("Write",
239                                 typeof (int),
240                                 new Type[] { typeof (string) },
241                                 typeof (DynamicMethodTest));
242
243                         MethodInfo invokeWrite = write.GetBaseDefinition ();
244
245                         ILGenerator helloIL = hello.GetILGenerator ();
246                         helloIL.Emit (OpCodes.Ldarg_0);
247                         helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
248                         helloIL.Emit (OpCodes.Ret);
249
250                         ILGenerator writeIL = write.GetILGenerator ();
251                         writeIL.Emit (OpCodes.Ldc_I4_2);
252                         writeIL.Emit (OpCodes.Ret);
253
254                         HelloInvoker hi =
255                                 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
256                         int ret = hi ("Hello, World!");
257                         Assert.AreEqual (2, ret, "#2");
258
259                         object[] invokeArgs = { "Hello, World!" };
260                         object objRet = hello.Invoke (null, invokeArgs);
261                         Assert.AreEqual (2, objRet, "#3");
262                 }
263
264                 [Test]
265                 public void Circular_Refs () {
266                         DynamicMethod m1 = new DynamicMethod("f1", typeof(int), new Type[] { typeof (int) },
267                                                                                                  typeof(object));
268                         DynamicMethod m2 = new DynamicMethod("f2", typeof(int), new Type[] { typeof (int) },
269                                                                                                  typeof(object));
270
271                         ILGenerator il1 = m1.GetILGenerator();
272                         ILGenerator il2 = m2.GetILGenerator();
273
274                         Label l = il1.DefineLabel ();
275                         //il1.EmitWriteLine ("f1");
276                         il1.Emit (OpCodes.Ldarg_0);
277                         il1.Emit (OpCodes.Ldc_I4_0);
278                         il1.Emit (OpCodes.Bne_Un, l);
279                         il1.Emit (OpCodes.Ldarg_0);
280                         il1.Emit (OpCodes.Ret);
281                         il1.MarkLabel (l);
282                         il1.Emit (OpCodes.Ldarg_0);
283                         il1.Emit (OpCodes.Ldc_I4_1);
284                         il1.Emit (OpCodes.Sub);
285                         il1.Emit (OpCodes.Call, m2);
286                         il1.Emit (OpCodes.Ret);
287
288                         //il2.EmitWriteLine("f2");
289                         il2.Emit(OpCodes.Ldarg_0);
290                         il2.Emit(OpCodes.Call, m1);
291                         il2.Emit(OpCodes.Ret);
292
293                         m1.Invoke(null, new object[] { 5 });
294                 }
295
296                 class Host {
297                         static string Field = "foo";
298                 }
299
300                 [Test]
301                 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297416
302                 public void TestOwnerMemberAccess ()
303                 {
304                         DynamicMethod method = new DynamicMethod ("GetField",
305                                 typeof (string), new Type [0], typeof (Host));
306
307                         ILGenerator il = method.GetILGenerator ();
308                         il.Emit (OpCodes.Ldsfld, typeof (Host).GetField (
309                                 "Field", BindingFlags.Static | BindingFlags.NonPublic));
310                         il.Emit (OpCodes.Ret);
311
312                         string ret = (string) method.Invoke (null, new object [] {});
313                         Assert.AreEqual ("foo", ret, "#1");
314                 }
315
316                 [Test]
317                 public void AnonHosted ()
318                 {
319                         DynamicMethod hello = new DynamicMethod ("Hello",
320                                                                                                          typeof (int),
321                                                                                                          new Type[] { typeof (string) });
322                         ILGenerator helloIL = hello.GetILGenerator ();
323                         helloIL.Emit (OpCodes.Ldc_I4_2);
324                         helloIL.Emit (OpCodes.Ret);
325
326                         HelloInvoker hi =
327                                 (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
328                         int ret = hi ("Hello, World!");
329                         Assert.AreEqual (2, ret);
330
331                         object[] invokeArgs = { "Hello, World!" };
332                         object objRet = hello.Invoke (null, invokeArgs);
333                         Assert.AreEqual (2, objRet);
334                 }
335
336                 public delegate int IntInvoker();
337
338                 public class Foo<T> {
339                         public virtual int Test () { return 99; }
340                 } 
341
342                 [Test]
343                 public void ConstrainedPrexixDoesntCrash () //bug #529238
344                 {
345                         Type foo = typeof (Foo<int>);
346
347                         DynamicMethod dm = new DynamicMethod ("Hello", typeof (int), null);
348                         ILGenerator ilgen = dm.GetILGenerator ();
349                         ilgen.DeclareLocal (foo);
350                         ilgen.Emit (OpCodes.Newobj, foo.GetConstructor (new Type [0]));
351                         ilgen.Emit (OpCodes.Stloc_0);
352                         ilgen.Emit (OpCodes.Ldloca_S, 0);
353                         ilgen.Emit (OpCodes.Constrained, foo);
354                         ilgen.Emit (OpCodes.Callvirt, foo.GetMethod ("Test"));
355                         ilgen.Emit (OpCodes.Ret);
356
357                         IntInvoker hi = (IntInvoker) dm.CreateDelegate (typeof (IntInvoker));
358                         Assert.AreEqual (99, hi (), "#1");      
359                 }
360
361                 // #575955
362                 [Test]
363                 public void Module_GetMethod () {
364                         AssemblyName assemblyName = new AssemblyName ();
365                         assemblyName.Name = "foo";
366
367                         AssemblyBuilder assembly =
368                                 AppDomain.CurrentDomain.DefineDynamicAssembly (
369                                                                                                                            assemblyName, AssemblyBuilderAccess.RunAndSave);
370
371                         ModuleBuilder module = assembly.DefineDynamicModule ("foo.dll");
372
373                         var d = new DynamicMethod ("foo", typeof (int), new Type [] { typeof (int[,]) }, module);
374                         var ig = d.GetILGenerator ();
375                         ig.Emit (OpCodes.Ldarg_0);
376                         ig.Emit (OpCodes.Ldc_I4, 1);
377                         ig.Emit (OpCodes.Ldc_I4, 1);
378                         ig.Emit (OpCodes.Call, module.GetArrayMethod (typeof (int[,]), "Get", CallingConventions.Standard, typeof (int), new Type [] { typeof (int), typeof (int) }));
379                         ig.Emit (OpCodes.Ret);
380                 
381                         var del = (Func<int[,], int>)d.CreateDelegate (typeof (Func<int[,], int>));
382                         int[,] arr = new int [10, 10];
383                         arr [1, 1] = 5;
384                         Assert.AreEqual (5, del (arr));
385                 }
386         }
387 }
388
389 #endif