In corlib/System.Runtime.InteropServices:
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / MethodBuilderTest.cs
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
7
8 // TODO:
9 //  - implement 'Signature' (what the hell it does???) and test it
10 //  - implement Equals and test it
11
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;
19 using System.Runtime.InteropServices;
20
21 using NUnit.Framework;
22
23 namespace MonoTests.System.Reflection.Emit
24 {
25         [TestFixture]
26         public class MethodBuilderTest
27         {
28                 private TypeBuilder genClass;
29                 private ModuleBuilder module;
30
31                 [SetUp]
32                 protected void SetUp ()
33                 {
34                         AssemblyName assemblyName = new AssemblyName ();
35                         assemblyName.Name = "MonoTests.System.Reflection.Emit.MethodBuilderTest";
36
37                         AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (
38                                 assemblyName, AssemblyBuilderAccess.Run);
39                         module = assembly.DefineDynamicModule ("module1");
40                         genClass = module.DefineType (genTypeName (), TypeAttributes.Public);
41                 }
42
43                 static int methodIndexer = 0;
44                 static int typeIndexer = 0;
45
46                 // Return a unique method name
47                 private string genMethodName ()
48                 {
49                         return "m" + (methodIndexer++);
50                 }
51
52                 // Return a unique type name
53                 private string genTypeName ()
54                 {
55                         return "class" + (typeIndexer++);
56                 }
57
58                 [Test]
59                 public void TestAttributes ()
60                 {
61                         MethodBuilder mb = genClass.DefineMethod (
62                                 genMethodName (), MethodAttributes.Public, typeof (void), new Type [0]);
63                         Assert.AreEqual (MethodAttributes.Public, mb.Attributes);
64                 }
65
66                 [Test]
67                 public void TestCallingConvention ()
68                 {
69                         MethodBuilder mb = genClass.DefineMethod (
70                                 genMethodName (), 0, typeof (void), new Type [0]);
71                         Assert.AreEqual (CallingConventions.Standard | CallingConventions.HasThis,
72                                 mb.CallingConvention, "CallingConvetion defaults to Standard+HasThis");
73
74                         MethodBuilder mb3 = genClass.DefineMethod (
75                                 genMethodName (), 0, CallingConventions.VarArgs, typeof (void), new Type [0]);
76                         Assert.AreEqual (CallingConventions.VarArgs | CallingConventions.HasThis,
77                                 mb3.CallingConvention, "CallingConvetion works");
78
79                         MethodBuilder mb4 = genClass.DefineMethod (
80                                 genMethodName (), MethodAttributes.Static, CallingConventions.Standard,
81                                 typeof (void), new Type [0]);
82                         Assert.AreEqual (CallingConventions.Standard, mb4.CallingConvention,
83                                 "Static implies !HasThis");
84                 }
85
86                 [Test]
87                 public void TestDeclaringType ()
88                 {
89                         MethodBuilder mb = genClass.DefineMethod (
90                                 genMethodName (), 0, typeof (void), new Type [0]);
91
92                         Assert.AreEqual (genClass, mb.DeclaringType, "DeclaringType works");
93                 }
94
95                 [Test]
96                 public void TestInitLocals ()
97                 {
98                         MethodBuilder mb = genClass.DefineMethod (
99                                 genMethodName (), 0, typeof (void), new Type [0]);
100
101                         Assert.IsTrue (mb.InitLocals, "#1");
102                         mb.InitLocals = false;
103                         Assert.IsFalse (mb.InitLocals, "#2");
104                 }
105
106                 [Test]
107                 [ExpectedException (typeof (NotSupportedException))]
108                 public void TestMethodHandleIncomplete ()
109                 {
110                         MethodBuilder mb = genClass.DefineMethod (
111                                 genMethodName (), 0, typeof (void), new Type [0]);
112
113                         RuntimeMethodHandle handle = mb.MethodHandle;
114                 }
115
116                 [Test]
117                 [ExpectedException (typeof (NotSupportedException))]
118                 public void TestMethodHandleComplete ()
119                 {
120                         MethodBuilder mb = genClass.DefineMethod (
121                                 genMethodName (), 0, typeof (void), new Type [0]);
122                         mb.CreateMethodBody (new byte [2], 1);
123                         genClass.CreateType ();
124
125                         RuntimeMethodHandle handle = mb.MethodHandle;
126                 }
127
128                 [Test]
129                 public void TestName ()
130                 {
131                         string name = genMethodName ();
132                         MethodBuilder mb = genClass.DefineMethod (
133                                 name, 0, typeof (void), new Type [0]);
134
135                         Assert.AreEqual (name, mb.Name);
136                 }
137
138                 [Test]
139                 public void TestReflectedType ()
140                 {
141                         MethodBuilder mb = genClass.DefineMethod (
142                                 genMethodName (), 0, typeof (void), new Type [0]);
143
144                         Assert.AreEqual (genClass, mb.ReflectedType);
145                 }
146
147                 [Test]
148                 public void TestReturnType ()
149                 {
150                         MethodBuilder mb = genClass.DefineMethod (
151                                 genMethodName (), 0, typeof (Console), new Type [0]);
152                         Assert.AreEqual (typeof (Console), mb.ReturnType, "#1");
153
154                         MethodBuilder mb2 = genClass.DefineMethod (
155                                 genMethodName (), 0, null, new Type [0]);
156                         Assert.IsTrue (mb2.ReturnType == null || mb2.ReturnType == typeof (void), "#2");
157                 }
158
159                 [Test]
160                 public void TestReturnTypeCustomAttributes ()
161                 {
162                         MethodBuilder mb = genClass.DefineMethod (
163                                 genMethodName (), 0, typeof (Console), new Type [0]);
164                         Assert.IsNull (mb.ReturnTypeCustomAttributes);
165                 }
166
167                 /*
168                 public void TestSignature () {
169                         MethodBuilder mb = genClass.DefineMethod (
170                                 "m91", 0, typeof (Console), new Type [1] { typeof (Console) });
171
172                         Console.WriteLine (mb.Signature);
173                 }
174                 */
175
176                 [Test]
177                 public void TestCreateMethodBody ()
178                 {
179                         MethodBuilder mb = genClass.DefineMethod (
180                                 genMethodName (), 0, typeof (void), new Type [0]);
181
182                         // Clear body
183                         mb.CreateMethodBody (null, 999);
184
185                         // Check arguments 1.
186                         try {
187                                 mb.CreateMethodBody (new byte [1], -1);
188                                 Assert.Fail ("#1");
189                         } catch (ArgumentOutOfRangeException) {
190                         }
191
192                         // Check arguments 2.
193                         try {
194                                 mb.CreateMethodBody (new byte [1], 2);
195                                 Assert.Fail ("#2");
196                         } catch (ArgumentOutOfRangeException) {
197                         }
198
199                         mb.CreateMethodBody (new byte [2], 1);
200
201                         // Could only be called once
202                         try {
203                                 mb.CreateMethodBody (new byte [2], 1);
204                                 Assert.Fail ("#3");
205                         } catch (InvalidOperationException) {
206                         }
207
208                         // Can not be called on a created type
209                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
210                         MethodBuilder mb2 = tb.DefineMethod (
211                                 genMethodName (), 0, typeof (void), new Type [0]);
212                         ILGenerator ilgen = mb2.GetILGenerator ();
213                         ilgen.Emit (OpCodes.Ret);
214                         tb.CreateType ();
215
216                         try {
217                                 mb2.CreateMethodBody (new byte [2], 1);
218                                 Assert.Fail ("#4");
219                         } catch (InvalidOperationException) {
220                         }
221                 }
222
223                 [Test]
224                 [ExpectedException (typeof (InvalidOperationException))]
225                 public void TestDefineParameterInvalidIndexComplete ()
226                 {
227                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
228                         MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
229                                 new Type [2] { typeof(int), typeof(int) });
230                         mb.CreateMethodBody (new byte [2], 1);
231                         tb.CreateType ();
232                         mb.DefineParameter (-5, ParameterAttributes.None, "param1");
233                 }
234
235                 [Test]
236                 [ExpectedException (typeof (InvalidOperationException))]
237                 public void TestDefineParameterValidIndexComplete ()
238                 {
239                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
240                         MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
241                                 new Type [2] { typeof(int), typeof(int) });
242                         mb.CreateMethodBody (new byte [2], 1);
243                         tb.CreateType ();
244                         mb.DefineParameter (1, ParameterAttributes.None, "param1");
245                 }
246
247                 [Test]
248                 public void TestDefineParameter ()
249                 {
250                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
251                         MethodBuilder mb = tb.DefineMethod (
252                                 genMethodName (), 0, typeof (void),
253                                 new Type [2] { typeof (int), typeof (int) });
254
255                         // index out of range
256
257                         // This fails on mono because the mono version accepts a 0 index
258                         /*
259                         try {
260                                 mb.DefineParameter (0, 0, "param1");
261                                 Fail ();
262                         } catch (ArgumentOutOfRangeException) {
263                         }
264                         */
265
266                         try {
267                                 mb.DefineParameter (3, 0, "param1");
268                                 Assert.Fail ("#1");
269                         } catch (ArgumentOutOfRangeException) {
270                         }
271
272                         // Normal usage
273                         mb.DefineParameter (1, 0, "param1");
274                         mb.DefineParameter (1, 0, "param1");
275                         mb.DefineParameter (2, 0, null);
276
277                         mb.CreateMethodBody (new byte [2], 1);
278                         tb.CreateType ();
279                         try {
280                                 mb.DefineParameter (1, 0, "param1");
281                                 Assert.Fail ("#2");
282                         } catch (InvalidOperationException) {
283                         }
284                 }
285
286                 [Test]
287 #if NET_2_0
288                 // MS.NET 2.x no longer allows a zero length method body
289                 // to be emitted
290                 [ExpectedException (typeof (InvalidOperationException))]
291 #endif
292                 public void ZeroLengthBodyTest1 ()
293                 {
294                         MethodBuilder mb = genClass.DefineMethod (
295                                 genMethodName (), 0, typeof (void),
296                                 new Type [2] { typeof (int), typeof (int) });
297                         mb.CreateMethodBody (new byte [2], 0);
298                         genClass.CreateType ();
299                 }
300
301                 // A zero length method body can be created
302                 [Test]
303                 public void ZeroLengthBodyTest2 ()
304                 {
305                         MethodBuilder mb = genClass.DefineMethod (
306                                 genMethodName (), 0, typeof (void),
307                                 new Type [2] { typeof (int), typeof (int) });
308                         mb.CreateMethodBody (new byte [2], 0);
309                 }
310
311                 [Test]
312                 public void TestHashCode ()
313                 {
314                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
315                         string methodName = genMethodName ();
316                         MethodBuilder mb = tb.DefineMethod (methodName, 0, typeof (void),
317                                 new Type [2] { typeof(int), typeof(int) });
318                         Assert.AreEqual (methodName.GetHashCode (), mb.GetHashCode ());
319                 }
320
321                 [Test]
322                 public void TestGetBaseDefinition ()
323                 {
324                         MethodBuilder mb = genClass.DefineMethod (
325                                 genMethodName (), 0, typeof (void), new Type [0]);
326                         Assert.AreEqual (mb.GetBaseDefinition (), mb);
327                 }
328
329                 [Test]
330                 public void TestGetILGenerator ()
331                 {
332                         MethodBuilder mb = genClass.DefineMethod (
333                                 genMethodName (), 0, typeof (void), new Type [0]);
334
335                         // The same instance is returned on the second call
336                         ILGenerator ilgen1 = mb.GetILGenerator ();
337                         ILGenerator ilgen2 = mb.GetILGenerator ();
338
339                         Assert.AreEqual (ilgen1, ilgen2, "#1");
340
341                         // Does not work on unmanaged code
342                         MethodBuilder mb2 = genClass.DefineMethod (
343                                 genMethodName (), 0, typeof (void), new Type [0]);
344                         try {
345                                 mb2.SetImplementationFlags (MethodImplAttributes.Unmanaged);
346                                 mb2.GetILGenerator ();
347                                 Assert.Fail ("#2");
348                         } catch (InvalidOperationException) {
349                         }
350                         try {
351                                 mb2.SetImplementationFlags (MethodImplAttributes.Native);
352                                 mb2.GetILGenerator ();
353                                 Assert.Fail ("#3");
354                         } catch (InvalidOperationException) {
355                         }
356                 }
357
358                 [Test]
359                 public void TestMethodImplementationFlags ()
360                 {
361                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
362                         MethodBuilder mb = tb.DefineMethod (
363                                 genMethodName (), 0, typeof (void), new Type [0]);
364
365                         Assert.AreEqual (MethodImplAttributes.Managed | MethodImplAttributes.IL,
366                                 mb.GetMethodImplementationFlags (), "#1");
367
368                         mb.SetImplementationFlags (MethodImplAttributes.OPTIL);
369
370                         Assert.AreEqual (MethodImplAttributes.OPTIL, mb.GetMethodImplementationFlags (), "#2");
371
372                         mb.CreateMethodBody (new byte [2], 1);
373                         mb.SetImplementationFlags (MethodImplAttributes.Managed);
374                         tb.CreateType ();
375                         try {
376                                 mb.SetImplementationFlags (MethodImplAttributes.OPTIL);
377                                 Assert.Fail ("#3");
378                         } catch (InvalidOperationException) {
379                         }
380                 }
381
382                 [Test]
383                 public void TestGetModule ()
384                 {
385                         MethodBuilder mb = genClass.DefineMethod (
386                                 genMethodName (), 0, typeof (void), new Type [0]);
387                         Assert.AreEqual (module, mb.GetModule ());
388                 }
389
390                 [Test]
391                 public void TestGetParameters ()
392                 {
393                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
394                         MethodBuilder mb = tb.DefineMethod (genMethodName (), 0, typeof (void),
395                                 new Type [1] { typeof (void) });
396
397                         /*
398                          * According to the MSDN docs, this method should fail with a
399                          * NotSupportedException. In reality, it throws an 
400                          * InvalidOperationException under MS .NET, and returns the 
401                          * requested data under mono.
402                          */
403                         /*
404                         try {
405                                 mb.GetParameters ();
406                                 Fail ("#161");
407                         } catch (InvalidOperationException ex) {
408                                 Console.WriteLine (ex);
409                         }
410                         */
411                 }
412
413                 [Test]
414                 public void TestGetToken ()
415                 {
416                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
417                         MethodBuilder mb = tb.DefineMethod (
418                                 genMethodName (), 0, typeof (void), new Type [1] { typeof (void) });
419                         mb.GetToken ();
420                 }
421
422                 [Test]
423                 public void TestInvoke ()
424                 {
425                         MethodBuilder mb = genClass.DefineMethod (
426                                 genMethodName (), 0, typeof (void),
427                                 new Type [1] { typeof (int) });
428
429                         try {
430                                 mb.Invoke (null, new object [1] { 42 });
431                                 Assert.Fail ("#1");
432                         } catch (NotSupportedException) {
433                         }
434
435                         try {
436                                 mb.Invoke (null, 0, null, new object [1] { 42 }, null);
437                                 Assert.Fail ("#2");
438                         } catch (NotSupportedException) {
439                         }
440                 }
441
442                 [Test]
443                 [ExpectedException (typeof (NotSupportedException))]
444                 public void TestIsDefined ()
445                 {
446                         MethodBuilder mb = genClass.DefineMethod (
447                                 genMethodName (), 0, typeof (void),
448                                 new Type [1] { typeof (int) });
449                         mb.IsDefined (null, true);
450                 }
451
452                 [Test]
453                 public void TestGetCustomAttributes ()
454                 {
455                         MethodBuilder mb = genClass.DefineMethod (
456                                 genMethodName (), 0, typeof (void),
457                                 new Type [1] { typeof (int) });
458
459                         try {
460                                 mb.GetCustomAttributes (true);
461                                 Assert.Fail ("#1");
462                         } catch (NotSupportedException) {
463                         }
464
465                         try {
466                                 mb.GetCustomAttributes (null, true);
467                                 Assert.Fail ("#2");
468                         } catch (NotSupportedException) {
469                         }
470                 }
471
472                 [Test]
473                 public void TestSetCustomAttribute ()
474                 {
475                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
476                         string name = genMethodName ();
477                         MethodBuilder mb = tb.DefineMethod (
478                                 name, MethodAttributes.Public, typeof (void),
479                                 new Type [1] { typeof (int) });
480
481                         // Null argument
482                         try {
483                                 mb.SetCustomAttribute (null);
484                                 Assert.Fail ("#1");
485                         } catch (ArgumentNullException) {
486                         }
487
488                         byte [] custAttrData = { 1, 0, 0, 0, 0 };
489                         Type attrType = Type.GetType
490                                 ("System.Reflection.AssemblyKeyNameAttribute");
491                         Type [] paramTypes = new Type [1];
492                         paramTypes [0] = typeof (String);
493                         ConstructorInfo ctorInfo =
494                                 attrType.GetConstructor (paramTypes);
495
496                         mb.SetCustomAttribute (ctorInfo, custAttrData);
497
498                         // Test MethodImplAttribute
499                         mb.SetCustomAttribute (new CustomAttributeBuilder (typeof (MethodImplAttribute).GetConstructor (new Type [1] { typeof (short) }), new object [1] { (short) MethodImplAttributes.Synchronized }));
500                         mb.GetILGenerator ().Emit (OpCodes.Ret);
501
502                         Type t = tb.CreateType ();
503
504                         Assert.AreEqual (t.GetMethod (name).GetMethodImplementationFlags (),
505                                 MethodImplAttributes.Synchronized, "#2");
506
507                         // Null arguments again
508                         try {
509                                 mb.SetCustomAttribute (null, new byte [2]);
510                                 Assert.Fail ("#3");
511                         } catch (ArgumentNullException) {
512                         }
513
514                         try {
515                                 mb.SetCustomAttribute (ctorInfo, null);
516                                 Assert.Fail ("#4");
517                         } catch (ArgumentNullException) {
518                         }
519                 }
520
521                 [Test]
522                 public void SetCustomAttribute_DllImport_DllName_Empty ()
523                 {
524                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
525                         MethodBuilder mb = tb.DefineMethod (genMethodName (),
526                                 MethodAttributes.Public, typeof (void),
527                                 new Type [1] { typeof (int) });
528
529                         ConstructorInfo ctorInfo = typeof (DllImportAttribute).GetConstructor (
530                                 new Type [] { typeof (string) });
531                         try {
532                                 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo,
533                                         new object [] { string.Empty }));
534                                 Assert.Fail ("#1");
535                         } catch (ArgumentException ex) {
536                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
537                                 Assert.IsNull (ex.InnerException, "#3");
538                                 Assert.IsNotNull (ex.Message, "#4");
539                                 Assert.IsNull (ex.ParamName, "#5");
540                         }
541                 }
542
543                 [Test]
544                 public void SetCustomAttribute_DllImport_DllName_Null ()
545                 {
546                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
547                         MethodBuilder mb = tb.DefineMethod (genMethodName (),
548                                 MethodAttributes.Public, typeof (void),
549                                 new Type [1] { typeof (int) });
550
551                         ConstructorInfo ctorInfo = typeof (DllImportAttribute).GetConstructor (
552                                 new Type [] { typeof (string) });
553                         try {
554                                 mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo,
555                                         new object [] { null }));
556                                 Assert.Fail ("#1");
557                         } catch (ArgumentException ex) {
558                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
559                                 Assert.IsNull (ex.InnerException, "#3");
560                                 Assert.IsNotNull (ex.Message, "#4");
561                                 Assert.IsNull (ex.ParamName, "#5");
562                         }
563                 }
564
565                 [AttributeUsage (AttributeTargets.Parameter)]
566                 class PrivateAttribute : Attribute
567                 {
568
569                         public PrivateAttribute ()
570                         {
571                         }
572                 }
573
574                 [Test]
575                 public void GetCustomAttributes ()
576                 {
577                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
578                         MethodBuilder mb = tb.DefineMethod ("foo", MethodAttributes.Public,
579                                                                                                 typeof (void),
580                                                                                                 new Type [1] { typeof (int) });
581                         mb.GetILGenerator ().Emit (OpCodes.Ret);
582
583                         Type attrType = typeof (ObsoleteAttribute);
584                         ConstructorInfo ctorInfo =
585                                 attrType.GetConstructor (new Type [] { typeof (String) });
586
587                         mb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
588
589                         // Check that attributes not accessible are not returned
590                         mb.SetCustomAttribute (new CustomAttributeBuilder (typeof (PrivateAttribute).GetConstructor (new Type [0]), new object [] { }));
591
592                         Type t = tb.CreateType ();
593
594                         // Try the created type
595                         {
596                                 MethodInfo mi = t.GetMethod ("foo");
597                                 object [] attrs = mi.GetCustomAttributes (true);
598
599                                 Assert.AreEqual (1, attrs.Length, "#A1");
600                                 Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#A2");
601                                 Assert.AreEqual ("FOO", ((ObsoleteAttribute) attrs [0]).Message, "#A3");
602                         }
603
604                         // Try the type builder
605                         {
606                                 MethodInfo mi = tb.GetMethod ("foo");
607                                 object [] attrs = mi.GetCustomAttributes (true);
608
609                                 Assert.AreEqual (1, attrs.Length, "#B1");
610                                 Assert.IsTrue (attrs [0] is ObsoleteAttribute, "#B2");
611                                 Assert.AreEqual ("FOO", ((ObsoleteAttribute) attrs [0]).Message, "#B3");
612                         }
613                 }
614
615                 [Test]
616                 [ExpectedException (typeof (InvalidOperationException))]
617                 public void TestAddDeclarativeSecurityAlreadyCreated ()
618                 {
619                         MethodBuilder mb = genClass.DefineMethod (
620                                 genMethodName (), MethodAttributes.Public, typeof (void),
621                                 new Type [0]);
622                         ILGenerator ilgen = mb.GetILGenerator ();
623                         ilgen.Emit (OpCodes.Ret);
624                         genClass.CreateType ();
625
626                         PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
627                         mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
628                 }
629
630                 [Test]
631                 [ExpectedException (typeof (ArgumentNullException))]
632                 public void TestAddDeclarativeSecurityNullPermissionSet ()
633                 {
634                         MethodBuilder mb = genClass.DefineMethod (
635                                 genMethodName (), MethodAttributes.Public, typeof (void),
636                                 new Type [0]);
637                         mb.AddDeclarativeSecurity (SecurityAction.Demand, null);
638                 }
639
640                 [Test]
641                 public void TestAddDeclarativeSecurityInvalidAction ()
642                 {
643                         MethodBuilder mb = genClass.DefineMethod (
644                                 genMethodName (), MethodAttributes.Public, typeof (void),
645                                 new Type [0]);
646
647                         SecurityAction [] actions = new SecurityAction [] { 
648                         SecurityAction.RequestMinimum,
649                         SecurityAction.RequestOptional,
650                         SecurityAction.RequestRefuse };
651                         PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
652
653                         foreach (SecurityAction action in actions) {
654                                 try {
655                                         mb.AddDeclarativeSecurity (action, set);
656                                         Assert.Fail ();
657                                 } catch (ArgumentOutOfRangeException) {
658                                 }
659                         }
660                 }
661
662                 [Test]
663                 [ExpectedException (typeof (InvalidOperationException))]
664                 public void TestAddDeclarativeSecurityDuplicateAction ()
665                 {
666                         MethodBuilder mb = genClass.DefineMethod (
667                                 genMethodName (), MethodAttributes.Public, typeof (void),
668                                 new Type [0]);
669                         PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
670                         mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
671                         mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
672                 }
673
674                 [AttributeUsage (AttributeTargets.Parameter)]
675                 class ParamAttribute : Attribute
676                 {
677
678                         public ParamAttribute ()
679                         {
680                         }
681                 }
682
683                 [Test]
684                 public void TestDynamicParams ()
685                 {
686                         string mname = genMethodName ();
687
688                         MethodBuilder mb = genClass.DefineMethod (
689                                 mname, MethodAttributes.Public, typeof (void),
690                                 new Type [] { typeof (int), typeof (string) });
691                         ParameterBuilder pb = mb.DefineParameter (1, ParameterAttributes.In, "foo");
692                         pb.SetConstant (52);
693                         pb.SetCustomAttribute (new CustomAttributeBuilder (typeof (ParamAttribute).GetConstructors () [0], new object [] { }));
694                         ParameterBuilder pb2 = mb.DefineParameter (2, 0, "bar");
695                         pb2.SetConstant ("foo");
696                         mb.GetILGenerator ().Emit (OpCodes.Ret);
697
698                         Type t = genClass.CreateType ();
699                         MethodInfo m = t.GetMethod (mname);
700                         ParameterInfo [] pi = m.GetParameters ();
701
702                         Assert.AreEqual ("foo", pi [0].Name, "#A1");
703                         Assert.IsTrue (pi [0].IsIn, "#A2");
704                         Assert.AreEqual (52, pi [0].DefaultValue, "#A3");
705                         object [] cattrs = pi [0].GetCustomAttributes (true);
706 #if NET_2_0
707                         Assert.AreEqual (1, cattrs.Length, "#A4");
708                         Assert.AreEqual (typeof (InAttribute), cattrs [0].GetType (), "#A5");
709 #else
710                         Assert.AreEqual (0, cattrs.Length, "#A4");
711 #endif
712
713                         Assert.AreEqual ("foo", pi [1].DefaultValue, "#B1");
714                 }
715
716 #if NET_2_0
717                 [Test]
718                 public void SetCustomAttribute_DllImport1 ()
719                 {
720                         string mname = genMethodName ();
721
722                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
723                         MethodBuilder mb = tb.DefineMethod (
724                                 mname, MethodAttributes.Public, typeof (void), 
725                                 new Type [] { typeof (int), typeof (string) });
726
727                         // Create an attribute with default values
728                         mb.SetCustomAttribute (new CustomAttributeBuilder(typeof(DllImportAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "kernel32" }));
729
730                         Type t = tb.CreateType ();
731
732                         DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
733
734                         Assert.AreEqual (CallingConvention.Winapi, attr.CallingConvention, "#1");
735                         Assert.AreEqual (mname, attr.EntryPoint, "#2");
736                         Assert.AreEqual ("kernel32", attr.Value, "#3");
737                         Assert.IsFalse (attr.ExactSpelling, "#4");
738                         Assert.IsTrue (attr.PreserveSig, "#5");
739                         Assert.IsFalse (attr.SetLastError, "#6");
740                         Assert.IsFalse (attr.BestFitMapping, "#7");
741                         Assert.IsFalse (attr.ThrowOnUnmappableChar, "#8");
742                 }
743
744                 [Test]
745                 public void SetCustomAttribute_DllImport2 () {
746                         string mname = genMethodName ();
747
748                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
749                         MethodBuilder mb = tb.DefineMethod (
750                                 mname, MethodAttributes.Public, typeof (void), 
751                                 new Type [] { typeof (int), typeof (string) });
752
753                         CustomAttributeBuilder cb = new CustomAttributeBuilder (typeof (DllImportAttribute).GetConstructor (new Type [] {typeof (String)}), new object [] { "foo" }, new FieldInfo [] {typeof (DllImportAttribute).GetField ("EntryPoint"), typeof (DllImportAttribute).GetField ("CallingConvention"), typeof (DllImportAttribute).GetField ("CharSet"), typeof (DllImportAttribute).GetField ("ExactSpelling"), typeof (DllImportAttribute).GetField ("PreserveSig")}, new object [] { "bar", CallingConvention.StdCall, CharSet.Unicode, true, false });
754                         mb.SetCustomAttribute (cb);
755
756                         Type t = tb.CreateType ();
757
758                         DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
759
760                         Assert.AreEqual (CallingConvention.StdCall, attr.CallingConvention, "#1");
761                         Assert.AreEqual (CharSet.Unicode, attr.CharSet, "#2");
762                         Assert.AreEqual ("bar", attr.EntryPoint, "#3");
763                         Assert.AreEqual ("foo", attr.Value, "#4");
764                         Assert.IsTrue (attr.ExactSpelling, "#5");
765                         Assert.IsFalse (attr.PreserveSig, "#6");
766                         Assert.IsFalse (attr.SetLastError, "#7");
767                         Assert.IsFalse (attr.BestFitMapping, "#8");
768                         Assert.IsFalse (attr.ThrowOnUnmappableChar, "#9");
769                 }
770
771                 [Test]
772                 public void SetCustomAttribute_DllImport3 () {
773                         string mname = genMethodName ();
774
775                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
776                         MethodBuilder mb = tb.DefineMethod (
777                                 mname, MethodAttributes.Public, typeof (void), 
778                                 new Type [] { typeof (int), typeof (string) });
779
780                         // Test attributes with three values (on/off/missing)
781                         CustomAttributeBuilder cb = new CustomAttributeBuilder (typeof (DllImportAttribute).GetConstructor (new Type [] {typeof (String)}), new object [] { "foo" }, new FieldInfo [] { typeof (DllImportAttribute).GetField ("BestFitMapping"), typeof (DllImportAttribute).GetField ("ThrowOnUnmappableChar")}, new object [] { false, false });
782                         mb.SetCustomAttribute (cb);
783
784                         Type t = tb.CreateType ();
785
786                         DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
787
788                         Assert.IsFalse (attr.BestFitMapping, "#1");
789                         Assert.IsFalse (attr.ThrowOnUnmappableChar, "#2");
790                 }
791
792                 [Test]
793                 public void SetCustomAttribute_DllImport4 ()
794                 {
795                         string mname = genMethodName ();
796
797                         TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
798                         MethodBuilder mb = tb.DefineMethod (
799                                 mname, MethodAttributes.Public, typeof (void), 
800                                 new Type [] { typeof (int), typeof (string) });
801
802                         CustomAttributeBuilder cb = new CustomAttributeBuilder (typeof (DllImportAttribute).GetConstructor (new Type [] {typeof (String)}), new object [] { "foo" }, new FieldInfo [] { typeof (DllImportAttribute).GetField ("SetLastError"), typeof (DllImportAttribute).GetField ("BestFitMapping"), typeof (DllImportAttribute).GetField ("ThrowOnUnmappableChar")}, new object [] { true, true, true });
803                         mb.SetCustomAttribute (cb);
804
805                         Type t = tb.CreateType ();
806
807                         DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
808
809                         Assert.IsTrue (attr.SetLastError, "#1");
810                         Assert.IsTrue (attr.BestFitMapping, "#2");
811                         Assert.IsTrue (attr.ThrowOnUnmappableChar, "#3");
812                 }
813 #endif
814         }
815 }