2003-02-12 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / MethodBuilderTest.cs
1 //\r
2 // MethodBuilderTest.cs - NUnit Test Cases for the MethodBuilder class\r
3 //\r
4 // Zoltan Varga (vargaz@freemail.hu)\r
5 //\r
6 // (C) Ximian, Inc.  http://www.ximian.com\r
7 \r
8 // TODO:\r
9 //  - implement 'Signature' (what the hell it does???) and test it\r
10 //  - implement Equals and test it\r
11 //  - AddDeclarativeSecurity\r
12 \r
13 using System;\r
14 using System.Threading;\r
15 using System.Reflection;\r
16 using System.Reflection.Emit;\r
17 using System.Runtime.CompilerServices;\r
18 \r
19 using NUnit.Framework;\r
20 \r
21 namespace MonoTests.System.Reflection.Emit\r
22 {\r
23 \r
24 [TestFixture]\r
25 public class MethodBuilderTest : Assertion\r
26 {       \r
27     private TypeBuilder genClass;\r
28 \r
29         private ModuleBuilder module;\r
30 \r
31         [SetUp]\r
32         protected void SetUp () {\r
33                 AssemblyName assemblyName = new AssemblyName();\r
34                 assemblyName.Name = "MonoTests.System.Reflection.Emit.MethodBuilderTest";\r
35 \r
36                 AssemblyBuilder assembly \r
37                         = Thread.GetDomain().DefineDynamicAssembly(\r
38                                 assemblyName, AssemblyBuilderAccess.Run);\r
39 \r
40                 module = assembly.DefineDynamicModule("module1");\r
41                 \r
42                 genClass = module.DefineType("class1", \r
43                                                                          TypeAttributes.Public);\r
44         }\r
45 \r
46         static int methodIndexer = 0;\r
47 \r
48         // Return a unique method name\r
49         private string genMethodName () {\r
50                 return "m" + (methodIndexer ++);\r
51         }\r
52 \r
53         public void TestAttributes () {\r
54                 MethodBuilder mb = genClass.DefineMethod (\r
55                         genMethodName (), MethodAttributes.Public, typeof (void), new Type [0]);\r
56 \r
57                 AssertEquals ("Attributes works", \r
58                                           mb.Attributes, MethodAttributes.Public);\r
59         }\r
60 \r
61         public void TestCallingConvention () {\r
62                 MethodBuilder mb = genClass.DefineMethod (\r
63                         genMethodName (), 0, typeof (void), new Type[0]);\r
64                 AssertEquals ("CallingConvetion defaults to Standard+HasThis",\r
65                                           mb.CallingConvention, \r
66                                           CallingConventions.Standard | CallingConventions.HasThis);\r
67 \r
68                 MethodBuilder mb3 = genClass.DefineMethod (\r
69                         genMethodName (), 0, CallingConventions.VarArgs, typeof (void), new Type[0]);\r
70                 AssertEquals ("CallingConvetion works",\r
71                                           mb3.CallingConvention, \r
72                                           CallingConventions.VarArgs | CallingConventions.HasThis);\r
73 \r
74                 MethodBuilder mb4 = genClass.DefineMethod (\r
75                         genMethodName (), MethodAttributes.Static, CallingConventions.Standard,\r
76                         typeof (void), new Type [0]);\r
77                 AssertEquals ("Static implies !HasThis",\r
78                                           mb4.CallingConvention,\r
79                                           CallingConventions.Standard);\r
80         }\r
81 \r
82         public void TestDeclaringType () {\r
83                 MethodBuilder mb = genClass.DefineMethod (\r
84                         genMethodName (), 0, typeof (void), new Type[0]);\r
85 \r
86                 AssertEquals ("DeclaringType works",\r
87                                           mb.DeclaringType, genClass);\r
88         }\r
89 \r
90         public void TestInitLocals () {\r
91                 MethodBuilder mb = genClass.DefineMethod (\r
92                         genMethodName (), 0, typeof (void), new Type[0]);\r
93 \r
94                 AssertEquals ("InitLocals defaults to true", mb.InitLocals, true);\r
95                 mb.InitLocals = false;\r
96                 AssertEquals ("InitLocals is settable", mb.InitLocals, false);\r
97         }\r
98 \r
99         public void TestMethodHandle () {\r
100                 MethodBuilder mb = genClass.DefineMethod (\r
101                         genMethodName (), 0, typeof (void), new Type [0]);\r
102 \r
103                 try {\r
104                         RuntimeMethodHandle handle = mb.MethodHandle;\r
105                         Fail ();\r
106                 } catch (NotSupportedException) {\r
107                 }\r
108         }\r
109 \r
110         public void TestName () {\r
111                 string name = genMethodName ();\r
112                 MethodBuilder mb = genClass.DefineMethod (\r
113                         name, 0, typeof (void), new Type [0]);\r
114 \r
115                 AssertEquals ("Name works", mb.Name, name);\r
116         }\r
117 \r
118         public void TestReflectedType () {\r
119                 MethodBuilder mb = genClass.DefineMethod (\r
120                         genMethodName (), 0, typeof (void), new Type [0]);\r
121 \r
122                 AssertEquals ("ReflectedType works", \r
123                                           genClass, mb.ReflectedType);\r
124         }\r
125 \r
126         public void TestReturnType () {\r
127                 MethodBuilder mb = genClass.DefineMethod (\r
128                         genMethodName (), 0, typeof (Console), new Type [0]);\r
129 \r
130                 AssertEquals ("ReturnType works", \r
131                                           mb.ReturnType, typeof (Console));\r
132 \r
133                 \r
134                 MethodBuilder mb2 = genClass.DefineMethod (\r
135                         genMethodName (), 0, null, new Type [0]);\r
136 \r
137                 AssertEquals ("ReturnType is null",\r
138                                           mb2.ReturnType, null);\r
139         }\r
140 \r
141         public void TestReturnTypeCustomAttributes () {\r
142                 MethodBuilder mb = genClass.DefineMethod (\r
143                         genMethodName (), 0, typeof (Console), new Type [0]);\r
144 \r
145                 AssertEquals ("ReturnTypeCustomAttributes must be null",\r
146                                           mb.ReturnTypeCustomAttributes, null);\r
147         }\r
148 \r
149         /*\r
150         public void TestSignature () {\r
151                 MethodBuilder mb = genClass.DefineMethod (\r
152                         "m91", 0, typeof (Console), new Type [1] { typeof (Console) });\r
153 \r
154                 Console.WriteLine (mb.Signature);\r
155         }\r
156         */\r
157 \r
158         public void TestCreateMethodBody () {\r
159                 MethodBuilder mb = genClass.DefineMethod (\r
160                         genMethodName (), 0, typeof (void), new Type [0]);\r
161 \r
162                 // Clear body\r
163                 mb.CreateMethodBody (null, 999);\r
164 \r
165                 // Check arguments 1.\r
166                 try {\r
167                         mb.CreateMethodBody (new byte[1], -1);\r
168                         Fail ();\r
169                 } catch (ArgumentException) {\r
170                 }\r
171 \r
172                 // Check arguments 2.\r
173                 try {\r
174                         mb.CreateMethodBody (new byte[1], 2);\r
175                         Fail ();\r
176                 } catch (ArgumentException) {\r
177                 }\r
178 \r
179                 mb.CreateMethodBody (new byte[2], 1);\r
180 \r
181                 // Could only be called once\r
182                 try {\r
183                         mb.CreateMethodBody (new byte[2], 1);\r
184                         Fail ();\r
185                 } catch (InvalidOperationException) {\r
186                 }\r
187 \r
188                 // Can not be called on a created type\r
189                 TypeBuilder tb = module.DefineType ("class6", TypeAttributes.Public);\r
190                 MethodBuilder mb2 = tb.DefineMethod (\r
191                         genMethodName (), 0, typeof (void), new Type [0]);\r
192                 ILGenerator ilgen = mb2.GetILGenerator ();\r
193                 ilgen.Emit (OpCodes.Ret);\r
194                 tb.CreateType ();\r
195 \r
196                 try {\r
197                         mb2.CreateMethodBody (new byte[2], 1);\r
198                         Fail ();\r
199                 } catch (InvalidOperationException) {\r
200                 }\r
201         }\r
202 \r
203         public void TestDefineParameter () {\r
204                 TypeBuilder tb = module.DefineType ("class7", TypeAttributes.Public);\r
205                 MethodBuilder mb = tb.DefineMethod (\r
206                         genMethodName (), 0, typeof (void), \r
207                         new Type [2] { typeof(int), typeof(int) });\r
208 \r
209                 // index out of range\r
210                 try {\r
211                         mb.DefineParameter (0, 0, "param1");\r
212                         Fail ();\r
213                 } catch (ArgumentOutOfRangeException) {\r
214                 }\r
215                 try {\r
216                         mb.DefineParameter (3, 0, "param1");\r
217                         Fail ();\r
218                 } catch (ArgumentOutOfRangeException) {\r
219                 }\r
220 \r
221                 // Normal usage\r
222                 mb.DefineParameter (1, 0, "param1");\r
223                 mb.DefineParameter (1, 0, "param1");\r
224                 mb.DefineParameter (2, 0, null);\r
225 \r
226                 // Can not be called on a created type\r
227                 mb.CreateMethodBody (new byte[2], 0);\r
228                 tb.CreateType ();\r
229                 try {\r
230                         mb.DefineParameter (1, 0, "param1");\r
231                         Fail ();\r
232                 }\r
233                 catch (InvalidOperationException) {\r
234                 }\r
235         }\r
236 \r
237         public void TestGetBaseDefinition () {\r
238                 MethodBuilder mb = genClass.DefineMethod (\r
239                         genMethodName (), 0, typeof (void), new Type [0]);\r
240 \r
241                 AssertEquals ("GetBaseDefinition works",\r
242                                           mb.GetBaseDefinition (), mb);\r
243         }\r
244 \r
245         public void TestGetILGenerator () {\r
246                 MethodBuilder mb = genClass.DefineMethod (\r
247                         genMethodName (), 0, typeof (void), new Type [0]);\r
248 \r
249                 // The same instance is returned on the second call\r
250                 ILGenerator ilgen1 = mb.GetILGenerator ();\r
251                 ILGenerator ilgen2 = mb.GetILGenerator ();\r
252 \r
253                 AssertEquals ("The same ilgen is returned on the second call",\r
254                                           ilgen1, ilgen2);\r
255 \r
256                 // Does not work on unmanaged code\r
257                 MethodBuilder mb2 = genClass.DefineMethod (\r
258                         genMethodName (), 0, typeof (void), new Type [0]);              \r
259                 try {\r
260                         mb2.SetImplementationFlags (MethodImplAttributes.Unmanaged);\r
261                         mb2.GetILGenerator ();\r
262                         Fail ();\r
263                 } catch (InvalidOperationException) {\r
264                 }\r
265                 try {\r
266                         mb2.SetImplementationFlags (MethodImplAttributes.Native);\r
267                         mb2.GetILGenerator ();\r
268                         Fail ();\r
269                 } catch (InvalidOperationException) {\r
270                 }\r
271         }\r
272 \r
273         public void TestMethodImplementationFlags () {\r
274                 TypeBuilder tb = module.DefineType ("class14", TypeAttributes.Public);\r
275                 MethodBuilder mb = tb.DefineMethod (\r
276                         genMethodName (), 0, typeof (void), new Type [0]);\r
277 \r
278                 AssertEquals ("MethodImplementationFlags defaults to Managed+IL",\r
279                                           mb.GetMethodImplementationFlags (),\r
280                                           MethodImplAttributes.Managed | MethodImplAttributes.IL);\r
281 \r
282                 mb.SetImplementationFlags (MethodImplAttributes.OPTIL);\r
283 \r
284                 AssertEquals ("SetImplementationFlags works",\r
285                                           mb.GetMethodImplementationFlags (),\r
286                                           MethodImplAttributes.OPTIL);\r
287 \r
288                 // Can not be called on a created type\r
289                 mb.CreateMethodBody (new byte[2], 0);\r
290                 mb.SetImplementationFlags (MethodImplAttributes.Managed);\r
291                 tb.CreateType ();\r
292                 try {\r
293                         mb.SetImplementationFlags (MethodImplAttributes.OPTIL);\r
294                         Fail ();\r
295                 }\r
296                 catch (InvalidOperationException) {\r
297                 }\r
298         }\r
299 \r
300         public void TestGetModule () {\r
301                 MethodBuilder mb = genClass.DefineMethod (\r
302                         genMethodName (), 0, typeof (void), new Type [0]);\r
303 \r
304                 AssertEquals ("GetMethod works",\r
305                                           mb.GetModule (), module);\r
306         }\r
307 \r
308         public void TestGetParameters () {\r
309                 TypeBuilder tb = module.DefineType ("class16", TypeAttributes.Public);\r
310                 MethodBuilder mb = tb.DefineMethod (\r
311                         genMethodName (), 0, typeof (void), new Type [1] {typeof(void)});\r
312 \r
313                 /*\r
314                  * According to the MSDN docs, this method should fail with a\r
315                  * NotSupportedException. In reality, it throws an \r
316                  * InvalidOperationException under MS .NET, and returns the \r
317                  * requested data under mono.\r
318                  */\r
319                 /*\r
320                 try {\r
321                         mb.GetParameters ();\r
322                         Fail ("#161");\r
323                 } catch (InvalidOperationException ex) {\r
324                         Console.WriteLine (ex);\r
325                 }\r
326                 */\r
327         }\r
328 \r
329         public void TestGetToken () {\r
330                 TypeBuilder tb = module.DefineType ("class17", TypeAttributes.Public);\r
331                 MethodBuilder mb = tb.DefineMethod (\r
332                         genMethodName (), 0, typeof (void), new Type [1] {typeof(void)});\r
333 \r
334                 mb.GetToken ();\r
335         }\r
336 \r
337         public void TestInvoke () {\r
338                 MethodBuilder mb = genClass.DefineMethod (\r
339                         genMethodName (), 0, typeof (void), \r
340                         new Type [1] {typeof(int)});\r
341 \r
342                 try {\r
343                         mb.Invoke (null, new object [1] { 42 });\r
344                         Fail ();\r
345                 } catch (NotSupportedException) {\r
346                 }\r
347 \r
348                 try {\r
349                         mb.Invoke (null, 0, null, new object [1] { 42 }, null);\r
350                         Fail ();\r
351                 } catch (NotSupportedException) {\r
352                 }\r
353         }\r
354 \r
355         public void TestIsDefined () {\r
356                 MethodBuilder mb = genClass.DefineMethod (\r
357                         genMethodName (), 0, typeof (void), \r
358                         new Type [1] {typeof(int)});\r
359 \r
360                 try {\r
361                         mb.IsDefined (null, true);\r
362                         Fail ();\r
363                 } catch (NotSupportedException) {\r
364                 }\r
365         }\r
366 \r
367         public void TestGetCustomAttributes () {\r
368                 MethodBuilder mb = genClass.DefineMethod (\r
369                         genMethodName (), 0, typeof (void), \r
370                         new Type [1] {typeof(int)});\r
371 \r
372                 try {\r
373                         mb.GetCustomAttributes (true);\r
374                         Fail ();\r
375                 } catch (NotSupportedException) {\r
376                 }\r
377 \r
378                 try {\r
379                         mb.GetCustomAttributes (null, true);\r
380                         Fail ();\r
381                 } catch (NotSupportedException) {\r
382                 }\r
383         }\r
384 \r
385         public void TestSetCustomAttribute () {\r
386                 TypeBuilder tb = module.DefineType ("class21", TypeAttributes.Public);\r
387                 string name = genMethodName ();\r
388                 MethodBuilder mb = tb.DefineMethod (\r
389                         name, MethodAttributes.Public, typeof (void), \r
390                         new Type [1] {typeof(int)});\r
391 \r
392                 // Null argument\r
393                 try {\r
394                         mb.SetCustomAttribute (null);\r
395                         Fail ();\r
396                 } catch (ArgumentNullException) {\r
397                 }\r
398 \r
399                 byte[] custAttrData = { 1, 0, 0, 0, 0};\r
400                 Type attrType = Type.GetType\r
401                         ("System.Reflection.AssemblyKeyNameAttribute");\r
402                 Type[] paramTypes = new Type[1];\r
403                 paramTypes[0] = typeof(String);\r
404                 ConstructorInfo ctorInfo =\r
405                         attrType.GetConstructor(paramTypes);\r
406 \r
407                 mb.SetCustomAttribute (ctorInfo, custAttrData);\r
408 \r
409                 // Test MethodImplAttribute\r
410                 mb.SetCustomAttribute (new CustomAttributeBuilder (typeof (MethodImplAttribute).GetConstructor (new Type[1] { typeof (short) }), new object[1] {(short)MethodImplAttributes.Synchronized}));\r
411                 mb.GetILGenerator ().Emit (OpCodes.Ret);\r
412 \r
413                 Type t = tb.CreateType ();\r
414 \r
415                 AssertEquals ("Setting MethodImplAttributes works",\r
416                                           MethodImplAttributes.Synchronized,\r
417                                           t.GetMethod (name).GetMethodImplementationFlags ());\r
418 \r
419                 // Null arguments again\r
420                 try {\r
421                         mb.SetCustomAttribute (null, new byte[2]);\r
422                         Fail ();\r
423                 } catch (ArgumentNullException) {\r
424                 }\r
425 \r
426                 try {\r
427                         mb.SetCustomAttribute (ctorInfo, null);\r
428                         Fail ();\r
429                 } catch (ArgumentNullException) {\r
430                 }\r
431         }\r
432 }\r
433 }\r