**** Merged from MCS ****
[mono-project.git] / mcs / class / corlib / Test / System.Reflection.Emit / MethodBuilderTest.cs
blob5efe531940eac7d93536d4447069c0561aecd6ec
1 //
2 // MethodBuilderTest.cs - NUnit Test Cases for the MethodBuilder class
3 //
4 // Zoltan Varga (vargaz@freemail.hu)
5 //
6 // (C) Ximian, Inc. http://www.ximian.com
8 // TODO:
9 // - implement 'Signature' (what the hell it does???) and test it
10 // - implement Equals and test it
12 using System;
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
25 [TestFixture]
26 public class MethodBuilderTest : Assertion
28 private TypeBuilder genClass;
30 private ModuleBuilder module;
32 [SetUp]
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]);
111 try {
112 RuntimeMethodHandle handle = mb.MethodHandle;
113 Fail ();
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),
139 mb.ReturnType);
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]);
169 // Clear body
170 mb.CreateMethodBody (null, 999);
172 // Check arguments 1.
173 try {
174 mb.CreateMethodBody (new byte[1], -1);
175 Fail ();
176 } catch (ArgumentException) {
179 // Check arguments 2.
180 try {
181 mb.CreateMethodBody (new byte[1], 2);
182 Fail ();
183 } catch (ArgumentException) {
186 mb.CreateMethodBody (new byte[2], 1);
188 // Could only be called once
189 try {
190 mb.CreateMethodBody (new byte[2], 1);
191 Fail ();
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);
201 tb.CreateType ();
203 try {
204 mb2.CreateMethodBody (new byte[2], 1);
205 Fail ();
206 } catch (InvalidOperationException) {
210 [Test]
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),
217 new Type[2] {
218 typeof(int), typeof(int)
220 tb.CreateType ();
221 mb.DefineParameter (-5, ParameterAttributes.None, "param1");
224 [Test]
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),
231 new Type[2] {
232 typeof(int), typeof(int)
234 tb.CreateType ();
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
248 try {
249 mb.DefineParameter (0, 0, "param1");
250 Fail ();
251 } catch (ArgumentOutOfRangeException) {
255 try {
256 mb.DefineParameter (3, 0, "param1");
257 Fail ();
258 } catch (ArgumentOutOfRangeException) {
261 // Normal usage
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);
268 tb.CreateType ();
269 try {
270 mb.DefineParameter (1, 0, "param1");
271 Fail ();
273 catch (InvalidOperationException) {
277 [Test]
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),
284 new Type[2] {
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",
308 ilgen1, ilgen2);
310 // Does not work on unmanaged code
311 MethodBuilder mb2 = genClass.DefineMethod (
312 genMethodName (), 0, typeof (void), new Type [0]);
313 try {
314 mb2.SetImplementationFlags (MethodImplAttributes.Unmanaged);
315 mb2.GetILGenerator ();
316 Fail ();
317 } catch (InvalidOperationException) {
319 try {
320 mb2.SetImplementationFlags (MethodImplAttributes.Native);
321 mb2.GetILGenerator ();
322 Fail ();
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);
345 tb.CreateType ();
346 try {
347 mb.SetImplementationFlags (MethodImplAttributes.OPTIL);
348 Fail ();
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,
359 mb.GetModule ());
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.
374 try {
375 mb.GetParameters ();
376 Fail ("#161");
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)});
388 mb.GetToken ();
391 public void TestInvoke () {
392 MethodBuilder mb = genClass.DefineMethod (
393 genMethodName (), 0, typeof (void),
394 new Type [1] {typeof(int)});
396 try {
397 mb.Invoke (null, new object [1] { 42 });
398 Fail ();
399 } catch (NotSupportedException) {
402 try {
403 mb.Invoke (null, 0, null, new object [1] { 42 }, null);
404 Fail ();
405 } catch (NotSupportedException) {
409 public void TestIsDefined () {
410 MethodBuilder mb = genClass.DefineMethod (
411 genMethodName (), 0, typeof (void),
412 new Type [1] {typeof(int)});
414 try {
415 mb.IsDefined (null, true);
416 Fail ();
417 } catch (NotSupportedException) {
421 public void TestGetCustomAttributes () {
422 MethodBuilder mb = genClass.DefineMethod (
423 genMethodName (), 0, typeof (void),
424 new Type [1] {typeof(int)});
426 try {
427 mb.GetCustomAttributes (true);
428 Fail ();
429 } catch (NotSupportedException) {
432 try {
433 mb.GetCustomAttributes (null, true);
434 Fail ();
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)});
446 // Null argument
447 try {
448 mb.SetCustomAttribute (null);
449 Fail ();
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
474 try {
475 mb.SetCustomAttribute (null, new byte[2]);
476 Fail ();
477 } catch (ArgumentNullException) {
480 try {
481 mb.SetCustomAttribute (ctorInfo, null);
482 Fail ();
483 } catch (ArgumentNullException) {
487 [Test]
488 [ExpectedException (typeof (InvalidOperationException))]
489 public void TestAddDeclarativeSecurityAlreadyCreated () {
490 MethodBuilder mb = genClass.DefineMethod (
491 genMethodName (), MethodAttributes.Public, typeof (void),
492 new Type [0]);
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);
501 [Test]
502 [ExpectedException (typeof (ArgumentNullException))]
503 public void TestAddDeclarativeSecurityNullPermissionSet () {
504 MethodBuilder mb = genClass.DefineMethod (
505 genMethodName (), MethodAttributes.Public, typeof (void),
506 new Type [0]);
507 mb.AddDeclarativeSecurity (SecurityAction.Demand, null);
510 [Test]
511 public void TestAddDeclarativeSecurityInvalidAction () {
512 MethodBuilder mb = genClass.DefineMethod (
513 genMethodName (), MethodAttributes.Public, typeof (void),
514 new Type [0]);
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) {
523 try {
524 mb.AddDeclarativeSecurity (action, set);
525 Fail ();
527 catch (ArgumentException) {
532 [Test]
533 [ExpectedException (typeof (InvalidOperationException))]
534 public void TestAddDeclarativeSecurityDuplicateAction () {
535 MethodBuilder mb = genClass.DefineMethod (
536 genMethodName (), MethodAttributes.Public, typeof (void),
537 new Type [0]);
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 () {
550 [Test]
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");
558 pb.SetConstant (52);
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 ());