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