Merge pull request #5288 from lambdageek/bug-58454
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / GenericTypeParameterBuilderTest.cs
1 //
2 // GenericTypeParameterBuilderTest.cs - NUnit Test Cases for GenericTypeParameterBuilder
3 //
4 // Rodrigo Kumpera <rkumpera@novell.com>
5 //
6 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
7 //
8
9 using System;
10 using System.Collections;
11 using System.Threading;
12 using System.Reflection;
13 using System.Reflection.Emit;
14 using System.IO;
15 using System.Security;
16 using System.Security.Permissions;
17 using System.Runtime.InteropServices;
18 using NUnit.Framework;
19 using System.Runtime.CompilerServices;
20
21 using System.Collections.Generic;
22
23 namespace MonoTests.System.Reflection.Emit
24 {
25         [TestFixture]
26         public class GenericTypeParameterBuilderTest
27         {
28                 AssemblyBuilder assembly;
29                 ModuleBuilder module;
30                 static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest";
31
32                 [SetUp]
33                 protected void SetUp ()
34                 {
35                         SetUp (AssemblyBuilderAccess.RunAndSave);
36                 }
37
38                 protected void SetUp (AssemblyBuilderAccess mode)
39                 {
40                         AssemblyName assemblyName = new AssemblyName ();
41                         assemblyName.Name = ASSEMBLY_NAME;
42
43                         assembly =
44                                 Thread.GetDomain ().DefineDynamicAssembly (
45                                         assemblyName, mode, Path.GetTempPath ());
46
47                         module = assembly.DefineDynamicModule ("module1");
48                 }
49
50                 [Test]
51                 public void PropertiesValue ()
52                 {
53                         TypeBuilder tb = module.DefineType ("ns.type", TypeAttributes.Public);
54                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
55
56                         Assert.AreEqual (assembly, gparam.Assembly, "#1");
57                         Assert.AreEqual (null, gparam.AssemblyQualifiedName, "#2");
58                         Assert.AreEqual (null, gparam.BaseType, "#3");
59                         Assert.AreEqual (null, gparam.FullName, "#4");
60                         Assert.AreEqual (module, gparam.Module, "#5");
61                         Assert.AreEqual (null, gparam.Namespace, "#6");
62                         Assert.AreEqual (gparam, gparam.UnderlyingSystemType, "#7");
63                         Assert.AreEqual ("B", gparam.Name, "#8");
64
65                         try {
66                                 object x = gparam.GUID;
67                                 Assert.Fail ("#9");
68                         } catch (NotSupportedException) {}
69
70                         try {
71                                 object x = gparam.TypeHandle;
72                                 Assert.Fail ("#10");
73                         } catch (NotSupportedException) {}
74
75                         try {
76                                 object x = gparam.StructLayoutAttribute;
77                                 Assert.Fail ("#11");
78                         } catch (NotSupportedException) {}
79
80                         Assert.AreEqual (TypeAttributes.Public, gparam.Attributes, "#12");
81                         Assert.IsFalse (gparam.HasElementType, "#13");
82                         Assert.IsFalse (gparam.IsArray, "#14");
83                         Assert.IsFalse (gparam.IsByRef, "#15");
84                         Assert.IsFalse (gparam.IsCOMObject, "#16");
85                         Assert.IsFalse (gparam.IsPointer, "#17");
86                         Assert.IsFalse (gparam.IsPrimitive, "#18");
87
88                 }       
89
90                 [Test]
91                 public void Methods ()
92                 {
93                         TypeBuilder tb = module.DefineType ("ns.type", TypeAttributes.Public);
94                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
95
96                         try {
97                                 gparam.GetInterface ("foo", true);
98                                 Assert.Fail ("#1");
99                         } catch (NotSupportedException) {
100
101                         }
102         
103                         try {
104                                 gparam.GetInterfaces ();
105                                 Assert.Fail ("#2");
106                         } catch (NotSupportedException) {
107
108                         }
109         
110                         try {
111                                 gparam.GetElementType ();
112                                 Assert.Fail ("#3");
113                         } catch (NotSupportedException) {
114
115                         }
116         
117                         try {
118                                 gparam.GetEvent ("foo", BindingFlags.Public);
119                                 Assert.Fail ("#4");
120                         } catch (NotSupportedException) {
121
122                         }
123         
124                         try {
125                                 gparam.GetEvents (BindingFlags.Public);
126                                 Assert.Fail ("#5");
127                         } catch (NotSupportedException) {
128
129                         }
130         
131                         try {
132                                 gparam.GetField ("foo", BindingFlags.Public);
133                                 Assert.Fail ("#6");
134                         } catch (NotSupportedException) {
135
136                         }
137         
138                         try {
139                                 gparam.GetFields (BindingFlags.Public);
140                                 Assert.Fail ("#7");
141                         } catch (NotSupportedException) {
142
143                         }
144         
145                         try {
146                                 gparam.GetMembers (BindingFlags.Public);
147                                 Assert.Fail ("#8");
148                         } catch (NotSupportedException) {
149
150                         }
151         
152                         try {
153                                 gparam.GetMethod ("Sort");
154                                 Assert.Fail ("#9");
155                         } catch (NotSupportedException) {
156
157                         }
158         
159                         try {
160                                 gparam.GetMethods (BindingFlags.Public);
161                                 Assert.Fail ("#9");
162                         } catch (NotSupportedException) {
163
164                         }
165         
166                         try {
167                                 gparam.GetNestedType ("bla", BindingFlags.Public);
168                                 Assert.Fail ("#10");
169                         } catch (NotSupportedException) {
170
171                         }
172         
173                         try {
174                                 gparam.GetNestedTypes (BindingFlags.Public);
175                                 Assert.Fail ("#11");
176                         } catch (NotSupportedException) {
177
178                         }
179         
180                         try {
181                                 gparam.GetProperties (BindingFlags.Public);
182                                 Assert.Fail ("#12");
183                         } catch (NotSupportedException) {
184
185                         }       
186         
187                         try {
188                                 gparam.GetProperty ("Length");
189                                 Assert.Fail ("#13");
190                         } catch (NotSupportedException) {
191
192                         }
193         
194                         try {
195                                 gparam.GetConstructor (new Type[] { typeof (int) });
196                                 Assert.Fail ("#14");
197                         } catch (NotSupportedException) {
198
199                         }
200         
201                         try {
202                                 gparam.GetArrayRank ();
203                                 Assert.Fail ("#15");
204                         } catch (NotSupportedException) {
205
206                         }
207
208                         try {
209                                 gparam.GetConstructors (BindingFlags.Public);
210                                 Assert.Fail ("#16");
211                         } catch (NotSupportedException) {}
212
213                         try {
214                                 gparam.InvokeMember ("GetLength", BindingFlags.Public, null, null, null);
215                                 Assert.Fail ("#17");
216                         } catch (NotSupportedException) {}
217
218                         try {
219                                 gparam.IsSubclassOf (gparam);
220                                 Assert.Fail ("#18");
221                         } catch (NotSupportedException) {}
222
223                         try {
224                                 gparam.IsAssignableFrom (gparam);
225                                 Assert.Fail ("#19");
226                         } catch (NotSupportedException) {}
227
228                         try {
229                                 gparam.GetInterfaceMap (typeof (IEnumerable));
230                                 Assert.Fail ("#20");
231                         } catch (NotSupportedException) {}
232
233                         try {
234                                 gparam.IsInstanceOfType (new object());
235                                 Assert.Fail ("#21");
236                         } catch (NotSupportedException) {}
237                 }
238
239                 [Test]
240                 public void MakeGenericType ()
241                 {
242                         TypeBuilder tb = module.DefineType ("dd.test", TypeAttributes.Public);
243                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
244                         try {
245                                 gparam.MakeGenericType (new Type[] { typeof (string) });
246                                 Assert.Fail ("#1");
247                         } catch (InvalidOperationException) {}
248                 }
249
250
251                 [Test]
252                 public void GenericParameterAttributes ()
253                 {
254                         TypeBuilder tb = module.DefineType ("dd.test", TypeAttributes.Public);
255                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
256                         try {
257                                 object attr = gparam.GenericParameterAttributes;
258                                 Assert.Fail ("#1");
259                         } catch (NotSupportedException) {}
260                 }
261
262                 [Test]
263                 public void MakeArrayType ()
264                 {
265                         TypeBuilder tb = module.DefineType ("dd.test", TypeAttributes.Public);
266                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
267                         Type res = gparam.MakeArrayType ();
268                         Assert.IsNotNull (res, "#1");
269                         Assert.IsTrue (res.IsArray, "#2");
270
271                         res = gparam.MakeArrayType (2);
272                         Assert.IsNotNull (res, "#3");
273                         Assert.IsTrue (res.IsArray, "#4");
274                 }
275
276                 [Test]
277                 public void MakeByRefType ()
278                 {
279                         TypeBuilder tb = module.DefineType ("dd.test", TypeAttributes.Public);
280                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
281                         Type res = gparam.MakeByRefType ();
282
283                         Assert.IsNotNull (res, "#1");
284                         Assert.IsTrue (res.IsByRef, "#2");
285                 }
286
287                 [Test]
288                 public void MakePointerType ()
289                 {
290                         TypeBuilder tb = module.DefineType ("dd.test", TypeAttributes.Public);
291                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
292                         Type res = gparam.MakePointerType ();
293
294                         Assert.IsNotNull (res, "#1");
295                         Assert.IsTrue (res.IsPointer, "#2");
296                 }
297
298                 [Test]
299                 public void SetBaseTypeConstraintWithNull ()
300                 {
301                         TypeBuilder tb = module.DefineType ("dd.test", TypeAttributes.Public);
302                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
303
304                         Assert.IsNull (gparam.BaseType, "#1");
305                         gparam.SetBaseTypeConstraint (null);
306                         Assert.AreEqual (typeof (object), gparam.BaseType, "#2");
307                 }
308
309                 [Test]
310                 public void GenericTypeMembers ()
311                 {
312                         TypeBuilder tb = module.DefineType ("dd.test", TypeAttributes.Public);
313                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
314
315                         try {
316                                 gparam.GetGenericArguments ();
317                                 Assert.Fail ("#1");
318                         } catch (InvalidOperationException) {}
319
320                         try {
321                                 gparam.GetGenericParameterConstraints ();
322                                 Assert.Fail ("#2");
323                         } catch (InvalidOperationException) {}
324
325                         try {
326                                 gparam.GetGenericTypeDefinition ();
327                                 Assert.Fail ("#3");
328                         } catch (InvalidOperationException) {}
329                 
330                         Assert.IsTrue (gparam.ContainsGenericParameters, "#4");
331                         try {
332                                 var x = gparam.GenericParameterAttributes;
333                                 Assert.Fail ("#5");
334                         } catch (NotSupportedException) {}
335
336                         Assert.AreEqual (1, gparam.GenericParameterPosition, "#6");
337
338                         Assert.IsTrue (gparam.ContainsGenericParameters, "#7");
339
340                         Assert.IsTrue (gparam.IsGenericParameter, "#8");
341                         Assert.IsFalse (gparam.IsGenericType, "#9");
342                         Assert.IsFalse (gparam.IsGenericTypeDefinition, "#10");
343                 }
344
345                 [Test]
346                 // CompilerContext no longer supported
347                 [Category ("NotWorking")]
348                 public void GetAttributeFlagsImpl ()
349                 {
350                         SetUp (AssemblyBuilderAccess.RunAndSave  | (AssemblyBuilderAccess)0x800);
351                         TypeBuilder tb = module.DefineType ("ns.type", TypeAttributes.Public);
352                         var gparam = tb.DefineGenericParameters ("A", "B")[1];
353
354                         Assert.AreEqual (TypeAttributes.Public, gparam.Attributes, "#1");
355                 }
356
357                 [Test]
358                 public void ActionConstructorInfoTest ()
359                 {
360                         // Regression test for https://bugzilla.xamarin.com/show_bug.cgi?id=58454
361                         //
362                         // Need to check that GenericTypeParameterBuilderTest:InternalResolve() passes the declaring type to GetMethodFromHandle()
363                         //
364                         /* Want to generate:
365
366                            public class Store<TState> {
367                            public Action<TSelection> Subscribe<TSelection> (TState state) {
368                                 return new Action<TSelection> (Foo<TSelection>);
369                            }
370                            public static void Foo<X> (X x) { }
371                            }
372
373                            ...  and then: new Store<string>().Subscribe<int>("x");
374                         */
375
376                         SetUp (AssemblyBuilderAccess.Run);
377
378                         var tb = module.DefineType ("Store");
379                         var tparsStore = tb.DefineGenericParameters ("TState");
380
381                         tb.DefineDefaultConstructor (MethodAttributes.Public);
382
383                         var methFoo = tb.DefineMethod ("Foo", MethodAttributes.Public | MethodAttributes.Static);
384                         var tparsFoo = methFoo.DefineGenericParameters ("X");
385                         methFoo.SetReturnType (typeof(void));
386                         methFoo.SetParameters (tparsFoo[0]);
387                         methFoo.GetILGenerator().Emit (OpCodes.Ret);
388
389                         var methSub = tb.DefineMethod ("Subscribe", MethodAttributes.Public | MethodAttributes.Static);
390                         var tparsSub = methSub.DefineGenericParameters ("TSelection");
391                         var actOfSel = typeof(Action<>).MakeGenericType (tparsSub[0]); // Action<TSelection>
392                         methSub.SetReturnType  (actOfSel);
393                         methSub.SetParameters (tparsStore[0]); // TState
394                         var ilg = methSub.GetILGenerator ();
395                         ilg.Emit (OpCodes.Ldnull); // instance == null
396                         ilg.Emit (OpCodes.Ldftn, methFoo.MakeGenericMethod (tparsSub[0])); // ldftn void class Store`1<!TState>::Foo<!!0> (!!0)
397                         var aaa = TypeBuilder.GetConstructor (actOfSel, typeof(Action<>).GetConstructors()[0]);
398                         ilg.Emit (OpCodes.Newobj, aaa); // new Action<TSelection> (Foo<TSelection>);
399                         ilg.Emit (OpCodes.Ret);
400
401                         var tgen = tb.CreateType (); // TState`1
402
403                         var t = tgen.MakeGenericType(typeof(string));
404                         var x = t.GetConstructor(Type.EmptyTypes).Invoke (null); // x = new Store<string> ()
405                         var mgen = t.GetMethod("Subscribe");
406                         var m = mgen.MakeGenericMethod (typeof (int)); // Action<int> Store<string>.Subscribe<int> (string)
407                         var y = m.Invoke (x, new object[] {"hello"}); // x.Subscribte<int> ("hello")
408                         Assert.IsNotNull (y);
409                 }
410
411         }
412 }