2005-10-27 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / ConstructorBuilderTest.cs
1 //
2 // ConstructorBuilderTest.cs - NUnit Test Cases for the ConstructorBuilder 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.Security;
17 using System.Security.Permissions;
18
19 using NUnit.Framework;
20
21 namespace MonoTests.System.Reflection.Emit
22 {
23
24 [TestFixture]
25 public class ConstructorBuilderTest : Assertion
26 {       
27     private TypeBuilder genClass;
28
29         private ModuleBuilder module;
30
31         private static int typeIndexer = 0;
32
33         [SetUp]
34         protected void SetUp () {
35                 AssemblyName assemblyName = new AssemblyName();
36                 assemblyName.Name = "MonoTests.System.Reflection.Emit.ConstructorBuilderTest";
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         // Return a unique type name
49         private string genTypeName () {
50                 return "class" + (typeIndexer ++);
51         }
52
53         public void TestAttributes () {
54                 ConstructorBuilder cb = genClass.DefineConstructor (
55                          MethodAttributes.Public, 0, new Type [0]);
56
57                 Assert ("Attributes works", 
58                                 (cb.Attributes & MethodAttributes.Public) != 0);
59                 Assert ("Attributes works", 
60                                 (cb.Attributes & MethodAttributes.SpecialName) != 0);
61         }
62
63         public void TestCallingConvention () {
64                 /* This does not work under MS.NET
65                 ConstructorBuilder cb3 = genClass.DefineConstructor (
66                         0, CallingConventions.VarArgs, new Type [0]);
67                 AssertEquals ("CallingConvetion works",
68                                           CallingConventions.VarArgs | CallingConventions.HasThis,
69                                           cb3.CallingConvention);
70                 */
71
72                 ConstructorBuilder cb4 = genClass.DefineConstructor (
73                          MethodAttributes.Static, CallingConventions.Standard, new Type [0]);
74                 AssertEquals ("Static implies !HasThis",
75                                           cb4.CallingConvention,
76                                           CallingConventions.Standard);
77         }
78
79         public void TestDeclaringType () {
80                 ConstructorBuilder cb = genClass.DefineConstructor (
81                          0, 0, new Type[0]);
82
83                 AssertEquals ("DeclaringType works",
84                                           cb.DeclaringType, genClass);
85         }
86
87         public void TestInitLocals () {
88                 ConstructorBuilder cb = genClass.DefineConstructor (
89                          0, 0, new Type[0]);
90
91                 AssertEquals ("InitLocals defaults to true", cb.InitLocals, true);
92                 cb.InitLocals = false;
93                 AssertEquals ("InitLocals is settable", cb.InitLocals, false);
94         }
95         
96         [Test]
97         public void TestMethodHandle () {
98                 ConstructorBuilder cb = genClass.DefineConstructor (
99                          0, 0, new Type [0]);
100
101                 RuntimeMethodHandle handle = cb.MethodHandle;
102         }
103
104         public void TestName () {
105                 ConstructorBuilder cb = genClass.DefineConstructor (0, 0, new Type [0]);
106
107                 AssertEquals ("Name works", ".ctor", cb.Name);
108
109                 ConstructorBuilder cb2 = genClass.DefineConstructor (MethodAttributes.Static, 0, new Type [0]);
110                 AssertEquals ("Static constructors have the right name", ".cctor", cb2.Name);
111         }
112
113         public void TestReflectedType () {
114                 ConstructorBuilder cb = genClass.DefineConstructor (0, 0, new Type [0]);
115
116                 AssertEquals ("ReflectedType works", 
117                                           genClass, cb.ReflectedType);
118         }
119
120         public void TestReturnType () {
121                 ConstructorBuilder cb = genClass.DefineConstructor (0, 0, new Type [0]);
122
123                 AssertEquals ("ReturnType works", 
124                                           null, cb.ReturnType);
125         }
126
127         public void TestDefineParameter () {
128                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
129                 ConstructorBuilder cb = tb.DefineConstructor (
130                          0, 0, new Type [2] { typeof(int), typeof(int) });
131
132                 // index out of range
133                 try {
134                         cb.DefineParameter (0, 0, "param1");
135                         Fail ();
136                 } catch (ArgumentOutOfRangeException) {
137                 }
138                 try {
139                         cb.DefineParameter (3, 0, "param1");
140                         Fail ();
141                 } catch (ArgumentOutOfRangeException) {
142                 }
143
144                 // Normal usage
145                 cb.DefineParameter (1, 0, "param1");
146                 cb.DefineParameter (1, 0, "param1");
147                 cb.DefineParameter (2, 0, null);
148
149                 // Can not be called on a created type
150                 cb.GetILGenerator ().Emit (OpCodes.Ret);
151                 tb.CreateType ();
152                 try {
153                         cb.DefineParameter (1, 0, "param1");
154                         Fail ();
155                 }
156                 catch (InvalidOperationException) {
157                 }
158         }
159
160         public void TestGetCustomAttributes () {
161                 ConstructorBuilder cb = genClass.DefineConstructor (
162                         0, 0, new Type [1] {typeof(int)});
163
164                 try {
165                         cb.GetCustomAttributes (true);
166                         Fail ();
167                 } catch (NotSupportedException) {
168                 }
169
170                 try {
171                         cb.GetCustomAttributes (null, true);
172                         Fail ();
173                 } catch (NotSupportedException) {
174                 }
175         }
176
177         public void TestMethodImplementationFlags () {
178                 ConstructorBuilder cb = genClass.DefineConstructor (
179                          0, 0, new Type [0]);
180
181                 AssertEquals ("MethodImplementationFlags defaults to Managed+IL",
182                                           cb.GetMethodImplementationFlags (),
183                                           MethodImplAttributes.Managed | MethodImplAttributes.IL);
184
185                 cb.SetImplementationFlags (MethodImplAttributes.OPTIL);
186
187                 AssertEquals ("SetImplementationFlags works",
188                                           cb.GetMethodImplementationFlags (),
189                                           MethodImplAttributes.OPTIL);
190
191                 // Can not be called on a created type
192                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
193                 ConstructorBuilder cb2 = tb.DefineConstructor (
194                          0, 0, new Type [0]);
195
196                 cb2.GetILGenerator ().Emit (OpCodes.Ret);
197                 cb2.SetImplementationFlags (MethodImplAttributes.Managed);
198                 tb.CreateType ();
199                 try {
200                         cb2.SetImplementationFlags (MethodImplAttributes.OPTIL);
201                         Fail ();
202                 }
203                 catch (InvalidOperationException) {
204                 }
205         }
206
207         public void TestGetModule () {
208                 ConstructorBuilder cb = genClass.DefineConstructor (
209                          0, 0, new Type [0]);
210
211                 AssertEquals ("GetModule works",
212                                           module, cb.GetModule ());
213         }
214
215         public void TestGetParameters () {
216                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
217                 ConstructorBuilder cb = tb.DefineConstructor (
218                          0, 0, new Type [1] {typeof(int)});
219                 cb.GetILGenerator ().Emit (OpCodes.Ret);
220
221                 // Can't be called before CreateType ()
222                 /* This does not work under mono
223                 try {
224                         cb.GetParameters ();
225                         Fail ();
226                 } catch (InvalidOperationException) {
227                 }
228                 */
229
230                 tb.CreateType ();
231
232                 /* This does not work under MS.NET !
233                 cb.GetParameters ();
234                 */
235         }
236
237         public void TestGetToken () {
238                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
239                 ConstructorBuilder cb = tb.DefineConstructor (
240                          0, 0, new Type [1] {typeof(void)});
241
242                 cb.GetToken ();
243         }
244
245         public void TestInvoke () {
246                 ConstructorBuilder cb = genClass.DefineConstructor (
247                          0, 0, 
248                         new Type [1] {typeof(int)});
249
250                 try {
251                         cb.Invoke (null, new object [1] { 42 });
252                         Fail ();
253                 } catch (NotSupportedException) {
254                 }
255
256                 try {
257                         cb.Invoke (null, 0, null, new object [1] { 42 }, null);
258                         Fail ();
259                 } catch (NotSupportedException) {
260                 }
261         }
262
263         public void TestIsDefined () {
264                 ConstructorBuilder cb = genClass.DefineConstructor (
265                          0, 0, 
266                         new Type [1] {typeof(int)});
267
268                 try {
269                         cb.IsDefined (null, true);
270                         Fail ();
271                 } catch (NotSupportedException) {
272                 }
273         }
274
275         public void TestSetCustomAttribute () {
276                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
277                 ConstructorBuilder cb = tb.DefineConstructor (
278                          0, 0, 
279                         new Type [1] {typeof(int)});
280                 cb.GetILGenerator ().Emit (OpCodes.Ret);
281
282                 // Null argument
283                 try {
284                         cb.SetCustomAttribute (null);
285                         Fail ();
286                 } catch (ArgumentNullException) {
287                 }
288
289                 byte[] custAttrData = { 1, 0, 0, 0, 0};
290                 Type attrType = Type.GetType
291                         ("System.Reflection.AssemblyKeyNameAttribute");
292                 Type[] paramTypes = new Type[1];
293                 paramTypes[0] = typeof(String);
294                 ConstructorInfo ctorInfo =
295                         attrType.GetConstructor(paramTypes);
296
297                 cb.SetCustomAttribute (ctorInfo, custAttrData);
298
299                 // Null arguments again
300                 try {
301                         cb.SetCustomAttribute (null, new byte[2]);
302                         Fail ();
303                 } catch (ArgumentNullException) {
304                 }
305
306                 try {
307                         cb.SetCustomAttribute (ctorInfo, null);
308                         Fail ();
309                 } catch (ArgumentNullException) {
310                 }
311         }
312
313         [Test]
314         public void GetCustomAttributes () {
315                 TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);
316                 ConstructorBuilder cb = tb.DefineConstructor (
317                          MethodAttributes.Public, 0, 
318                         new Type [1] {typeof(int)});
319                 cb.GetILGenerator ().Emit (OpCodes.Ret);
320
321                 Type attrType = typeof (ObsoleteAttribute);
322                 ConstructorInfo ctorInfo =
323                         attrType.GetConstructor (new Type [] { typeof (String) });
324
325                 cb.SetCustomAttribute (new CustomAttributeBuilder (ctorInfo, new object [] { "FOO" }));
326
327                 Type t = tb.CreateType ();
328
329                 // Try the created type
330                 {
331                         ConstructorInfo ci = t.GetConstructors () [0];
332                         object[] attrs = ci.GetCustomAttributes (true);
333
334                         AssertEquals (1, attrs.Length);
335                         Assert (attrs [0] is ObsoleteAttribute);
336                         AssertEquals ("FOO", ((ObsoleteAttribute)attrs [0]).Message);
337                 }
338
339                 // Try the type builder
340                 {
341                         ConstructorInfo ci = tb.GetConstructors () [0];
342                         object[] attrs = ci.GetCustomAttributes (true);
343
344                         AssertEquals (1, attrs.Length);
345                         Assert (attrs [0] is ObsoleteAttribute);
346                         AssertEquals ("FOO", ((ObsoleteAttribute)attrs [0]).Message);
347                 }
348
349         }
350
351         // Same as in MethodBuilderTest
352         [Test]
353         [ExpectedException (typeof (InvalidOperationException))]
354         public void TestAddDeclarativeSecurityAlreadyCreated () {
355                 ConstructorBuilder cb = genClass.DefineConstructor (
356                          MethodAttributes.Public, 0, new Type [0]);
357                 ILGenerator ilgen = cb.GetILGenerator ();
358                 ilgen.Emit (OpCodes.Ret);
359                 genClass.CreateType ();
360
361                 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
362                 cb.AddDeclarativeSecurity (SecurityAction.Demand, set);
363         }
364
365         [Test]
366         [ExpectedException (typeof (ArgumentNullException))]
367         public void TestAddDeclarativeSecurityNullPermissionSet () {
368                 ConstructorBuilder cb = genClass.DefineConstructor (
369                          MethodAttributes.Public, 0, new Type [0]);
370                 cb.AddDeclarativeSecurity (SecurityAction.Demand, null);
371         }
372
373         [Test]
374         public void TestAddDeclarativeSecurityInvalidAction () {
375                 ConstructorBuilder cb = genClass.DefineConstructor (
376                          MethodAttributes.Public, 0, new Type [0]);
377
378                 SecurityAction[] actions = new SecurityAction [] { 
379                         SecurityAction.RequestMinimum,
380                         SecurityAction.RequestOptional,
381                         SecurityAction.RequestRefuse };
382                 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
383
384                 foreach (SecurityAction action in actions) {
385                         try {
386                                 cb.AddDeclarativeSecurity (action, set);
387                                 Fail ();
388                         }
389                         catch (ArgumentException) {
390                         }
391                 }
392         }
393
394         [Test]
395         [ExpectedException (typeof (InvalidOperationException))]
396         public void TestAddDeclarativeSecurityDuplicateAction () {
397                 ConstructorBuilder cb = genClass.DefineConstructor (
398                          MethodAttributes.Public, 0, new Type [0]);
399                 PermissionSet set = new PermissionSet (PermissionState.Unrestricted);
400                 cb.AddDeclarativeSecurity (SecurityAction.Demand, set);
401                 cb.AddDeclarativeSecurity (SecurityAction.Demand, set);
402         }
403 }
404 }