1 // 2 // EnumBuiderTest - NUnit Test Cases for the EnumBuider class 3 // 4 // Keerti Narayan (keertiln@rediffmail.com) 5 // Gert Driesen (drieseng@users.sourceforge.net) 6 // 7 // (C) Ximian, Inc. http://www.ximian.com 8 // 9 // 10 11 using System; 12 using System.IO; 13 using System.Reflection; 14 using System.Reflection.Emit; 15 using System.Collections; 16 using System.Threading; 17 18 using NUnit.Framework; 19 20 namespace MonoTests.System.Reflection.Emit 21 { 22 [TestFixture] 23 public class EnumBuilderTest 24 { 25 private static string _assemblyName = "MonoTests.System.Reflection.Emit.EnumBuilder"; 26 private static string _moduleName = "EmittedModule"; 27 private static string _enumNamespace = "MyNameSpace"; 28 private static string _enumName = "MyEnum"; 29 private static Type _enumType = typeof (Int32); 30 private static string _fieldName = "MyField"; 31 private static object _fieldValue = 1; 32 33 [Test] TestEnumBuilder()34 public void TestEnumBuilder () 35 { 36 EnumBuilder enumBuilder = GenerateEnum (); 37 VerifyType (enumBuilder); 38 39 Assert.IsNotNull (enumBuilder.TypeToken, "#1"); 40 Assert.IsNotNull (enumBuilder.UnderlyingField, "#2"); 41 Assert.IsNull (enumBuilder.DeclaringType, "#3"); 42 Assert.IsNull (enumBuilder.ReflectedType, "#4"); 43 Assert.AreEqual (_enumType, enumBuilder.UnderlyingSystemType, "#5"); 44 Assert.IsFalse (enumBuilder.IsSerializable); 45 } 46 47 [Test] 48 [Category ("NotWorking")] TestHasElementTypeEnumBuilderIncomplete()49 public void TestHasElementTypeEnumBuilderIncomplete () 50 { 51 EnumBuilder enumBuilder = GenerateEnum (); 52 bool hasElementType = enumBuilder.HasElementType; 53 Assert.IsFalse (hasElementType); 54 } 55 56 [Test] TestHasElementTypeEnumBuilderComplete()57 public void TestHasElementTypeEnumBuilderComplete () 58 { 59 EnumBuilder enumBuilder = GenerateEnum (); 60 enumBuilder.CreateType (); 61 bool hasElementType = enumBuilder.HasElementType; 62 Assert.IsFalse (hasElementType); 63 } 64 65 [Test] 66 [ExpectedException (typeof (InvalidOperationException))] TestDefineLiteralTypeComplete()67 public void TestDefineLiteralTypeComplete () 68 { 69 EnumBuilder enumBuilder = GenerateEnum (); 70 Type enumType = enumBuilder.CreateType (); 71 // you should not be able to define literal after type 72 // has been created 73 enumBuilder.DefineLiteral (_fieldName, _fieldValue); 74 } 75 76 [Test] TestDefineLiteralTypeIncomplete()77 public void TestDefineLiteralTypeIncomplete () 78 { 79 EnumBuilder enumBuilder = GenerateEnum (); 80 FieldBuilder fieldBuilder = enumBuilder.DefineLiteral (_fieldName, _fieldValue); 81 Type enumType = enumBuilder.CreateType (); 82 83 Assert.IsTrue (fieldBuilder.IsPublic, "#1"); 84 Assert.IsTrue (fieldBuilder.IsStatic, "#2"); 85 Assert.IsTrue (fieldBuilder.IsLiteral, "#3"); 86 Assert.AreEqual (_fieldName, fieldBuilder.Name, "#4"); 87 Assert.IsFalse (enumType == fieldBuilder.DeclaringType, "#5"); 88 Assert.IsFalse (enumBuilder == fieldBuilder.DeclaringType, "#6"); 89 Assert.AreEqual (enumType.FullName, fieldBuilder.DeclaringType.FullName, "#7"); 90 Assert.IsFalse (enumType == fieldBuilder.FieldType, "#8"); 91 Assert.AreEqual (enumBuilder, fieldBuilder.FieldType, "#9"); 92 } 93 94 [Test] TestEnumType()95 public void TestEnumType () 96 { 97 AssemblyBuilder assemblyBuilder = GenerateAssembly (); 98 99 ModuleBuilder modBuilder = GenerateModule (assemblyBuilder); 100 EnumBuilder enumBuilder = GenerateEnum (modBuilder); 101 enumBuilder.CreateType (); 102 103 Type enumType = assemblyBuilder.GetType (_enumNamespace + "." + _enumName, true); 104 105 VerifyType (enumType); 106 } 107 108 [Test] 109 [ExpectedException (typeof (NotSupportedException))] TestEnumBuilderGUIDIncomplete()110 public void TestEnumBuilderGUIDIncomplete () 111 { 112 EnumBuilder enumBuilder = GenerateEnum (); 113 Guid guid = enumBuilder.GUID; 114 } 115 116 [Test] 117 [Category ("NotWorking")] // Bug:71299 TestEnumBuilderGUIDComplete()118 public void TestEnumBuilderGUIDComplete () 119 { 120 EnumBuilder enumBuilder = GenerateEnum (); 121 enumBuilder.CreateType (); 122 Assert.IsTrue (enumBuilder.GUID != Guid.Empty); 123 } 124 125 [Test] TestEnumTypeGUID()126 public void TestEnumTypeGUID () 127 { 128 AssemblyBuilder assemblyBuilder = GenerateAssembly (); 129 ModuleBuilder modBuilder = GenerateModule (assemblyBuilder); 130 EnumBuilder enumBuilder = GenerateEnum (modBuilder); 131 enumBuilder.CreateType (); 132 133 Type enumType = assemblyBuilder.GetType (_enumNamespace + "." + _enumName, true); 134 135 // Tested in above test: Assert (enumType.GUID != Guid.Empty); 136 Assert.IsNull (enumType.DeclaringType); 137 } 138 139 [Test] TestFieldProperties()140 public void TestFieldProperties () 141 { 142 AssemblyBuilder assemblyBuilder = GenerateAssembly (); 143 ModuleBuilder modBuilder = GenerateModule (assemblyBuilder); 144 EnumBuilder enumBuilder = GenerateEnum (modBuilder); 145 FieldBuilder fieldBuilder = GenerateField (enumBuilder); 146 enumBuilder.CreateType (); 147 148 Type enumType = assemblyBuilder.GetType (_enumNamespace + "." + _enumName, true); 149 FieldInfo fi = enumType.GetField (_fieldName); 150 Object o = fi.GetValue (enumType); 151 152 Assert.IsTrue (fi.IsLiteral, "#1"); 153 Assert.IsTrue (fi.IsPublic, "#2"); 154 Assert.IsTrue (fi.IsStatic, "#3"); 155 Assert.AreEqual (enumBuilder, fieldBuilder.FieldType, "#4"); 156 Assert.IsFalse (enumType == fieldBuilder.FieldType, "#5"); 157 Assert.AreEqual (enumType.FullName, fieldBuilder.FieldType.FullName, "#6"); 158 Assert.IsFalse (_enumType == fieldBuilder.FieldType, "#7"); 159 160 object fieldValue = fi.GetValue (enumType); 161 Assert.IsFalse (_fieldValue == fieldValue, "#8"); 162 Assert.IsTrue (fieldValue.GetType ().IsEnum, "#9"); 163 Assert.AreEqual (enumType, fieldValue.GetType (), "#10"); 164 Assert.AreEqual (_fieldValue, (int) fieldValue, "#11"); 165 } 166 167 [Test] TestFindInterfaces()168 public void TestFindInterfaces () 169 { 170 EnumBuilder enumBuilder = GenerateEnum (); 171 172 Type [] interfaces = enumBuilder.FindInterfaces ( 173 new TypeFilter (MyInterfaceFilter), 174 "System.Collections.IEnumerable"); 175 Assert.AreEqual (0, interfaces.Length); 176 } 177 178 [Test] 179 [ExpectedException (typeof (NotSupportedException))] TestFindMembersIncomplete()180 public void TestFindMembersIncomplete () 181 { 182 EnumBuilder enumBuilder = GenerateEnum (); 183 GenerateField (enumBuilder); 184 185 MemberInfo [] members = enumBuilder.FindMembers ( 186 MemberTypes.All, BindingFlags.Static | 187 BindingFlags.Public, new MemberFilter (MemberNameFilter), 188 _fieldName); 189 } 190 191 [Test] GetEnumUnderlyingType()192 public void GetEnumUnderlyingType () 193 { 194 var @enum = GenerateEnum (); 195 196 Assert.AreEqual (_enumType, @enum.GetEnumUnderlyingType ()); 197 } 198 199 [Test] TestFindMembersComplete()200 public void TestFindMembersComplete () 201 { 202 EnumBuilder enumBuilder = GenerateEnum (); 203 GenerateField (enumBuilder); 204 enumBuilder.CreateType (); 205 206 MemberInfo [] members = enumBuilder.FindMembers ( 207 MemberTypes.Field, BindingFlags.Static | 208 BindingFlags.Public, new MemberFilter (MemberNameFilter), 209 _fieldName); 210 Assert.AreEqual (1, members.Length, "#1"); 211 212 members = enumBuilder.FindMembers ( 213 MemberTypes.Field, BindingFlags.Static | 214 BindingFlags.Public, new MemberFilter (MemberNameFilter), 215 "doesntmatter"); 216 Assert.AreEqual (0, members.Length, "#2"); 217 } 218 219 [Test] 220 [ExpectedException (typeof (NotSupportedException))] TestGetConstructorIncomplete()221 public void TestGetConstructorIncomplete () 222 { 223 EnumBuilder enumBuilder = GenerateEnum (); 224 enumBuilder.GetConstructor (BindingFlags.Public, null, 225 CallingConventions.Any, Type.EmptyTypes, new ParameterModifier [0]); 226 } 227 228 [Test] TestGetConstructorComplete()229 public void TestGetConstructorComplete () 230 { 231 EnumBuilder enumBuilder = GenerateEnum (); 232 enumBuilder.CreateType (); 233 ConstructorInfo ctor = enumBuilder.GetConstructor ( 234 BindingFlags.Public, null, CallingConventions.Any, 235 Type.EmptyTypes, new ParameterModifier [0]); 236 Assert.IsNull (ctor); 237 } 238 239 [Test] 240 [ExpectedException (typeof (ArgumentNullException))] TestGetConstructorNullTypes()241 public void TestGetConstructorNullTypes () 242 { 243 EnumBuilder enumBuilder = GenerateEnum (); 244 enumBuilder.CreateType (); 245 ConstructorInfo ctor = enumBuilder.GetConstructor ( 246 BindingFlags.Public, null, CallingConventions.Any, 247 null, new ParameterModifier [0]); 248 } 249 250 [Test] 251 [Category ("NotWorking")] 252 [ExpectedException (typeof (ArgumentNullException))] TestGetConstructorNullElementType()253 public void TestGetConstructorNullElementType () 254 { 255 EnumBuilder enumBuilder = GenerateEnum (); 256 enumBuilder.CreateType (); 257 ConstructorInfo ctor = enumBuilder.GetConstructor ( 258 BindingFlags.Public, null, CallingConventions.Any, 259 new Type [] { null }, new ParameterModifier [0]); 260 } 261 262 [Test] 263 [ExpectedException (typeof (NotSupportedException))] 264 [Category ("NotWorking")] TestGetConstructorsIncomplete()265 public void TestGetConstructorsIncomplete () 266 { 267 EnumBuilder enumBuilder = GenerateEnum (); 268 269 ConstructorInfo [] ctors = enumBuilder.GetConstructors ( 270 BindingFlags.Instance | BindingFlags.Public); 271 Assert.AreEqual (0, ctors.Length); 272 } 273 274 [Test] TestGetConstructorsComplete()275 public void TestGetConstructorsComplete () 276 { 277 EnumBuilder enumBuilder = GenerateEnum (); 278 enumBuilder.CreateType (); 279 280 ConstructorInfo [] ctors = enumBuilder.GetConstructors ( 281 BindingFlags.Instance | BindingFlags.Public); 282 Assert.AreEqual (0, ctors.Length); 283 } 284 285 [Test] TestIsValue__SpecialName()286 public void TestIsValue__SpecialName () 287 { 288 EnumBuilder enumBuilder = GenerateEnum (); 289 Type enumType = enumBuilder.CreateType (); 290 FieldInfo value = enumType.GetField ("value__", BindingFlags.Instance | BindingFlags.NonPublic); 291 Assert.AreEqual (FieldAttributes.RTSpecialName, value.Attributes & FieldAttributes.RTSpecialName); 292 } 293 294 [Test] TestCreateTypeIncompleteEnumStaticField()295 public void TestCreateTypeIncompleteEnumStaticField () 296 { 297 ModuleBuilder modBuilder = GenerateModule (); 298 EnumBuilder enumBuilder = GenerateEnum (modBuilder); 299 GenerateField (enumBuilder); 300 301 var tb = modBuilder.DefineType ("T", TypeAttributes.Public); 302 303 tb.DefineDefaultConstructor (MethodAttributes.Public); 304 tb.DefineField ("e", enumBuilder, FieldAttributes.Static | FieldAttributes.Public); 305 306 var t = tb.CreateType (); 307 Assert.IsNotNull (t); 308 bool caught = false; 309 try { 310 object x = Activator.CreateInstance (t); 311 } catch (TypeLoadException exn) { 312 Assert.AreEqual (t.Name, exn.TypeName); 313 caught = true; 314 } 315 if (!caught) 316 Assert.Fail ("Expected CreateInstance of a broken type to throw TLE"); 317 } 318 319 [Test] TestEnumBuilderTokenUsable()320 public void TestEnumBuilderTokenUsable () { 321 // Regression test for https://bugzilla.xamarin.com/show_bug.cgi?id=58361 322 // Create an EnumBuilder and use it in an ILGenerator that consumes its token. 323 var modBuilder = GenerateModule (); 324 EnumBuilder enumBuilder = GenerateEnum (modBuilder); 325 326 var tb = modBuilder.DefineType ("Foo", TypeAttributes.Public); 327 328 var cb = tb.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, 329 Type.EmptyTypes); 330 331 var ilg = cb.GetILGenerator (); 332 333 ilg.Emit (OpCodes.Ldtoken, enumBuilder); 334 ilg.Emit (OpCodes.Pop); 335 ilg.Emit (OpCodes.Ret); 336 337 var t = tb.CreateType (); 338 enumBuilder.CreateType (); 339 340 var ci = t.GetConstructor (Type.EmptyTypes); 341 var x = ci.Invoke (null); 342 Assert.IsNotNull (x); 343 } 344 345 [Test] TestEnumBuilderTokenUsableCrossAssembly()346 public void TestEnumBuilderTokenUsableCrossAssembly () { 347 // Regression test for https://bugzilla.xamarin.com/show_bug.cgi?id=58361 348 // Create an EnumBuilder and use it in an ILGenerator that consumes its token in a different assembly. 349 var modBuilder = GenerateModule (); 350 var modBuilder2 = GenerateModule (); 351 EnumBuilder enumBuilder = GenerateEnum (modBuilder2); 352 353 // N.B. "tb" is in modBuilder but enumBuilder is in modBuilder2 354 var tb = modBuilder.DefineType ("Foo", TypeAttributes.Public); 355 356 var cb = tb.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, 357 Type.EmptyTypes); 358 359 var ilg = cb.GetILGenerator (); 360 361 ilg.Emit (OpCodes.Ldtoken, enumBuilder); 362 ilg.Emit (OpCodes.Pop); 363 ilg.Emit (OpCodes.Ret); 364 365 var t = tb.CreateType (); 366 enumBuilder.CreateType (); 367 368 var ci = t.GetConstructor (Type.EmptyTypes); 369 var x = ci.Invoke (null); 370 Assert.IsNotNull (x); 371 } 372 373 VerifyType(Type type)374 private static void VerifyType (Type type) 375 { 376 Assert.IsNotNull (type.Assembly, "#V1"); 377 Assert.IsNotNull (type.AssemblyQualifiedName, "#V2"); 378 Assert.IsNotNull (type.BaseType, "#V3"); 379 Assert.IsNotNull (type.FullName, "#V4"); 380 Assert.IsNotNull (type.Module, "#V5"); 381 Assert.IsNotNull (type.Name, "#V6"); 382 Assert.IsNotNull (type.Namespace, "#V7"); 383 Assert.IsNotNull (type.UnderlyingSystemType, "#V8"); 384 385 Assert.AreEqual (_enumNamespace, type.Namespace, "#V10"); 386 Assert.AreEqual (_enumName, type.Name, "#V11"); 387 Assert.AreEqual (typeof (Enum), type.BaseType, "#V12"); 388 Assert.AreEqual (MemberTypes.TypeInfo, type.MemberType, "#V13"); 389 Assert.AreEqual (typeof (int), Enum.GetUnderlyingType (type), "#V14"); 390 391 Assert.IsFalse (type.IsArray, "#V15"); 392 Assert.IsFalse (type.IsAutoClass, "#V16"); 393 Assert.IsTrue (type.IsAutoLayout, "#V17"); 394 Assert.IsFalse (type.IsByRef, "#V18"); 395 Assert.IsFalse (type.IsClass, "#V19"); 396 Assert.IsFalse (type.IsCOMObject, "#V20"); 397 Assert.IsFalse (type.IsContextful, "#V21"); 398 Assert.IsTrue (type.IsEnum, "#V22"); 399 Assert.IsFalse (type.IsExplicitLayout, "#V23"); 400 Assert.IsFalse (type.IsImport, "#V24"); 401 Assert.IsFalse (type.IsInterface, "#V25"); 402 Assert.IsFalse (type.IsLayoutSequential, "#V26"); 403 Assert.IsFalse (type.IsMarshalByRef, "#V27"); 404 Assert.IsFalse (type.IsNestedAssembly, "#V28"); 405 Assert.IsFalse (type.IsNestedFamily, "#V29"); 406 Assert.IsFalse (type.IsNestedPublic, "#V30"); 407 Assert.IsFalse (type.IsNestedPrivate, "#V31"); 408 Assert.IsFalse (type.IsNotPublic, "#V32"); 409 Assert.IsFalse (type.IsPrimitive, "#V33"); 410 Assert.IsFalse (type.IsPointer, "#V34"); 411 Assert.IsTrue (type.IsPublic, "#V35"); 412 Assert.IsTrue (type.IsSealed, "#V36"); 413 Assert.IsFalse (type.IsUnicodeClass, "#V37"); 414 Assert.IsFalse (type.IsSpecialName, "#V38"); 415 Assert.IsTrue (type.IsValueType, "#V39"); 416 } 417 MyInterfaceFilter(Type t, object filterCriteria)418 public static bool MyInterfaceFilter (Type t, object filterCriteria) 419 { 420 if (t.ToString () == filterCriteria.ToString ()) 421 return true; 422 else 423 return false; 424 } 425 MemberNameFilter(MemberInfo m, object filterCriteria)426 public static bool MemberNameFilter (MemberInfo m, object filterCriteria) 427 { 428 if (m.Name == filterCriteria.ToString ()) 429 return true; 430 else 431 return false; 432 } 433 GetAssemblyName()434 private static AssemblyName GetAssemblyName () 435 { 436 AssemblyName assemblyName = new AssemblyName (); 437 assemblyName.Name = _assemblyName; 438 return assemblyName; 439 } 440 GenerateAssembly()441 private static AssemblyBuilder GenerateAssembly () 442 { 443 return AppDomain.CurrentDomain.DefineDynamicAssembly ( 444 GetAssemblyName (), AssemblyBuilderAccess.RunAndSave); 445 } 446 GenerateModule()447 private static ModuleBuilder GenerateModule () 448 { 449 AssemblyBuilder assemblyBuilder = GenerateAssembly (); 450 return assemblyBuilder.DefineDynamicModule (_moduleName); 451 } 452 GenerateModule(AssemblyBuilder assemblyBuilder)453 private static ModuleBuilder GenerateModule (AssemblyBuilder assemblyBuilder) 454 { 455 return assemblyBuilder.DefineDynamicModule (_moduleName); 456 } 457 GenerateEnum()458 private static EnumBuilder GenerateEnum () 459 { 460 ModuleBuilder modBuilder = GenerateModule (); 461 return modBuilder.DefineEnum (_enumNamespace + "." 462 + _enumName, TypeAttributes.Public, _enumType); 463 } 464 GenerateEnum(ModuleBuilder modBuilder)465 private static EnumBuilder GenerateEnum (ModuleBuilder modBuilder) 466 { 467 return modBuilder.DefineEnum (_enumNamespace + "." 468 + _enumName, TypeAttributes.Public, _enumType); 469 } 470 GenerateField()471 private static FieldBuilder GenerateField () 472 { 473 EnumBuilder enumBuilder = GenerateEnum (); 474 return enumBuilder.DefineLiteral (_fieldName, _fieldValue); 475 } 476 GenerateField(EnumBuilder enumBuilder)477 private static FieldBuilder GenerateField (EnumBuilder enumBuilder) 478 { 479 return enumBuilder.DefineLiteral (_fieldName, _fieldValue); 480 } 481 } 482 } 483