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.Collections.Generic; 6 using Xunit; 7 8 namespace System.Reflection.Emit.Tests 9 { 10 public class TypeBuilderSetParent 11 { SetParent_TestData()12 public static IEnumerable<object[]> SetParent_TestData() 13 { 14 yield return new object[] { TypeAttributes.NotPublic, typeof(EmptyNonGenericClass), typeof(EmptyNonGenericClass) }; 15 yield return new object[] { TypeAttributes.NotPublic, typeof(object), typeof(object) }; 16 yield return new object[] { TypeAttributes.NotPublic, null, typeof(object) }; 17 yield return new object[] { TypeAttributes.Abstract, typeof(EmptyGenericClass<int>), typeof(EmptyGenericClass<int>) }; 18 yield return new object[] { TypeAttributes.Interface | TypeAttributes.Abstract, null, null }; 19 } 20 21 [Theory] 22 [MemberData(nameof(SetParent_TestData))] SetParent(TypeAttributes attributes, Type parent, Type expected)23 public void SetParent(TypeAttributes attributes, Type parent, Type expected) 24 { 25 TypeBuilder type = Helpers.DynamicType(attributes); 26 27 type.SetParent(parent); 28 Assert.Equal(expected, type.BaseType); 29 30 TypeInfo createdType = type.CreateTypeInfo(); 31 Assert.Equal(expected, createdType.BaseType); 32 } 33 34 [Fact] SetParent_TypeCreated_ThrowsInvalidOperationException()35 public void SetParent_TypeCreated_ThrowsInvalidOperationException() 36 { 37 TypeBuilder type = Helpers.DynamicType(TypeAttributes.NotPublic); 38 type.CreateTypeInfo().AsType(); 39 Assert.Throws<InvalidOperationException>(() => type.SetParent(typeof(string))); 40 } 41 42 [Fact] 43 [ActiveIssue(13977)] SetParent_This_LoopsForever()44 public void SetParent_This_LoopsForever() 45 { 46 TypeBuilder type = Helpers.DynamicType(TypeAttributes.NotPublic); 47 type.SetParent(type.AsType()); 48 Assert.Equal(type.AsType(), type.BaseType); 49 50 Assert.ThrowsAny<Exception>(() => type.CreateTypeInfo()); 51 } 52 53 [Fact] SetParent_ThisIsInterface_ThrowsTypeLoadExceptionOnLoad()54 public void SetParent_ThisIsInterface_ThrowsTypeLoadExceptionOnLoad() 55 { 56 TypeBuilder type = Helpers.DynamicType(TypeAttributes.Interface | TypeAttributes.Abstract); 57 type.SetParent(typeof(EmptyNonGenericClass)); 58 Assert.Throws<TypeLoadException>(() => type.CreateTypeInfo()); 59 } 60 61 [Theory] 62 [InlineData(TypeAttributes.NotPublic)] 63 [InlineData(TypeAttributes.Interface | TypeAttributes.Abstract)] SetParent_InterfaceType_ThrowsArgumentException(TypeAttributes attributes)64 public void SetParent_InterfaceType_ThrowsArgumentException(TypeAttributes attributes) 65 { 66 TypeBuilder type = Helpers.DynamicType(attributes); 67 AssertExtensions.Throws<ArgumentException>(null, () => type.SetParent(typeof(EmptyNonGenericInterface1))); 68 } 69 70 [Fact] SetParent_ByRefType_ThrowsArgumentExceptionOnCreation()71 public void SetParent_ByRefType_ThrowsArgumentExceptionOnCreation() 72 { 73 TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); 74 75 type.SetParent(typeof(int).MakeByRefType()); 76 Assert.Equal(typeof(int).MakeByRefType(), type.BaseType); 77 78 AssertExtensions.Throws<ArgumentException>(null, () => type.CreateTypeInfo()); 79 } 80 81 [Fact] SetParent_GenericParameter_ThrowsNotSupportedExceptionOnCreation()82 public void SetParent_GenericParameter_ThrowsNotSupportedExceptionOnCreation() 83 { 84 TypeBuilder type = Helpers.DynamicType(TypeAttributes.NotPublic); 85 GenericTypeParameterBuilder genericType = type.DefineGenericParameters("T")[0]; 86 87 type.SetParent(genericType.AsType()); 88 Assert.Equal(genericType.AsType(), type.BaseType); 89 90 Assert.Throws<NotSupportedException>(() => type.CreateTypeInfo()); 91 } 92 93 [Fact] ParentNotCreated_ThrowsNotSupportedExceptionOnCreation()94 public void ParentNotCreated_ThrowsNotSupportedExceptionOnCreation() 95 { 96 ModuleBuilder module = Helpers.DynamicModule(); 97 TypeBuilder type = module.DefineType("Daughter", TypeAttributes.Public); 98 TypeBuilder parentType = module.DefineType("Parent", TypeAttributes.Public); 99 100 type.SetParent(parentType.AsType()); 101 Assert.Equal(parentType.AsType(), type.BaseType); 102 103 Assert.Throws<NotSupportedException>(() => type.CreateTypeInfo()); 104 } 105 106 [Theory] 107 [InlineData(typeof(void))] 108 [InlineData(typeof(EmptyNonGenericStruct))] 109 [InlineData(typeof(EmptyEnum))] 110 [InlineData(typeof(EmptyGenericStruct<>))] 111 [InlineData(typeof(EmptyGenericStruct<int>))] 112 [InlineData(typeof(SealedClass))] 113 [InlineData(typeof(int?))] ParentNotInheritable_ThrowsTypeLoadExceptionOnCreation(Type parentType)114 public void ParentNotInheritable_ThrowsTypeLoadExceptionOnCreation(Type parentType) 115 { 116 TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); 117 118 type.SetParent(parentType); 119 Assert.Equal(parentType, type.BaseType); 120 121 Assert.Throws<TypeLoadException>(() => type.CreateTypeInfo()); 122 } 123 124 [Theory] 125 [InlineData(typeof(string))] 126 [InlineData(typeof(StaticClass))] 127 [InlineData(typeof(int*))] 128 [InlineData(typeof(EmptyNonGenericClass[]))] ParentHasNoDefaultConstructor_ThrowsNotSupportedExceptionOnCreation(Type parentType)129 public void ParentHasNoDefaultConstructor_ThrowsNotSupportedExceptionOnCreation(Type parentType) 130 { 131 TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); 132 133 type.SetParent(parentType); 134 Assert.Equal(parentType, type.BaseType); 135 136 Assert.Throws<NotSupportedException>(() => type.CreateTypeInfo()); 137 } 138 139 [Fact] ParentOpenGenericClass_ThrowsBadImageFormatExceptionOnCreation()140 public void ParentOpenGenericClass_ThrowsBadImageFormatExceptionOnCreation() 141 { 142 TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); 143 144 type.SetParent(typeof(EmptyGenericClass<>)); 145 Assert.Equal(typeof(EmptyGenericClass<>), type.BaseType); 146 147 Assert.Throws<BadImageFormatException>(() => type.CreateTypeInfo()); 148 } 149 } 150 } 151