1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Linq; 6 using Xunit; 7 8 namespace System.Reflection.Emit.Tests 9 { 10 public class EmptyNonGenericClass { } 11 public class EmptyGenericClass<T> { } 12 public sealed class SealedClass { } 13 public static class StaticClass { } 14 15 public struct EmptyNonGenericStruct { } 16 public struct EmptyGenericStruct<T> { } 17 18 public enum EmptyEnum { } BasicDelegate()19 public delegate EventHandler BasicDelegate(); 20 21 public interface EmptyNonGenericInterface1 { } 22 public interface EmptyNonGenericInterface2 { } 23 24 public interface EmptyGenericInterface<T> { } 25 26 public class EmptyAttribute : Attribute { } 27 28 [AttributeUsage(AttributeTargets.All, AllowMultiple = false)] 29 public class IntAllAttribute : Attribute 30 { 31 public int _i; IntAllAttribute(int i)32 public IntAllAttribute(int i) { _i = i; } 33 } 34 35 public static class TypeExtensions 36 { AsType(this Type type)37 public static Type AsType(this Type type) 38 { 39 return type; 40 } 41 } 42 43 public static class Helpers 44 { 45 public const BindingFlags AllFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 46 DynamicAssembly(string name = R, AssemblyBuilderAccess access = AssemblyBuilderAccess.Run)47 public static AssemblyBuilder DynamicAssembly(string name = "TestAssembly", AssemblyBuilderAccess access = AssemblyBuilderAccess.Run) 48 { 49 AssemblyName assemblyName = new AssemblyName(name); 50 return AssemblyBuilder.DefineDynamicAssembly(assemblyName, access); 51 } 52 DynamicModule(string assemblyName = R, string moduleName = R)53 public static ModuleBuilder DynamicModule(string assemblyName = "TestAssembly", string moduleName = "TestModule") 54 { 55 return DynamicAssembly(assemblyName).DefineDynamicModule(moduleName); 56 } 57 DynamicType(TypeAttributes attributes, string assemblyName = R, string moduleName = R, string typeName = R)58 public static TypeBuilder DynamicType(TypeAttributes attributes, string assemblyName = "TestAssembly", string moduleName = "TestModule", string typeName = "TestType") 59 { 60 return DynamicModule(assemblyName, moduleName).DefineType(typeName, attributes); 61 } 62 DynamicEnum(TypeAttributes visibility, Type underlyingType, string enumName = R, string assemblyName = R, string moduleName = R)63 public static EnumBuilder DynamicEnum(TypeAttributes visibility, Type underlyingType, string enumName = "TestEnum", string assemblyName = "TestAssembly", string moduleName = "TestModule") 64 { 65 return DynamicModule(assemblyName, moduleName).DefineEnum(enumName, visibility, underlyingType); 66 } 67 VerifyType(TypeBuilder type, Module module, TypeBuilder declaringType, string name, TypeAttributes attributes, Type baseType, int size, PackingSize packingSize, Type[] implementedInterfaces)68 public static void VerifyType(TypeBuilder type, Module module, TypeBuilder declaringType, string name, TypeAttributes attributes, Type baseType, int size, PackingSize packingSize, Type[] implementedInterfaces) 69 { 70 Assert.Equal(module, type.Module); 71 Assert.Equal(module.Assembly, type.Assembly); 72 73 Assert.Equal(name, type.Name); 74 if (declaringType == null) 75 { 76 Assert.Equal(GetFullName(name), type.FullName); 77 } 78 else 79 { 80 Assert.Equal(GetFullName(declaringType.Name) + "+" + GetFullName(type.Name), type.FullName); 81 } 82 83 Assert.Equal(attributes, type.Attributes); 84 85 Assert.Equal(declaringType?.AsType(), type.DeclaringType); 86 Assert.Equal(baseType, type.BaseType); 87 88 Assert.Equal(size, type.Size); 89 Assert.Equal(packingSize, type.PackingSize); 90 91 Assert.Equal(implementedInterfaces ?? new Type[0], type.GetInterfaces()); 92 93 if (declaringType == null && !type.IsInterface && (implementedInterfaces == null || implementedInterfaces.Length == 0)) 94 { 95 Type createdType = type.CreateTypeInfo().AsType(); 96 Assert.Equal(createdType, module.GetType(name, false, false)); 97 Assert.Equal(createdType, module.GetType(name, true, false)); 98 99 Assert.Equal(type.AsType().GetNestedTypes(AllFlags), createdType.GetNestedTypes(AllFlags)); 100 Assert.Equal(type.AsType().GetNestedType(name, AllFlags), createdType.GetNestedType(name, AllFlags)); 101 102 // [ActiveIssue(10989, TestPlatforms.AnyUnix)] 103 // Assert.Equal(createdType, module.GetType(name, true, true)); 104 // Assert.Equal(createdType, module.GetType(name.ToLowerInvariant(), true, true)); 105 // Assert.Equal(createdType, module.GetType(name.ToUpperInvariant(), true, true)); 106 } 107 } 108 VerifyConstructor(ConstructorBuilder constructor, TypeBuilder type, MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes)109 public static void VerifyConstructor(ConstructorBuilder constructor, TypeBuilder type, MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes) 110 { 111 string expectedName = (attributes & MethodAttributes.Static) != 0 ? ConstructorInfo.TypeConstructorName : ConstructorInfo.ConstructorName; 112 113 Assert.Equal(expectedName, constructor.Name); 114 Assert.Equal(attributes | MethodAttributes.SpecialName, constructor.Attributes); 115 Assert.Equal(CallingConventions.Standard, constructor.CallingConvention); 116 Assert.Equal(type.AsType(), constructor.DeclaringType); 117 Assert.Equal(type.Module, constructor.Module); 118 Assert.Equal(MethodImplAttributes.IL, constructor.MethodImplementationFlags); 119 120 Assert.Throws<NotSupportedException>(() => constructor.Invoke(null)); 121 Assert.Throws<NotSupportedException>(() => constructor.Invoke(null, null)); 122 123 Type createdType = type.CreateTypeInfo().AsType(); 124 Assert.Equal(type.AsType().GetConstructors(AllFlags), createdType.GetConstructors(AllFlags)); 125 Assert.Equal(type.AsType().GetConstructor(parameterTypes), createdType.GetConstructor(parameterTypes)); 126 127 ConstructorInfo createdConstructor = createdType.GetConstructors(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) 128 .Single(ctor => ctor.IsStatic == constructor.IsStatic); 129 130 CallingConventions expectedCallingConvention = CallingConventions.Standard; 131 if ((callingConvention & CallingConventions.VarArgs) != 0) 132 { 133 expectedCallingConvention = CallingConventions.VarArgs; 134 } 135 if ((attributes & MethodAttributes.Static) == 0) 136 { 137 expectedCallingConvention |= CallingConventions.HasThis; 138 } 139 140 MethodAttributes expectedAttributes = attributes | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; 141 expectedAttributes &= ~MethodAttributes.RequireSecObject; 142 143 Assert.Equal(expectedName, constructor.Name); 144 Assert.Equal(expectedAttributes, createdConstructor.Attributes); 145 Assert.Equal(expectedCallingConvention, createdConstructor.CallingConvention); 146 Assert.Equal(createdType, createdConstructor.DeclaringType); 147 Assert.Equal(MethodImplAttributes.IL, constructor.MethodImplementationFlags); 148 } 149 GetFullName(string name)150 public static string GetFullName(string name) 151 { 152 int nullTerminatorIndex = name.IndexOf('\0'); 153 if (nullTerminatorIndex >= 0) 154 { 155 return name.Substring(0, nullTerminatorIndex); 156 } 157 return name; 158 } 159 } 160 } 161