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