/src/libraries/System.Reflection.Emit/tests/EnumBuilder/EnumBuilder.Methods.Tests.cs

https://github.com/dotnet/runtime · C# · 245 lines · 201 code · 41 blank · 3 comment · 5 complexity · c484fdd6c48d6f05f5d2b7f4ea3538ff MD5 · raw file

  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. using System.Collections.Generic;
  4. using System.Linq;
  5. using Xunit;
  6. namespace System.Reflection.Emit.Tests
  7. {
  8. public class EnumBuilderMethodTests
  9. {
  10. public static IEnumerable<object[]> DefineLiteral_TestData()
  11. {
  12. yield return new object[] { typeof(byte), (byte)0 };
  13. yield return new object[] { typeof(byte), (byte)1 };
  14. yield return new object[] { typeof(sbyte), (sbyte)0 };
  15. yield return new object[] { typeof(sbyte), (sbyte)1 };
  16. yield return new object[] { typeof(ushort), (ushort)0 };
  17. yield return new object[] { typeof(ushort), (ushort)1 };
  18. yield return new object[] { typeof(short), (short)0 };
  19. yield return new object[] { typeof(short), (short)1 };
  20. yield return new object[] { typeof(uint), (uint)0 };
  21. yield return new object[] { typeof(uint), (uint)1 };
  22. yield return new object[] { typeof(int), 0 };
  23. yield return new object[] { typeof(int), 1 };
  24. yield return new object[] { typeof(ulong), (ulong)0 };
  25. yield return new object[] { typeof(ulong), (ulong)1 };
  26. yield return new object[] { typeof(long), (long)0 };
  27. yield return new object[] { typeof(long), (long)1 };
  28. yield return new object[] { typeof(char), (char)0 };
  29. yield return new object[] { typeof(char), (char)1 };
  30. yield return new object[] { typeof(bool), true };
  31. yield return new object[] { typeof(bool), false };
  32. yield return new object[] { typeof(float), 0f };
  33. yield return new object[] { typeof(float), 1.1f };
  34. yield return new object[] { typeof(double), 0d };
  35. yield return new object[] { typeof(double), 1.1d };
  36. }
  37. [Theory]
  38. [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)]
  39. [MemberData(nameof(DefineLiteral_TestData))]
  40. public void DefineLiteral(Type underlyingType, object literalValue)
  41. {
  42. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, underlyingType);
  43. FieldBuilder literal = enumBuilder.DefineLiteral("FieldOne", literalValue);
  44. Assert.Equal("FieldOne", literal.Name);
  45. Assert.Equal(enumBuilder.Name, literal.DeclaringType.Name);
  46. Assert.Equal(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal, literal.Attributes);
  47. Assert.Equal(enumBuilder.AsType(), literal.FieldType);
  48. Type createdEnum = enumBuilder.CreateTypeInfo().AsType();
  49. FieldInfo createdLiteral = createdEnum.GetField("FieldOne");
  50. Assert.Equal(createdEnum, createdLiteral.FieldType);
  51. if (literalValue is bool || literalValue is float || literalValue is double)
  52. {
  53. // EnumBuilder generates invalid data for non-integer enums
  54. Assert.Throws<FormatException>(() => createdLiteral.GetValue(null));
  55. }
  56. else
  57. {
  58. Assert.Equal(Enum.ToObject(createdEnum, literalValue), createdLiteral.GetValue(null));
  59. }
  60. }
  61. [Fact]
  62. public void DefineLiteral_NullLiteralName_ThrowsArgumentNullException()
  63. {
  64. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int));
  65. AssertExtensions.Throws<ArgumentNullException>("fieldName", () => enumBuilder.DefineLiteral(null, 1));
  66. }
  67. [Theory]
  68. [InlineData("")]
  69. [InlineData("\0")]
  70. [InlineData("\0abc")]
  71. public void DefineLiteral_EmptyLiteralName_ThrowsArgumentException(string literalName)
  72. {
  73. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int));
  74. AssertExtensions.Throws<ArgumentException>("fieldName", () => enumBuilder.DefineLiteral(literalName, 1));
  75. }
  76. public static IEnumerable<object[]> DefineLiteral_InvalidLiteralValue_ThrowsArgumentException_TestData()
  77. {
  78. yield return new object[] { typeof(int), null };
  79. yield return new object[] { typeof(int), (short)1 };
  80. yield return new object[] { typeof(short), 1 };
  81. yield return new object[] { typeof(float), 1d };
  82. yield return new object[] { typeof(double), 1f };
  83. yield return new object[] { typeof(IntPtr), (IntPtr)1 };
  84. yield return new object[] { typeof(UIntPtr), (UIntPtr)1 };
  85. yield return new object[] { typeof(int).MakePointerType(), 1 };
  86. yield return new object[] { typeof(int).MakeByRefType(), 1 };
  87. yield return new object[] { typeof(int[]), new int[] { 1 } };
  88. yield return new object[] { typeof(int?), 1 };
  89. yield return new object[] { typeof(int?), null };
  90. yield return new object[] { typeof(string), null };
  91. }
  92. [Theory]
  93. [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)]
  94. [MemberData(nameof(DefineLiteral_InvalidLiteralValue_ThrowsArgumentException_TestData))]
  95. public void DefineLiteral_InvalidLiteralValue_ThrowsArgumentException(Type underlyingType, object literalValue)
  96. {
  97. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, underlyingType);
  98. AssertExtensions.Throws<ArgumentException>(null, () => enumBuilder.DefineLiteral("LiteralName", literalValue));
  99. }
  100. public static IEnumerable<object[]> DefineLiteral_InvalidLiteralValue_ThrowsTypeLoadExceptionOnCreation_TestData()
  101. {
  102. yield return new object[] { typeof(DateTime), DateTime.Now };
  103. yield return new object[] { typeof(string), "" }; ;
  104. }
  105. [Theory]
  106. [MemberData(nameof(DefineLiteral_InvalidLiteralValue_ThrowsTypeLoadExceptionOnCreation_TestData))]
  107. public void DefineLiteral_InvalidLiteralValue_ThrowsTypeLoadExceptionOnCreation(Type underlyingType, object literalValue)
  108. {
  109. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, underlyingType);
  110. FieldBuilder literal = enumBuilder.DefineLiteral("LiteralName", literalValue);
  111. Assert.Throws<TypeLoadException>(() => enumBuilder.CreateTypeInfo());
  112. }
  113. [Fact]
  114. public void IsAssignableFrom()
  115. {
  116. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int));
  117. Assert.False(enumBuilder.IsAssignableFrom(null));
  118. Assert.True(enumBuilder.IsAssignableFrom(typeof(int).GetTypeInfo()));
  119. Assert.False(enumBuilder.IsAssignableFrom(typeof(short).GetTypeInfo()));
  120. }
  121. [Fact]
  122. public void GetElementType_ThrowsNotSupportedException()
  123. {
  124. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int));
  125. Assert.Throws<NotSupportedException>(() => enumBuilder.GetElementType());
  126. }
  127. [Fact]
  128. public void MakeArrayType()
  129. {
  130. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int), enumName: "TestEnum");
  131. Type arrayType = enumBuilder.MakeArrayType();
  132. Assert.Equal(typeof(Array), arrayType.GetTypeInfo().BaseType);
  133. Assert.Equal("TestEnum[]", arrayType.Name);
  134. }
  135. [Theory]
  136. [InlineData(1)]
  137. [InlineData(2)]
  138. [InlineData(260)]
  139. public void MakeArrayType_Int(int rank)
  140. {
  141. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int), enumName: "TestEnum");
  142. Type arrayType = enumBuilder.MakeArrayType(rank);
  143. string ranks = rank == 1 ? "*" : string.Empty;
  144. for (int i = 1; i < rank; i++)
  145. {
  146. ranks += ",";
  147. }
  148. Assert.Equal(typeof(Array), arrayType.GetTypeInfo().BaseType);
  149. Assert.Equal($"TestEnum[{ranks}]", arrayType.Name);
  150. }
  151. [Theory]
  152. [InlineData(0)]
  153. [InlineData(-1)]
  154. public void MakeArrayType_Int_RankLessThanOne_ThrowsIndexOutOfRange(int rank)
  155. {
  156. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int), enumName: "TestEnum");
  157. Assert.Throws<IndexOutOfRangeException>(() => enumBuilder.MakeArrayType(rank));
  158. }
  159. [Fact]
  160. public void MakeByRefType()
  161. {
  162. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int), enumName: "TestEnum");
  163. Type arrayType = enumBuilder.MakeByRefType();
  164. Assert.Equal(typeof(Array), arrayType.GetTypeInfo().BaseType);
  165. Assert.Equal("TestEnum&", arrayType.Name);
  166. }
  167. [Fact]
  168. public void MakePointerType()
  169. {
  170. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int), enumName: "TestEnum");
  171. Type arrayType = enumBuilder.MakePointerType();
  172. Assert.Equal(typeof(Array), arrayType.GetTypeInfo().BaseType);
  173. Assert.Equal("TestEnum*", arrayType.Name);
  174. }
  175. [Fact]
  176. [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)]
  177. public void SetCustomAttribute_ConstructorInfo_ByteArray()
  178. {
  179. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int));
  180. enumBuilder.CreateTypeInfo().AsType();
  181. ConstructorInfo attributeConstructor = typeof(BoolAttribute).GetConstructor(new Type[] { typeof(bool) });
  182. enumBuilder.SetCustomAttribute(attributeConstructor, new byte[] { 01, 00, 01 });
  183. Attribute[] objVals = (Attribute[])CustomAttributeExtensions.GetCustomAttributes(enumBuilder, true).ToArray();
  184. Assert.Equal(new BoolAttribute(true), objVals[0]);
  185. }
  186. [Fact]
  187. [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)]
  188. public void SetCustomAttribute_CustomAttributeBuilder()
  189. {
  190. EnumBuilder enumBuilder = Helpers.DynamicEnum(TypeAttributes.Public, typeof(int));
  191. enumBuilder.CreateTypeInfo().AsType();
  192. ConstructorInfo attributeConstructor = typeof(BoolAttribute).GetConstructor(new Type[] { typeof(bool) });
  193. CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(attributeConstructor, new object[] { true });
  194. enumBuilder.SetCustomAttribute(attributeBuilder);
  195. object[] objVals = enumBuilder.GetCustomAttributes(true).ToArray();
  196. Assert.Equal(new BoolAttribute(true), objVals[0]);
  197. }
  198. public class BoolAttribute : Attribute
  199. {
  200. private bool _b;
  201. public BoolAttribute(bool myBool) { _b = myBool; }
  202. }
  203. }
  204. }