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]
SetUp()33 		protected void SetUp ()
34 		{
35 			SetUp (AssemblyBuilderAccess.RunAndSave);
36 		}
37 
SetUp(AssemblyBuilderAccess mode)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]
PropertiesValue()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]
Methods()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]
MakeGenericType()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]
GenericParameterAttributes()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]
MakeArrayType()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]
MakeByRefType()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]
MakePointerType()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]
SetBaseTypeConstraintWithNull()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]
GenericTypeMembers()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")]
GetAttributeFlagsImpl()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]
ActionConstructorInfoTest()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 }
413