2 // MethodBuilderTest.cs - NUnit Test Cases for the MethodBuilder class
4 // Zoltan Varga (vargaz@freemail.hu)
6 // (C) Ximian, Inc. http://www.ximian.com
9 // - implement 'Signature' (what the hell it does???) and test it
10 // - implement Equals and test it
13 using System
.Threading
;
14 using System
.Reflection
;
15 using System
.Reflection
.Emit
;
16 using System
.Runtime
.CompilerServices
;
17 using System
.Security
;
18 using System
.Security
.Permissions
;
20 using NUnit
.Framework
;
22 namespace MonoTests
.System
.Reflection
.Emit
26 public class MethodBuilderTest
: Assertion
28 private TypeBuilder genClass
;
30 private ModuleBuilder module
;
33 protected void SetUp () {
34 AssemblyName assemblyName
= new AssemblyName();
35 assemblyName
.Name
= "MonoTests.System.Reflection.Emit.MethodBuilderTest";
37 AssemblyBuilder assembly
38 = Thread
.GetDomain().DefineDynamicAssembly(
39 assemblyName
, AssemblyBuilderAccess
.Run
);
41 module
= assembly
.DefineDynamicModule("module1");
43 genClass
= module
.DefineType(genTypeName (),
44 TypeAttributes
.Public
);
47 static int methodIndexer
= 0;
49 static int typeIndexer
= 0;
51 // Return a unique method name
52 private string genMethodName () {
53 return "m" + (methodIndexer
++);
56 // Return a unique type name
57 private string genTypeName () {
58 return "class" + (typeIndexer
++);
61 public void TestAttributes () {
62 MethodBuilder mb
= genClass
.DefineMethod (
63 genMethodName (), MethodAttributes
.Public
, typeof (void), new Type
[0]);
65 AssertEquals ("Attributes works",
66 MethodAttributes
.Public
, mb
.Attributes
);
69 public void TestCallingConvention () {
70 MethodBuilder mb
= genClass
.DefineMethod (
71 genMethodName (), 0, typeof (void), new Type
[0]);
72 AssertEquals ("CallingConvetion defaults to Standard+HasThis",
73 CallingConventions
.Standard
| CallingConventions
.HasThis
,
74 mb
.CallingConvention
);
76 MethodBuilder mb3
= genClass
.DefineMethod (
77 genMethodName (), 0, CallingConventions
.VarArgs
, typeof (void), new Type
[0]);
78 AssertEquals ("CallingConvetion works",
79 CallingConventions
.VarArgs
| CallingConventions
.HasThis
,
80 mb3
.CallingConvention
);
82 MethodBuilder mb4
= genClass
.DefineMethod (
83 genMethodName (), MethodAttributes
.Static
, CallingConventions
.Standard
,
84 typeof (void), new Type
[0]);
85 AssertEquals ("Static implies !HasThis",
86 CallingConventions
.Standard
,
87 mb4
.CallingConvention
);
90 public void TestDeclaringType () {
91 MethodBuilder mb
= genClass
.DefineMethod (
92 genMethodName (), 0, typeof (void), new Type
[0]);
94 AssertEquals ("DeclaringType works",
95 genClass
, mb
.DeclaringType
);
98 public void TestInitLocals () {
99 MethodBuilder mb
= genClass
.DefineMethod (
100 genMethodName (), 0, typeof (void), new Type
[0]);
102 Assert ("InitLocals defaults to true", mb
.InitLocals
);
103 mb
.InitLocals
= false;
104 Assert ("InitLocals is settable", !mb
.InitLocals
);
107 public void TestMethodHandle () {
108 MethodBuilder mb
= genClass
.DefineMethod (
109 genMethodName (), 0, typeof (void), new Type
[0]);
112 RuntimeMethodHandle handle
= mb
.MethodHandle
;
114 } catch (NotSupportedException
) {
118 public void TestName () {
119 string name
= genMethodName ();
120 MethodBuilder mb
= genClass
.DefineMethod (
121 name
, 0, typeof (void), new Type
[0]);
123 AssertEquals ("Name works", name
, mb
.Name
);
126 public void TestReflectedType () {
127 MethodBuilder mb
= genClass
.DefineMethod (
128 genMethodName (), 0, typeof (void), new Type
[0]);
130 AssertEquals ("ReflectedType works",
131 genClass
, mb
.ReflectedType
);
134 public void TestReturnType () {
135 MethodBuilder mb
= genClass
.DefineMethod (
136 genMethodName (), 0, typeof (Console
), new Type
[0]);
138 AssertEquals ("ReturnType works", typeof (Console
),
142 MethodBuilder mb2
= genClass
.DefineMethod (
143 genMethodName (), 0, null, new Type
[0]);
145 Assert ("void ReturnType works", (mb2
.ReturnType
== null) || (mb2
.ReturnType
== typeof (void)));
148 public void TestReturnTypeCustomAttributes () {
149 MethodBuilder mb
= genClass
.DefineMethod (
150 genMethodName (), 0, typeof (Console
), new Type
[0]);
152 AssertEquals ("ReturnTypeCustomAttributes must be null", null,
153 mb
.ReturnTypeCustomAttributes
);
157 public void TestSignature () {
158 MethodBuilder mb = genClass.DefineMethod (
159 "m91", 0, typeof (Console), new Type [1] { typeof (Console) });
161 Console.WriteLine (mb.Signature);
165 public void TestCreateMethodBody () {
166 MethodBuilder mb
= genClass
.DefineMethod (
167 genMethodName (), 0, typeof (void), new Type
[0]);
170 mb
.CreateMethodBody (null, 999);
172 // Check arguments 1.
174 mb
.CreateMethodBody (new byte[1], -1);
176 } catch (ArgumentException
) {
179 // Check arguments 2.
181 mb
.CreateMethodBody (new byte[1], 2);
183 } catch (ArgumentException
) {
186 mb
.CreateMethodBody (new byte[2], 1);
188 // Could only be called once
190 mb
.CreateMethodBody (new byte[2], 1);
192 } catch (InvalidOperationException
) {
195 // Can not be called on a created type
196 TypeBuilder tb
= module
.DefineType (genTypeName (), TypeAttributes
.Public
);
197 MethodBuilder mb2
= tb
.DefineMethod (
198 genMethodName (), 0, typeof (void), new Type
[0]);
199 ILGenerator ilgen
= mb2
.GetILGenerator ();
200 ilgen
.Emit (OpCodes
.Ret
);
204 mb2
.CreateMethodBody (new byte[2], 1);
206 } catch (InvalidOperationException
) {
211 [ExpectedException (typeof(InvalidOperationException
))]
212 public void TestDefineParameterInvalidIndexComplete ()
214 TypeBuilder tb
= module
.DefineType (genTypeName (), TypeAttributes
.Public
);
215 MethodBuilder mb
= tb
.DefineMethod (
216 genMethodName (), 0, typeof (void),
218 typeof(int), typeof(int)
221 mb
.DefineParameter (-5, ParameterAttributes
.None
, "param1");
225 [ExpectedException (typeof(InvalidOperationException
))]
226 public void TestDefineParameterValidIndexComplete ()
228 TypeBuilder tb
= module
.DefineType (genTypeName (), TypeAttributes
.Public
);
229 MethodBuilder mb
= tb
.DefineMethod (
230 genMethodName (), 0, typeof (void),
232 typeof(int), typeof(int)
235 mb
.DefineParameter (1, ParameterAttributes
.None
, "param1");
238 public void TestDefineParameter () {
239 TypeBuilder tb
= module
.DefineType (genTypeName (), TypeAttributes
.Public
);
240 MethodBuilder mb
= tb
.DefineMethod (
241 genMethodName (), 0, typeof (void),
242 new Type
[2] { typeof(int), typeof(int) }
);
244 // index out of range
246 // This fails on mono because the mono version accepts a 0 index
249 mb.DefineParameter (0, 0, "param1");
251 } catch (ArgumentOutOfRangeException) {
256 mb
.DefineParameter (3, 0, "param1");
258 } catch (ArgumentOutOfRangeException
) {
262 mb
.DefineParameter (1, 0, "param1");
263 mb
.DefineParameter (1, 0, "param1");
264 mb
.DefineParameter (2, 0, null);
266 // Can not be called on a created type
267 mb
.CreateMethodBody (new byte[2], 0);
270 mb
.DefineParameter (1, 0, "param1");
273 catch (InvalidOperationException
) {
278 public void TestHashCode ()
280 TypeBuilder tb
= module
.DefineType (genTypeName (), TypeAttributes
.Public
);
281 string methodName
= genMethodName ();
282 MethodBuilder mb
= tb
.DefineMethod (
283 methodName
, 0, typeof (void),
285 typeof(int), typeof(int)
287 AssertEquals ("Hashcode of method should be equal to hashcode of method name",
288 methodName
.GetHashCode (), mb
.GetHashCode ());
291 public void TestGetBaseDefinition () {
292 MethodBuilder mb
= genClass
.DefineMethod (
293 genMethodName (), 0, typeof (void), new Type
[0]);
295 AssertEquals ("GetBaseDefinition works",
296 mb
.GetBaseDefinition (), mb
);
299 public void TestGetILGenerator () {
300 MethodBuilder mb
= genClass
.DefineMethod (
301 genMethodName (), 0, typeof (void), new Type
[0]);
303 // The same instance is returned on the second call
304 ILGenerator ilgen1
= mb
.GetILGenerator ();
305 ILGenerator ilgen2
= mb
.GetILGenerator ();
307 AssertEquals ("The same ilgen is returned on the second call",
310 // Does not work on unmanaged code
311 MethodBuilder mb2
= genClass
.DefineMethod (
312 genMethodName (), 0, typeof (void), new Type
[0]);
314 mb2
.SetImplementationFlags (MethodImplAttributes
.Unmanaged
);
315 mb2
.GetILGenerator ();
317 } catch (InvalidOperationException
) {
320 mb2
.SetImplementationFlags (MethodImplAttributes
.Native
);
321 mb2
.GetILGenerator ();
323 } catch (InvalidOperationException
) {
327 public void TestMethodImplementationFlags () {
328 TypeBuilder tb
= module
.DefineType (genTypeName (), TypeAttributes
.Public
);
329 MethodBuilder mb
= tb
.DefineMethod (
330 genMethodName (), 0, typeof (void), new Type
[0]);
332 AssertEquals ("MethodImplementationFlags defaults to Managed+IL",
333 MethodImplAttributes
.Managed
| MethodImplAttributes
.IL
,
334 mb
.GetMethodImplementationFlags ());
336 mb
.SetImplementationFlags (MethodImplAttributes
.OPTIL
);
338 AssertEquals ("SetImplementationFlags works",
339 MethodImplAttributes
.OPTIL
,
340 mb
.GetMethodImplementationFlags ());
342 // Can not be called on a created type
343 mb
.CreateMethodBody (new byte[2], 0);
344 mb
.SetImplementationFlags (MethodImplAttributes
.Managed
);
347 mb
.SetImplementationFlags (MethodImplAttributes
.OPTIL
);
350 catch (InvalidOperationException
) {
354 public void TestGetModule () {
355 MethodBuilder mb
= genClass
.DefineMethod (
356 genMethodName (), 0, typeof (void), new Type
[0]);
358 AssertEquals ("GetMethod works", module
,
362 public void TestGetParameters () {
363 TypeBuilder tb
= module
.DefineType (genTypeName (), TypeAttributes
.Public
);
364 MethodBuilder mb
= tb
.DefineMethod (
365 genMethodName (), 0, typeof (void), new Type
[1] {typeof(void)}
);
368 * According to the MSDN docs, this method should fail with a
369 * NotSupportedException. In reality, it throws an
370 * InvalidOperationException under MS .NET, and returns the
371 * requested data under mono.
377 } catch (InvalidOperationException ex) {
378 Console.WriteLine (ex);
383 public void TestGetToken () {
384 TypeBuilder tb
= module
.DefineType (genTypeName (), TypeAttributes
.Public
);
385 MethodBuilder mb
= tb
.DefineMethod (
386 genMethodName (), 0, typeof (void), new Type
[1] {typeof(void)}
);
391 public void TestInvoke () {
392 MethodBuilder mb
= genClass
.DefineMethod (
393 genMethodName (), 0, typeof (void),
394 new Type
[1] {typeof(int)}
);
397 mb
.Invoke (null, new object [1] { 42 }
);
399 } catch (NotSupportedException
) {
403 mb
.Invoke (null, 0, null, new object [1] { 42 }
, null);
405 } catch (NotSupportedException
) {
409 public void TestIsDefined () {
410 MethodBuilder mb
= genClass
.DefineMethod (
411 genMethodName (), 0, typeof (void),
412 new Type
[1] {typeof(int)}
);
415 mb
.IsDefined (null, true);
417 } catch (NotSupportedException
) {
421 public void TestGetCustomAttributes () {
422 MethodBuilder mb
= genClass
.DefineMethod (
423 genMethodName (), 0, typeof (void),
424 new Type
[1] {typeof(int)}
);
427 mb
.GetCustomAttributes (true);
429 } catch (NotSupportedException
) {
433 mb
.GetCustomAttributes (null, true);
435 } catch (NotSupportedException
) {
439 public void TestSetCustomAttribute () {
440 TypeBuilder tb
= module
.DefineType (genTypeName (), TypeAttributes
.Public
);
441 string name
= genMethodName ();
442 MethodBuilder mb
= tb
.DefineMethod (
443 name
, MethodAttributes
.Public
, typeof (void),
444 new Type
[1] {typeof(int)}
);
448 mb
.SetCustomAttribute (null);
450 } catch (ArgumentNullException
) {
453 byte[] custAttrData
= { 1, 0, 0, 0, 0}
;
454 Type attrType
= Type
.GetType
455 ("System.Reflection.AssemblyKeyNameAttribute");
456 Type
[] paramTypes
= new Type
[1];
457 paramTypes
[0] = typeof(String
);
458 ConstructorInfo ctorInfo
=
459 attrType
.GetConstructor(paramTypes
);
461 mb
.SetCustomAttribute (ctorInfo
, custAttrData
);
463 // Test MethodImplAttribute
464 mb
.SetCustomAttribute (new CustomAttributeBuilder (typeof (MethodImplAttribute
).GetConstructor (new Type
[1] { typeof (short) }
), new object[1] {(short)MethodImplAttributes.Synchronized}
));
465 mb
.GetILGenerator ().Emit (OpCodes
.Ret
);
467 Type t
= tb
.CreateType ();
469 AssertEquals ("Setting MethodImplAttributes works",
470 t
.GetMethod (name
).GetMethodImplementationFlags (),
471 MethodImplAttributes
.Synchronized
);
473 // Null arguments again
475 mb
.SetCustomAttribute (null, new byte[2]);
477 } catch (ArgumentNullException
) {
481 mb
.SetCustomAttribute (ctorInfo
, null);
483 } catch (ArgumentNullException
) {
488 [ExpectedException (typeof (InvalidOperationException
))]
489 public void TestAddDeclarativeSecurityAlreadyCreated () {
490 MethodBuilder mb
= genClass
.DefineMethod (
491 genMethodName (), MethodAttributes
.Public
, typeof (void),
493 ILGenerator ilgen
= mb
.GetILGenerator ();
494 ilgen
.Emit (OpCodes
.Ret
);
495 genClass
.CreateType ();
497 PermissionSet
set = new PermissionSet (PermissionState
.Unrestricted
);
498 mb
.AddDeclarativeSecurity (SecurityAction
.Demand
, set);
502 [ExpectedException (typeof (ArgumentNullException
))]
503 public void TestAddDeclarativeSecurityNullPermissionSet () {
504 MethodBuilder mb
= genClass
.DefineMethod (
505 genMethodName (), MethodAttributes
.Public
, typeof (void),
507 mb
.AddDeclarativeSecurity (SecurityAction
.Demand
, null);
511 public void TestAddDeclarativeSecurityInvalidAction () {
512 MethodBuilder mb
= genClass
.DefineMethod (
513 genMethodName (), MethodAttributes
.Public
, typeof (void),
516 SecurityAction
[] actions
= new SecurityAction
[] {
517 SecurityAction
.RequestMinimum
,
518 SecurityAction
.RequestOptional
,
519 SecurityAction
.RequestRefuse
};
520 PermissionSet
set = new PermissionSet (PermissionState
.Unrestricted
);
522 foreach (SecurityAction action
in actions
) {
524 mb
.AddDeclarativeSecurity (action
, set);
527 catch (ArgumentException
) {
533 [ExpectedException (typeof (InvalidOperationException
))]
534 public void TestAddDeclarativeSecurityDuplicateAction () {
535 MethodBuilder mb
= genClass
.DefineMethod (
536 genMethodName (), MethodAttributes
.Public
, typeof (void),
538 PermissionSet
set = new PermissionSet (PermissionState
.Unrestricted
);
539 mb
.AddDeclarativeSecurity (SecurityAction
.Demand
, set);
540 mb
.AddDeclarativeSecurity (SecurityAction
.Demand
, set);
543 [AttributeUsage (AttributeTargets
.Parameter
)]
544 class ParamAttribute
: Attribute
{
546 public ParamAttribute () {
551 public void TestDynamicParams () {
552 string mname
= genMethodName ();
554 MethodBuilder mb
= genClass
.DefineMethod (
555 mname
, MethodAttributes
.Public
, typeof (void),
556 new Type
[] { typeof (int), typeof (string) }
);
557 ParameterBuilder pb
= mb
.DefineParameter (1, 0, "foo");
559 pb
.SetCustomAttribute (new CustomAttributeBuilder (typeof (ParamAttribute
).GetConstructors () [0], new object [] { }
));
560 ParameterBuilder pb2
= mb
.DefineParameter (2, 0, "bar");
561 pb2
.SetConstant ("foo");
562 mb
.GetILGenerator ().Emit (OpCodes
.Ret
);
564 Type t
= genClass
.CreateType ();
565 MethodInfo m
= t
.GetMethod (mname
);
566 ParameterInfo
[] pi
= m
.GetParameters ();
568 AssertEquals ("foo", pi
[0].Name
);
569 AssertEquals (52, pi
[0].DefaultValue
);
570 object[] cattrs
= pi
[0].GetCustomAttributes (true);
572 AssertEquals ("foo", pi
[1].DefaultValue
);
575 /* This test does not run under MS.NET: */
577 AssertEquals (1, cattrs.Length);
578 AssertEquals (typeof (ParamAttribute), cattrs [0].GetType ());