* MethodBuilder.cs: In CreateMethodBody, throw ArgumentOutOfRangeException
[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         [Test]
539         [ExpectedException (typeof (InvalidOperationException))]
540         public void TestAddDeclarativeSecurityAlreadyCreated () {
541                 MethodBuilder mb = genClass.DefineMethod (
542                         genMethodName (), MethodAttributes.Public, typeof (void),
543                         new Type [0]);
544                 ILGenerator ilgen = mb.GetILGenerator ();
545                 ilgen.Emit (OpCodes.Ret);
546                 genClass.CreateType ();
547
548                 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
549                 mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
550         }
551
552         [Test]
553         [ExpectedException (typeof (ArgumentNullException))]
554         public void TestAddDeclarativeSecurityNullPermissionSet () {
555                 MethodBuilder mb = genClass.DefineMethod (
556                         genMethodName (), MethodAttributes.Public, typeof (void), 
557                         new Type [0]);
558                 mb.AddDeclarativeSecurity (SecurityAction.Demand, null);
559         }
560
561         [Test]
562         public void TestAddDeclarativeSecurityInvalidAction () {
563                 MethodBuilder mb = genClass.DefineMethod (
564                         genMethodName (), MethodAttributes.Public, typeof (void), 
565                         new Type [0]);
566
567                 SecurityAction[] actions = new SecurityAction [] { 
568                         SecurityAction.RequestMinimum,
569                         SecurityAction.RequestOptional,
570                         SecurityAction.RequestRefuse };
571                 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
572
573                 foreach (SecurityAction action in actions) {
574                         try {
575                                 mb.AddDeclarativeSecurity (action, set);
576                                 Fail ();
577                         }
578                         catch (ArgumentException) {
579                         }
580                 }
581         }
582
583         [Test]
584         [ExpectedException (typeof (InvalidOperationException))]
585         public void TestAddDeclarativeSecurityDuplicateAction () {
586                 MethodBuilder mb = genClass.DefineMethod (
587                         genMethodName (), MethodAttributes.Public, typeof (void), 
588                         new Type [0]);
589                 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
590                 mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
591                 mb.AddDeclarativeSecurity (SecurityAction.Demand, set);
592         }
593
594         [AttributeUsage (AttributeTargets.Parameter)]
595         class ParamAttribute : Attribute {
596
597                 public ParamAttribute () {
598                 }
599         }
600
601         [Test]
602         public void TestDynamicParams () {
603                 string mname = genMethodName ();
604
605                 MethodBuilder mb = genClass.DefineMethod (
606                         mname, MethodAttributes.Public, typeof (void), 
607                         new Type [] { typeof (int), typeof (string) });
608                 ParameterBuilder pb = mb.DefineParameter (1, ParameterAttributes.In, "foo");
609                 pb.SetConstant (52);
610                 pb.SetCustomAttribute (new CustomAttributeBuilder (typeof (ParamAttribute).GetConstructors () [0], new object [] { }));
611                 ParameterBuilder pb2 = mb.DefineParameter (2, 0, "bar");
612                 pb2.SetConstant ("foo");
613                 mb.GetILGenerator ().Emit (OpCodes.Ret);
614
615                 Type t = genClass.CreateType ();
616                 MethodInfo m = t.GetMethod (mname);
617                 ParameterInfo[] pi = m.GetParameters ();
618
619                 AssertEquals ("foo", pi [0].Name);
620                 AssertEquals (true, pi [0].IsIn);
621                 AssertEquals (52, pi [0].DefaultValue);
622                 object[] cattrs = pi [0].GetCustomAttributes (true);
623
624                 AssertEquals ("foo", pi [1].DefaultValue);
625                 
626
627                 /* This test does not run under MS.NET: */
628                 /*
629                   AssertEquals (1, cattrs.Length);
630                   AssertEquals (typeof (ParamAttribute), cattrs [0].GetType ());
631                 */
632         }
633
634 #if NET_2_0
635         [Test]
636         public void SetCustomAttribute_DllImport1 () {
637                 string mname = genMethodName ();
638
639                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
640                 MethodBuilder mb = tb.DefineMethod (
641                         mname, MethodAttributes.Public, typeof (void), 
642                         new Type [] { typeof (int), typeof (string) });
643
644                 // Create an attribute with default values
645                 mb.SetCustomAttribute (new CustomAttributeBuilder(typeof(DllImportAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "kernel32" }));
646
647                 Type t = tb.CreateType ();
648
649                 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
650
651                 AssertEquals (CallingConvention.Winapi, attr.CallingConvention);
652                 AssertEquals (mname, attr.EntryPoint);
653                 AssertEquals ("kernel32", attr.Value);
654                 AssertEquals (false, attr.ExactSpelling);
655                 AssertEquals (true, attr.PreserveSig);
656                 AssertEquals (false, attr.SetLastError);
657                 AssertEquals (false, attr.BestFitMapping);
658                 AssertEquals (false, attr.ThrowOnUnmappableChar);
659         }
660
661         [Test]
662         public void SetCustomAttribute_DllImport2 () {
663                 string mname = genMethodName ();
664
665                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
666                 MethodBuilder mb = tb.DefineMethod (
667                         mname, MethodAttributes.Public, typeof (void), 
668                         new Type [] { typeof (int), typeof (string) });
669
670                 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 });
671                 mb.SetCustomAttribute (cb);
672
673                 Type t = tb.CreateType ();
674
675                 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
676
677                 AssertEquals (CallingConvention.StdCall, attr.CallingConvention);
678                 AssertEquals (CharSet.Unicode, attr.CharSet);
679                 AssertEquals ("bar", attr.EntryPoint);
680                 AssertEquals ("foo", attr.Value);
681                 AssertEquals (true, attr.ExactSpelling);
682                 AssertEquals (false, attr.PreserveSig);
683                 AssertEquals (false, attr.SetLastError);
684                 AssertEquals (false, attr.BestFitMapping);
685                 AssertEquals (false, attr.ThrowOnUnmappableChar);
686         }
687
688         [Test]
689         public void SetCustomAttribute_DllImport3 () {
690                 string mname = genMethodName ();
691
692                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
693                 MethodBuilder mb = tb.DefineMethod (
694                         mname, MethodAttributes.Public, typeof (void), 
695                         new Type [] { typeof (int), typeof (string) });
696
697                 // Test attributes with three values (on/off/missing)
698                 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 });
699                 mb.SetCustomAttribute (cb);
700
701                 Type t = tb.CreateType ();
702
703                 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
704
705                 AssertEquals (false, attr.BestFitMapping);
706                 AssertEquals (false, attr.ThrowOnUnmappableChar);
707         }
708
709         [Test]
710         public void SetCustomAttribute_DllImport4 () {
711                 string mname = genMethodName ();
712
713                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
714                 MethodBuilder mb = tb.DefineMethod (
715                         mname, MethodAttributes.Public, typeof (void), 
716                         new Type [] { typeof (int), typeof (string) });
717
718                 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 });
719                 mb.SetCustomAttribute (cb);
720
721                 Type t = tb.CreateType ();
722
723                 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod (mname).GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
724
725                 AssertEquals (true, attr.SetLastError);
726                 AssertEquals (true, attr.BestFitMapping);
727                 AssertEquals (true, attr.ThrowOnUnmappableChar);
728         }
729 #endif
730 }
731 }