MonoGenericClassTest.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. //
  2. // MonoGenericClassTest.cs - NUnit Test Cases for MonoGenericClassTest
  3. //
  4. // Rodrigo Kumpera <[email protected]>
  5. //
  6. // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
  7. // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
  8. //
  9. #if !MONOTOUCH && !FULL_AOT_RUNTIME
  10. using System;
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using System.Collections.ObjectModel;
  14. using System.Threading;
  15. using System.Reflection;
  16. using System.Reflection.Emit;
  17. using System.IO;
  18. using System.Security;
  19. using System.Security.Permissions;
  20. using System.Runtime.InteropServices;
  21. using NUnit.Framework;
  22. using System.Runtime.CompilerServices;
  23. namespace MonoTests.System.Reflection.Emit
  24. {
  25. [TestFixture]
  26. public class MonoGenericClassTest
  27. {
  28. AssemblyBuilder assembly;
  29. ModuleBuilder module;
  30. int typeCount;
  31. static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.MonoGenericClassTest";
  32. string MakeName ()
  33. {
  34. return "internal__type"+ typeCount++;
  35. }
  36. [SetUp]
  37. public void SetUp ()
  38. {
  39. SetUp (AssemblyBuilderAccess.RunAndSave);
  40. }
  41. void SetUp (AssemblyBuilderAccess access)
  42. {
  43. AssemblyName assemblyName = new AssemblyName ();
  44. assemblyName.Name = ASSEMBLY_NAME;
  45. assembly =
  46. Thread.GetDomain ().DefineDynamicAssembly (
  47. assemblyName, access, Path.GetTempPath ());
  48. module = assembly.DefineDynamicModule ("module1");
  49. typeCount = 0;
  50. }
  51. [Test]
  52. public void TestNameMethods ()
  53. {
  54. TypeBuilder tb = module.DefineType ("foo.type");
  55. tb.DefineGenericParameters ("T", "K");
  56. Type inst = tb.MakeGenericType (typeof (double), typeof (string));
  57. Assert.AreEqual ("type", inst.Name, "#1");
  58. Assert.AreEqual ("foo", inst.Namespace, "#2");
  59. #if !MOBILE
  60. Assert.AreEqual ("foo.type[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", inst.FullName, "#3");
  61. Assert.AreEqual ("foo.type[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], MonoTests.System.Reflection.Emit.MonoGenericClassTest, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", inst.AssemblyQualifiedName, "#4");
  62. #elif MOBILE || MOBILE
  63. Assert.AreEqual ("foo.type[[System.Double, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]", inst.FullName, "#3");
  64. Assert.AreEqual ("foo.type[[System.Double, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], MonoTests.System.Reflection.Emit.MonoGenericClassTest, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", inst.AssemblyQualifiedName, "#4");
  65. Assert.AreEqual ("foo.type[System.Double,System.String]", inst.ToString (), "#5");
  66. #endif
  67. }
  68. static void CheckInst (string prefix, Type inst, int a, int b)
  69. {
  70. var resA = inst.GetMethods (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
  71. var resB = inst.GetMethods (BindingFlags.Public | BindingFlags.Instance);
  72. Assert.AreEqual (a, resA.Length, prefix + 1);
  73. Assert.AreEqual (b, resB.Length, prefix + 2);
  74. }
  75. [Test]
  76. public void MethodsThatRaiseNotSupported ()
  77. {
  78. var tb = module.DefineType ("foo.type");
  79. tb.DefineGenericParameters ("T");
  80. var ginst = tb.MakeGenericType (typeof (double));
  81. try {
  82. ginst.GetElementType ();
  83. Assert.Fail ("#1");
  84. } catch (NotSupportedException) { }
  85. try {
  86. ginst.GetInterface ("foo", true);
  87. Assert.Fail ("#2");
  88. } catch (NotSupportedException) { }
  89. try {
  90. ginst.GetEvent ("foo", BindingFlags.Public | BindingFlags.Instance);
  91. Assert.Fail ("#3");
  92. } catch (NotSupportedException) { }
  93. try {
  94. ginst.GetField ("foo", BindingFlags.Public | BindingFlags.Instance);
  95. Assert.Fail ("#4");
  96. } catch (NotSupportedException) { }
  97. try {
  98. ginst.GetMembers (BindingFlags.Public | BindingFlags.Instance);
  99. Assert.Fail ("#5");
  100. } catch (NotSupportedException) { }
  101. try {
  102. ginst.GetMethod ("Foo");
  103. Assert.Fail ("#6");
  104. } catch (NotSupportedException) { }
  105. try {
  106. ginst.GetNestedType ("foo", BindingFlags.Public | BindingFlags.Instance);
  107. Assert.Fail ("#7");
  108. } catch (NotSupportedException) { }
  109. try {
  110. ginst.GetProperty ("foo");
  111. Assert.Fail ("#8");
  112. } catch (NotSupportedException) { }
  113. try {
  114. var x = ginst.TypeInitializer;
  115. Assert.Fail ("#9");
  116. } catch (NotSupportedException) { }
  117. try {
  118. var x = ginst.InvokeMember ("foo", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, null, null);
  119. Assert.Fail ("#10");
  120. } catch (NotSupportedException) { }
  121. try {
  122. ginst.IsDefined (typeof (int), true);
  123. Assert.Fail ("#11");
  124. } catch (NotSupportedException) { }
  125. try {
  126. ginst.GetCustomAttributes (true);
  127. Assert.Fail ("#12");
  128. } catch (NotSupportedException) { }
  129. try {
  130. ginst.GetCustomAttributes (typeof (int), true);
  131. Assert.Fail ("#13");
  132. } catch (NotSupportedException) { }
  133. try {
  134. ginst.IsAssignableFrom (ginst);
  135. Assert.Fail ("#14");
  136. } catch (NotSupportedException) { }
  137. try {
  138. ginst.GetNestedTypes (BindingFlags.Public);
  139. Assert.Fail ("#14");
  140. } catch (NotSupportedException) { }
  141. }
  142. [Test]
  143. public void ClassMustNotBeRegisteredAfterTypeBuilderIsFinished ()
  144. {
  145. TypeBuilder tb = module.DefineType ("foo.type");
  146. tb.DefineGenericParameters ("T");
  147. var c = tb.CreateType ();
  148. var sreInst = tb.MakeGenericType (typeof (int));
  149. var rtInst = c.MakeGenericType (typeof (int));
  150. Assert.AreNotSame (sreInst, rtInst, "#1");
  151. /*This must not throw*/
  152. rtInst.IsDefined (typeof (int), true);
  153. }
  154. public class Bar<T> {
  155. public class Foo<U> {}
  156. }
  157. [Test]
  158. public void DeclaringTypeMustReturnNonInflatedType ()
  159. {
  160. var ut = new TypeDelegator (typeof (int));
  161. var ut2 = typeof(Bar<>.Foo<>);
  162. var t = ut2.MakeGenericType (ut, ut);
  163. Assert.AreSame (typeof (Bar<>), t.DeclaringType, "#1");
  164. }
  165. public class Base<T> {}
  166. public class SubClass<K> : Base<K> {}
  167. [Test]
  168. public void BaseTypeMustReturnNonInflatedType ()
  169. {
  170. var ut = new TypeDelegator (typeof (int));
  171. var ut2 = typeof(SubClass<>);
  172. var t = ut2.MakeGenericType (ut);
  173. //This is Base<K> where K is SubClass::K
  174. var expected = typeof (Base<>).MakeGenericType (typeof (SubClass<>).GetGenericArguments ()[0]);
  175. Assert.AreSame (expected, t.BaseType, "#1");
  176. }
  177. [Test]
  178. public void GenericClassFromStaleTypeBuilderDoesNotClassInit ()
  179. {
  180. // interface JJJ<T> {
  181. // abstract void W (x : T)
  182. // }
  183. MethodInfo winfo = null;
  184. TypeBuilder ib = null;
  185. Type ic = null;
  186. Type icreated = null;
  187. {
  188. ib = module.DefineType ("Foo.JJJ`1",
  189. TypeAttributes.Public
  190. | TypeAttributes.Interface
  191. | TypeAttributes.Abstract);
  192. String[] gens = { "T" };
  193. GenericTypeParameterBuilder[] gbs = ib.DefineGenericParameters (gens);
  194. var gb = gbs[0];
  195. winfo = ib.DefineMethod ("W",
  196. MethodAttributes.Public |
  197. MethodAttributes.Abstract |
  198. MethodAttributes.Virtual,
  199. CallingConventions.HasThis,
  200. typeof(void),
  201. new Type[] { gb });
  202. icreated = ib.CreateType();
  203. }
  204. // class SSS : JJJ<char> {
  205. // bool wasCalled;
  206. // void JJJ.W (x : T) { wasCalled = true; return; }
  207. // }
  208. TypeBuilder tb = null;
  209. MethodBuilder mb = null;
  210. {
  211. tb = module.DefineType ("Foo.SSS",
  212. TypeAttributes.Public,
  213. null,
  214. new Type[]{ icreated.MakeGenericType(typeof(char)) });
  215. var wasCalledField = tb.DefineField ("wasCalled",
  216. typeof(bool),
  217. FieldAttributes.Public);
  218. mb = tb.DefineMethod ("W_impl",
  219. MethodAttributes.Public | MethodAttributes.Virtual,
  220. CallingConventions.HasThis,
  221. typeof (void),
  222. new Type[] { typeof (char) });
  223. {
  224. var il = mb.GetILGenerator ();
  225. il.Emit (OpCodes.Ldarg_0); // this
  226. il.Emit (OpCodes.Ldc_I4_1);
  227. il.Emit (OpCodes.Stfld, wasCalledField); // this.wasCalled = true
  228. il.Emit (OpCodes.Ret);
  229. }
  230. }
  231. ic = ib.MakeGenericType(typeof (char)); // this is a MonoGenericMethod
  232. var mintf = TypeBuilder.GetMethod(ic, winfo);
  233. // the next line causes mono_class_init() to
  234. // be called on JJJ<char> when we try to setup
  235. // the vtable for SSS
  236. tb.DefineMethodOverride(mb, mintf);
  237. var result = tb.CreateType();
  238. // o = new SSS()
  239. object o = Activator.CreateInstance(result);
  240. Assert.IsNotNull(o, "#1");
  241. // ((JJJ<char>)o).W('a');
  242. var m = icreated.MakeGenericType(typeof(char)).GetMethod("W", BindingFlags.Public | BindingFlags.Instance);
  243. Assert.IsNotNull(m, "#2");
  244. m.Invoke(o, new object[] {'a'});
  245. var f = result.GetField("wasCalled", BindingFlags.Public | BindingFlags.Instance);
  246. Assert.IsNotNull(f, "#3");
  247. var wasCalledVal = f.GetValue(o);
  248. Assert.IsNotNull(wasCalledVal, "#4");
  249. Assert.AreEqual (wasCalledVal.GetType(), typeof(Boolean), "#5");
  250. Assert.AreEqual (wasCalledVal, true, "#6");
  251. }
  252. }
  253. }
  254. #endif