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 ());