namespace System.Tests
{
- public static partial class Helpers
+ public static class Helpers
{
private static Type s_refEmitType;
<Compile Include="$(CommonTestPath)\System\Collections\IEnumerable.NonGeneric.Tests.cs">
<Link>Common\System\Collections\IEnumerable.NonGeneric.Tests.cs</Link>
</Compile>
+ <Compile Include="Helpers.cs" />
<Compile Include="Microsoft\Win32\SafeHandles\CriticalHandleZeroOrMinusOneIsInvalid.cs" />
<Compile Include="Microsoft\Win32\SafeHandles\SafeHandleZeroOrMinusOneIsInvalid.cs" />
<Compile Include="System\AccessViolationExceptionTests.cs" />
<Compile Include="System\ActivatorTests.cs" />
<Compile Include="System\ActivatorTests.Generic.cs" />
+ <Compile Include="System\AmbiguousImplementationExceptionTests.cs" />
<Compile Include="System\ArgumentExceptionTests.cs" />
<Compile Include="System\ArgumentNullExceptionTests.cs" />
<Compile Include="System\ArgumentOutOfRangeExceptionTests.cs" />
<Compile Include="System\GCTests.cs" />
<Compile Include="System\GuidTests.cs" />
<Compile Include="System\HandleTests.cs" />
+ <Compile Include="System\HashCodeTests.cs" />
<Compile Include="System\IndexOutOfRangeExceptionTests.cs" />
+ <Compile Include="System\IndexTests.cs" />
<Compile Include="System\Int16Tests.cs" />
<Compile Include="System\Int32Tests.cs" />
<Compile Include="System\Int64Tests.cs" />
<Compile Include="System\ParamArrayAttributeTests.cs" />
<Compile Include="System\PlatformNotSupportedExceptionTests.cs" />
<Compile Include="System\PseudoCustomAttributeTests.cs" />
+ <Compile Include="System\RangeTests.cs" />
<Compile Include="System\RankExceptionTests.cs" />
<Compile Include="System\SByteTests.cs" />
<Compile Include="System\SingleTests.cs" />
<Compile Include="System\StackOverflowExceptionTests.cs" />
<Compile Include="System\StringComparerTests.cs" />
<Compile Include="System\StringGetHashCodeTests.cs" />
+ <Compile Include="System\StringTests.cs" />
<Compile Include="System\String.SplitTests.cs" />
<Compile Include="System\SystemExceptionTests.cs" />
<Compile Include="System\TimeoutExceptionTests.cs" />
<Compile Include="System\TimeZoneInfoTests.cs" />
<Compile Include="System\TimeZoneTests.cs" />
<Compile Include="System\TimeZoneNotFoundExceptionTests.cs" />
+ <Compile Include="System\TypedReferenceTests.cs" />
<Compile Include="System\TypeLoadExceptionTests.cs" />
<Compile Include="System\TypeUnloadedExceptionTests.cs" />
<Compile Include="System\TupleTests.cs" />
<Compile Include="System\Reflection\AssemblyTitleAttributeTests.cs" />
<Compile Include="System\Reflection\AssemblyTrademarkAttributeTests.cs" />
<Compile Include="System\Reflection\AssemblyVersionAttributeTests.cs" />
+ <Compile Include="System\Reflection\BindingFlagsDoNotWrap.cs" />
<Compile Include="System\Reflection\CustomAttributeDataTests.cs" />
<Compile Include="System\Reflection\CustomAttributesTestData.cs" />
<Compile Include="System\Reflection\CustomAttribute_Named_Typed_ArgumentTests.cs" />
<Compile Include="System\Reflection\DefaultMemberAttributeTests.cs" />
+ <Compile Include="System\Reflection\InvokeRefReturn.cs" />
+ <Compile Include="System\Reflection\IsCollectibleTests.cs" />
<Compile Include="System\Reflection\MethodBaseTests.cs" />
<Compile Include="System\Reflection\MethodBodyTests.cs" />
<Compile Include="System\Reflection\ModuleTests.cs" />
<Compile Include="System\ExitCodeTests.Unix.cs" />
</ItemGroup>
<ItemGroup>
- <Compile Include="System\HashCodeTests.netcoreapp.cs" />
- <Compile Include="Helpers.netcoreapp.cs" />
- <Compile Include="System\ActivatorTests.netcoreapp.cs" />
- <Compile Include="System\AmbiguousImplementationExceptionTests.cs" />
- <Compile Include="System\ArrayTests.netcoreapp.cs" />
- <Compile Include="System\ArraySegmentTests.netcoreapp.cs" />
- <Compile Include="System\BooleanTests.netcoreapp.cs" />
- <Compile Include="System\ByteTests.netcoreapp.cs" />
- <Compile Include="System\CharTests.netcoreapp.cs" />
- <Compile Include="System\DateTimeTests.netcoreapp.cs" />
- <Compile Include="System\DateTimeOffsetTests.netcoreapp.cs" />
- <Compile Include="System\DecimalTests.netcoreapp.cs" />
- <Compile Include="System\EnumTests.netcoreapp.cs" />
- <Compile Include="System\FormattableStringTests.netcoreapp.cs" />
- <Compile Include="System\GCTests.netcoreapp.cs" />
- <Compile Include="System\GuidTests.netcoreapp.cs" />
- <Compile Include="System\IndexTests.cs" />
- <Compile Include="System\Int16Tests.netcoreapp.cs" />
- <Compile Include="System\Int32Tests.netcoreapp.cs" />
- <Compile Include="System\Int64Tests.netcoreapp.cs" />
- <Compile Include="System\IntPtrTests.netcoreapp.cs" />
- <Compile Include="System\Collections\Generic\KeyValuePairTests.netcoreapp.cs" />
- <Compile Include="System\LazyTests.netcoreapp.cs" />
- <Compile Include="System\RangeTests.cs" />
- <Compile Include="System\SByteTests.netcoreapp.cs" />
- <Compile Include="System\StringComparerTests.netcoreapp.cs" />
- <Compile Include="System\StringGetHashCodeTests.netcoreapp.cs" />
- <Compile Include="System\StringTests.netcoreapp.cs" />
- <Compile Include="System\TimeSpanTests.netcoreapp.cs" />
- <Compile Include="System\TypedReferenceTests.cs" />
- <Compile Include="System\UIntPtrTests.netcoreapp.cs" />
- <Compile Include="System\UInt16Tests.netcoreapp.cs" />
- <Compile Include="System\UInt32Tests.netcoreapp.cs" />
- <Compile Include="System\UInt64Tests.netcoreapp.cs" />
- <Compile Include="System\VersionTests.netcoreapp.cs" />
- <Compile Include="System\ComponentModel\DefaultValueAttributeTests.netcoreapp.cs" />
- <Compile Include="System\Reflection\BindingFlagsDoNotWrap.netcoreapp.cs" />
- <Compile Include="System\Reflection\InvokeRefReturn.netcoreapp.cs" />
- <Compile Include="System\Reflection\IsCollectibleTests.cs" />
- <!-- missing method 'AssemblyLoadContext..ctor(bool) -->
- <Compile Include="System\Reflection\MethodBaseTests.netcoreapp.cs" />
- <Compile Include="System\Reflection\SignatureTypes.netcoreapp.cs" />
- <Compile Include="System\Reflection\TypeDelegatorTests.netcoreapp.cs" />
- <Compile Include="System\Runtime\CompilerServices\AttributesTests.netcoreapp.cs" />
+ <Compile Include="System\Reflection\SignatureTypes.cs" />
<Compile Include="System\Runtime\CompilerServices\CallerArgumentExpressionAttributeTests.cs" />
- <Compile Include="System\Runtime\CompilerServices\ConditionalWeakTableTests.netcoreapp.cs" />
- <Compile Include="System\Runtime\CompilerServices\MethodImplAttributeTests.netcoreapp.cs" />
- <Compile Include="System\Runtime\CompilerServices\RuntimeHelpersTests.netcoreapp.cs" />
- <Compile Include="System\Runtime\CompilerServices\RuntimeFeatureTests.netcoreapp.cs" />
+ <Compile Include="System\Runtime\CompilerServices\MethodImplAttributeTests.cs" />
+ <Compile Include="System\Runtime\CompilerServices\RuntimeFeatureTests.cs" />
<Compile Include="System\Runtime\CompilerServices\RuntimeWrappedExceptionTests.cs" />
- <Compile Include="System\Runtime\ExceptionServices\ExceptionDispatchInfoTests.netcoreapp.cs" />
- <Compile Include="System\Text\ASCIIUtilityTests.netcoreapp.cs" />
- <Compile Include="System\Text\RuneTests.netcoreapp.cs" />
- <Compile Include="System\Text\RuneTests.TestData.netcoreapp.cs" />
- <Compile Include="System\Text\StringBuilderTests.netcoreapp.cs" />
- <Compile Include="System\Text\Unicode\UnicodeData.netcoreapp.cs" />
- <Compile Include="System\Text\Unicode\Utf16UtilityTests.ValidateChars.netcoreapp.cs" />
- <Compile Include="System\Text\Unicode\Utf8Tests.netcoreapp.cs" />
- <Compile Include="System\Text\Unicode\Utf8Tests.ToBytes.netcoreapp.cs" />
- <Compile Include="System\Text\Unicode\Utf8Tests.ToChars.netcoreapp.cs" />
- <Compile Include="System\Text\Unicode\Utf8UtilityTests.ValidateBytes.netcoreapp.cs" />
- <Compile Include="System\Type\TypePropertyTests.netcoreapp.cs" />
- <Compile Include="System\Type\TypeTests.netcoreapp.cs" />
- <Compile Include="System\ArgIteratorTests.netcoreapp.cs" />
- <Compile Include="System\DoubleTests.netcoreapp.cs" />
- <Compile Include="System\SingleTests.netcoreapp.cs" />
+ <Compile Include="System\Runtime\ExceptionServices\ExceptionDispatchInfoTests.cs" />
+ <Compile Include="System\Text\ASCIIUtilityTests.cs" />
+ <Compile Include="System\Text\RuneTests.cs" />
+ <Compile Include="System\Text\RuneTests.TestData.cs" />
+ <Compile Include="System\Text\Unicode\UnicodeData.cs" />
+ <Compile Include="System\Text\Unicode\Utf16UtilityTests.ValidateChars.cs" />
+ <Compile Include="System\Text\Unicode\Utf8Tests.cs" />
+ <Compile Include="System\Text\Unicode\Utf8UtilityTests.ValidateBytes.cs" />
+ <Compile Include="System\ArgIteratorTests.cs" />
<Compile Include="$(CommonPath)\..\tests\System\RealFormatterTestsBase.netcoreapp.cs" Link="System\RealFormatterTestsBase.netcoreapp.cs" />
- <Compile Include="System\RealFormatterTests.netcoreapp.cs" />
+ <Compile Include="System\RealFormatterTests.cs" />
<Compile Include="$(CommonPath)\..\tests\System\RealParserTestsBase.netcoreapp.cs" Link="System\RealParserTestsBase.netcoreapp.cs" />
<Compile Include="System\RealParserTests.netcoreapp.cs" />
</ItemGroup>
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Globalization;
+using System.IO;
using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.Remoting;
+using Microsoft.DotNet.RemoteExecutor;
using Xunit;
namespace System.Tests
Activator.CreateInstance(typeof(ClassWithIsTestedAttribute), null, null);
Activator.CreateInstance(typeof(ClassWithIsTestedAttribute), null, new object[] { });
}
+
+ [Fact]
+ public void CreateInstance_NonPublicValueTypeWithPrivateDefaultConstructor_Success()
+ {
+ AssemblyName assemblyName = new AssemblyName("Assembly");
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type", TypeAttributes.Public, typeof(ValueType));
+
+ FieldBuilder fieldBuilder = typeBuilder.DefineField("_field", typeof(int), FieldAttributes.Public);
+ ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, CallingConventions.Standard, new Type[0]);
+
+ ILGenerator generator = constructorBuilder.GetILGenerator();
+ generator.Emit(OpCodes.Ldarg_0);
+ generator.Emit(OpCodes.Ldc_I4, -1);
+ generator.Emit(OpCodes.Stfld, fieldBuilder);
+ generator.Emit(OpCodes.Ret);
+
+ Type type = typeBuilder.CreateType();
+ FieldInfo field = type.GetField("_field");
+
+ // Activator holds a cache of constructors and the types to which they belong.
+ // Test caching behaviour by activating multiple times.
+ object v1 = Activator.CreateInstance(type, nonPublic: true);
+ Assert.Equal(-1, field.GetValue(v1));
+
+ object v2 = Activator.CreateInstance(type, nonPublic: true);
+ Assert.Equal(-1, field.GetValue(v2));
+ }
+
+ [Fact]
+ public void CreateInstance_PublicOnlyValueTypeWithPrivateDefaultConstructor_ThrowsMissingMethodException()
+ {
+ AssemblyName assemblyName = new AssemblyName("Assembly");
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type", TypeAttributes.Public, typeof(ValueType));
+
+ FieldBuilder fieldBuilder = typeBuilder.DefineField("_field", typeof(int), FieldAttributes.Public);
+ ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, CallingConventions.Standard, new Type[0]);
+
+ ILGenerator generator = constructorBuilder.GetILGenerator();
+ generator.Emit(OpCodes.Ldarg_0);
+ generator.Emit(OpCodes.Ldc_I4, -1);
+ generator.Emit(OpCodes.Stfld, fieldBuilder);
+ generator.Emit(OpCodes.Ret);
+
+ Type type = typeBuilder.CreateType();
+
+ Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(type));
+ Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(type, nonPublic: false));
+
+ // Put the private default constructor into the cache and make sure we still throw if public only.
+ Assert.NotNull(Activator.CreateInstance(type, nonPublic: true));
+
+ Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(type));
+ Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(type, nonPublic: false));
+ }
+
+ [Theory]
+ [MemberData(nameof(TestingCreateInstanceFromObjectHandleData))]
+ public static void TestingCreateInstanceFromObjectHandle(string physicalFileName, string assemblyFile, string type, string returnedFullNameType, Type exceptionType)
+ {
+ ObjectHandle oh = null;
+
+ if (exceptionType != null)
+ {
+ Assert.Throws(exceptionType, () => Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type));
+ }
+ else
+ {
+ oh = Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type);
+ CheckValidity(oh, returnedFullNameType);
+ }
+
+ if (exceptionType != null)
+ {
+ Assert.Throws(exceptionType, () => Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, null));
+ }
+ else
+ {
+ oh = Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, null);
+ CheckValidity(oh, returnedFullNameType);
+ }
+ Assert.True(File.Exists(physicalFileName));
+ }
+
+ public static TheoryData<string, string, string, string, Type> TestingCreateInstanceFromObjectHandleData => new TheoryData<string, string, string, string, Type>()
+ {
+ // string physicalFileName, string assemblyFile, string typeName, returnedFullNameType, expectedException
+ { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PublicClassSample", "PublicClassSample", null },
+ { "TestLoadAssembly.dll", "testloadassembly.dll", "publicclasssample", "PublicClassSample", typeof(TypeLoadException) },
+
+ { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PrivateClassSample", "PrivateClassSample", null },
+ { "TestLoadAssembly.dll", "testloadassembly.dll", "privateclasssample", "PrivateClassSample", typeof(TypeLoadException) },
+
+ { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PublicClassNoDefaultConstructorSample", "PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) },
+ { "TestLoadAssembly.dll", "testloadassembly.dll", "publicclassnodefaultconstructorsample", "PublicClassNoDefaultConstructorSample", typeof(TypeLoadException) }
+ };
+
+ [Theory]
+ [MemberData(nameof(TestingCreateInstanceObjectHandleData))]
+ public static void TestingCreateInstanceObjectHandle(string assemblyName, string type, string returnedFullNameType, Type exceptionType, bool returnNull)
+ {
+ ObjectHandle oh = null;
+
+ if (exceptionType != null)
+ {
+ Assert.Throws(exceptionType, () => Activator.CreateInstance(assemblyName: assemblyName, typeName: type));
+ }
+ else
+ {
+ oh = Activator.CreateInstance(assemblyName: assemblyName, typeName: type);
+ if (returnNull)
+ {
+ Assert.Null(oh);
+ }
+ else
+ {
+ CheckValidity(oh, returnedFullNameType);
+ }
+ }
+
+ if (exceptionType != null)
+ {
+ Assert.Throws(exceptionType, () => Activator.CreateInstance(assemblyName: assemblyName, typeName: type, null));
+ }
+ else
+ {
+ oh = Activator.CreateInstance(assemblyName: assemblyName, typeName: type, null);
+ if (returnNull)
+ {
+ Assert.Null(oh);
+ }
+ else
+ {
+ CheckValidity(oh, returnedFullNameType);
+ }
+ }
+ }
+
+ public static TheoryData<string, string, string, Type, bool> TestingCreateInstanceObjectHandleData => new TheoryData<string, string, string, Type, bool>()
+ {
+ // string assemblyName, string typeName, returnedFullNameType, expectedException
+ { "TestLoadAssembly", "PublicClassSample", "PublicClassSample", null, false },
+ { "testloadassembly", "publicclasssample", "PublicClassSample", typeof(TypeLoadException), false },
+
+ { "TestLoadAssembly", "PrivateClassSample", "PrivateClassSample", null, false },
+ { "testloadassembly", "privateclasssample", "PrivateClassSample", typeof(TypeLoadException), false },
+
+ { "TestLoadAssembly", "PublicClassNoDefaultConstructorSample", "PublicClassNoDefaultConstructorSample", typeof(MissingMethodException), false },
+ { "testloadassembly", "publicclassnodefaultconstructorsample", "PublicClassNoDefaultConstructorSample", typeof(TypeLoadException), false },
+
+ { "mscorlib", "System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", "", null, true }
+ };
+
+ [Theory]
+ [MemberData(nameof(TestingCreateInstanceFromObjectHandleFullSignatureData))]
+ public static void TestingCreateInstanceFromObjectHandleFullSignature(string physicalFileName, string assemblyFile, string type, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, string returnedFullNameType)
+ {
+ ObjectHandle oh = Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
+ CheckValidity(oh, returnedFullNameType);
+ Assert.True(File.Exists(physicalFileName));
+ }
+
+ public static IEnumerable<object[]> TestingCreateInstanceFromObjectHandleFullSignatureData()
+ {
+ // string physicalFileName, string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, returnedFullNameType
+ yield return new object[] { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PublicClassSample" };
+ yield return new object[] { "TestLoadAssembly.dll", "testloadassembly.dll", "publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PublicClassSample" };
+ yield return new object[] { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PublicClassSample" };
+ yield return new object[] { "TestLoadAssembly.dll", "testloadassembly.dll", "publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PublicClassSample" };
+
+ yield return new object[] { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PrivateClassSample" };
+ yield return new object[] { "TestLoadAssembly.dll", "testloadassembly.dll", "privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PrivateClassSample" };
+ yield return new object[] { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PrivateClassSample" };
+ yield return new object[] { "TestLoadAssembly.dll", "testloadassembly.dll", "privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PrivateClassSample" };
+ }
+
+ [Theory]
+ [MemberData(nameof(TestingCreateInstanceObjectHandleFullSignatureData))]
+ public static void TestingCreateInstanceObjectHandleFullSignature(string assemblyName, string type, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, string returnedFullNameType, bool returnNull)
+ {
+ ObjectHandle oh = Activator.CreateInstance(assemblyName: assemblyName, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
+ if (returnNull)
+ {
+ Assert.Null(oh);
+ }
+ else
+ {
+ CheckValidity(oh, returnedFullNameType);
+ }
+ }
+
+ public static IEnumerable<object[]> TestingCreateInstanceObjectHandleFullSignatureData()
+ {
+ // string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, returnedFullNameType
+ yield return new object[] { "TestLoadAssembly", "PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PublicClassSample" , false };
+ yield return new object[] { "testloadassembly", "publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PublicClassSample" , false };
+ yield return new object[] { "TestLoadAssembly", "PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PublicClassSample" , false };
+ yield return new object[] { "testloadassembly", "publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PublicClassSample" , false };
+
+ yield return new object[] { "TestLoadAssembly", "PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PrivateClassSample", false };
+ yield return new object[] { "testloadassembly", "privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PrivateClassSample", false };
+ yield return new object[] { "TestLoadAssembly", "PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PrivateClassSample", false };
+ yield return new object[] { "testloadassembly", "privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PrivateClassSample", false };
+
+ yield return new object[] { null, typeof(PublicType).FullName, false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, typeof(PublicType).FullName, false };
+ yield return new object[] { null, typeof(PrivateType).FullName, false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, typeof(PrivateType).FullName, false };
+
+ yield return new object[] { "mscorlib", "System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "", true };
+ yield return new object[] { "mscorlib", "SyStEm.NULLABLE`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "", true };
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsWinUISupported))]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ [MemberData(nameof(TestingCreateInstanceObjectHandleFullSignatureWinRTData))]
+ public static void TestingCreateInstanceObjectHandleFullSignatureWinRT(string assemblyName, string type, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, string returnedFullNameType)
+ {
+ ObjectHandle oh = Activator.CreateInstance(assemblyName: assemblyName, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
+ CheckValidity(oh, returnedFullNameType);
+ }
+
+ public static IEnumerable<object[]> TestingCreateInstanceObjectHandleFullSignatureWinRTData()
+ {
+ // string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, returnedFullNameType
+ yield return new object[] { "Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime", "Windows.Foundation.Collections.StringMap", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "Windows.Foundation.Collections.StringMap" };
+ }
+
+ private static void CheckValidity(ObjectHandle instance, string expected)
+ {
+ Assert.NotNull(instance);
+ Assert.Equal(expected, instance.Unwrap().GetType().FullName);
+ }
+
+ public class PublicType
+ {
+ public PublicType() { }
+ }
+
+ [Fact]
+ public static void CreateInstanceAssemblyResolve()
+ {
+ RemoteExecutor.Invoke(() =>
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs args) => Assembly.LoadFile(Path.Combine(Directory.GetCurrentDirectory(), "TestLoadAssembly.dll"));
+ Assert.Throws<FileLoadException>(() => Activator.CreateInstance(",,,,", "PublicClassSample"));
+ }).Dispose();
+ }
+
+ [Fact]
+ public void CreateInstance_TypeBuilder_ThrowsNotSupportedException()
+ {
+ AssemblyName assemblyName = new AssemblyName("Assembly");
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type", TypeAttributes.Public);
+
+ Assert.Throws<ArgumentException>("type", () => Activator.CreateInstance(typeBuilder));
+ Assert.Throws<NotSupportedException>(() => Activator.CreateInstance(typeBuilder, new object[0]));
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Runtime.Remoting;
-using Microsoft.DotNet.RemoteExecutor;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class ActivatorTests
- {
- [Fact]
- public void CreateInstance_NonPublicValueTypeWithPrivateDefaultConstructor_Success()
- {
- AssemblyName assemblyName = new AssemblyName("Assembly");
- AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
- ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
- TypeBuilder typeBuilder = moduleBuilder.DefineType("Type", TypeAttributes.Public, typeof(ValueType));
-
- FieldBuilder fieldBuilder = typeBuilder.DefineField("_field", typeof(int), FieldAttributes.Public);
- ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, CallingConventions.Standard, new Type[0]);
-
- ILGenerator generator = constructorBuilder.GetILGenerator();
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldc_I4, -1);
- generator.Emit(OpCodes.Stfld, fieldBuilder);
- generator.Emit(OpCodes.Ret);
-
- Type type = typeBuilder.CreateType();
- FieldInfo field = type.GetField("_field");
-
- // Activator holds a cache of constructors and the types to which they belong.
- // Test caching behaviour by activating multiple times.
- object v1 = Activator.CreateInstance(type, nonPublic: true);
- Assert.Equal(-1, field.GetValue(v1));
-
- object v2 = Activator.CreateInstance(type, nonPublic: true);
- Assert.Equal(-1, field.GetValue(v2));
- }
-
- [Fact]
- public void CreateInstance_PublicOnlyValueTypeWithPrivateDefaultConstructor_ThrowsMissingMethodException()
- {
- AssemblyName assemblyName = new AssemblyName("Assembly");
- AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
- ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
- TypeBuilder typeBuilder = moduleBuilder.DefineType("Type", TypeAttributes.Public, typeof(ValueType));
-
- FieldBuilder fieldBuilder = typeBuilder.DefineField("_field", typeof(int), FieldAttributes.Public);
- ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, CallingConventions.Standard, new Type[0]);
-
- ILGenerator generator = constructorBuilder.GetILGenerator();
- generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldc_I4, -1);
- generator.Emit(OpCodes.Stfld, fieldBuilder);
- generator.Emit(OpCodes.Ret);
-
- Type type = typeBuilder.CreateType();
-
- Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(type));
- Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(type, nonPublic: false));
-
- // Put the private default constructor into the cache and make sure we still throw if public only.
- Assert.NotNull(Activator.CreateInstance(type, nonPublic: true));
-
- Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(type));
- Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(type, nonPublic: false));
- }
-
- [Theory]
- [MemberData(nameof(TestingCreateInstanceFromObjectHandleData))]
- public static void TestingCreateInstanceFromObjectHandle(string physicalFileName, string assemblyFile, string type, string returnedFullNameType, Type exceptionType)
- {
- ObjectHandle oh = null;
-
- if (exceptionType != null)
- {
- Assert.Throws(exceptionType, () => Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type));
- }
- else
- {
- oh = Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type);
- CheckValidity(oh, returnedFullNameType);
- }
-
- if (exceptionType != null)
- {
- Assert.Throws(exceptionType, () => Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, null));
- }
- else
- {
- oh = Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, null);
- CheckValidity(oh, returnedFullNameType);
- }
- Assert.True(File.Exists(physicalFileName));
- }
-
- public static TheoryData<string, string, string, string, Type> TestingCreateInstanceFromObjectHandleData => new TheoryData<string, string, string, string, Type>()
- {
- // string physicalFileName, string assemblyFile, string typeName, returnedFullNameType, expectedException
- { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PublicClassSample", "PublicClassSample", null },
- { "TestLoadAssembly.dll", "testloadassembly.dll", "publicclasssample", "PublicClassSample", typeof(TypeLoadException) },
-
- { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PrivateClassSample", "PrivateClassSample", null },
- { "TestLoadAssembly.dll", "testloadassembly.dll", "privateclasssample", "PrivateClassSample", typeof(TypeLoadException) },
-
- { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PublicClassNoDefaultConstructorSample", "PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) },
- { "TestLoadAssembly.dll", "testloadassembly.dll", "publicclassnodefaultconstructorsample", "PublicClassNoDefaultConstructorSample", typeof(TypeLoadException) }
- };
-
- [Theory]
- [MemberData(nameof(TestingCreateInstanceObjectHandleData))]
- public static void TestingCreateInstanceObjectHandle(string assemblyName, string type, string returnedFullNameType, Type exceptionType, bool returnNull)
- {
- ObjectHandle oh = null;
-
- if (exceptionType != null)
- {
- Assert.Throws(exceptionType, () => Activator.CreateInstance(assemblyName: assemblyName, typeName: type));
- }
- else
- {
- oh = Activator.CreateInstance(assemblyName: assemblyName, typeName: type);
- if (returnNull)
- {
- Assert.Null(oh);
- }
- else
- {
- CheckValidity(oh, returnedFullNameType);
- }
- }
-
- if (exceptionType != null)
- {
- Assert.Throws(exceptionType, () => Activator.CreateInstance(assemblyName: assemblyName, typeName: type, null));
- }
- else
- {
- oh = Activator.CreateInstance(assemblyName: assemblyName, typeName: type, null);
- if (returnNull)
- {
- Assert.Null(oh);
- }
- else
- {
- CheckValidity(oh, returnedFullNameType);
- }
- }
- }
-
- public static TheoryData<string, string, string, Type, bool> TestingCreateInstanceObjectHandleData => new TheoryData<string, string, string, Type, bool>()
- {
- // string assemblyName, string typeName, returnedFullNameType, expectedException
- { "TestLoadAssembly", "PublicClassSample", "PublicClassSample", null, false },
- { "testloadassembly", "publicclasssample", "PublicClassSample", typeof(TypeLoadException), false },
-
- { "TestLoadAssembly", "PrivateClassSample", "PrivateClassSample", null, false },
- { "testloadassembly", "privateclasssample", "PrivateClassSample", typeof(TypeLoadException), false },
-
- { "TestLoadAssembly", "PublicClassNoDefaultConstructorSample", "PublicClassNoDefaultConstructorSample", typeof(MissingMethodException), false },
- { "testloadassembly", "publicclassnodefaultconstructorsample", "PublicClassNoDefaultConstructorSample", typeof(TypeLoadException), false },
-
- { "mscorlib", "System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", "", null, true }
- };
-
- [Theory]
- [MemberData(nameof(TestingCreateInstanceFromObjectHandleFullSignatureData))]
- public static void TestingCreateInstanceFromObjectHandleFullSignature(string physicalFileName, string assemblyFile, string type, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, string returnedFullNameType)
- {
- ObjectHandle oh = Activator.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
- CheckValidity(oh, returnedFullNameType);
- Assert.True(File.Exists(physicalFileName));
- }
-
- public static IEnumerable<object[]> TestingCreateInstanceFromObjectHandleFullSignatureData()
- {
- // string physicalFileName, string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, returnedFullNameType
- yield return new object[] { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PublicClassSample" };
- yield return new object[] { "TestLoadAssembly.dll", "testloadassembly.dll", "publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PublicClassSample" };
- yield return new object[] { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PublicClassSample" };
- yield return new object[] { "TestLoadAssembly.dll", "testloadassembly.dll", "publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PublicClassSample" };
-
- yield return new object[] { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PrivateClassSample" };
- yield return new object[] { "TestLoadAssembly.dll", "testloadassembly.dll", "privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PrivateClassSample" };
- yield return new object[] { "TestLoadAssembly.dll", "TestLoadAssembly.dll", "PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PrivateClassSample" };
- yield return new object[] { "TestLoadAssembly.dll", "testloadassembly.dll", "privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PrivateClassSample" };
- }
-
- [Theory]
- [MemberData(nameof(TestingCreateInstanceObjectHandleFullSignatureData))]
- public static void TestingCreateInstanceObjectHandleFullSignature(string assemblyName, string type, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, string returnedFullNameType, bool returnNull)
- {
- ObjectHandle oh = Activator.CreateInstance(assemblyName: assemblyName, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
- if (returnNull)
- {
- Assert.Null(oh);
- }
- else
- {
- CheckValidity(oh, returnedFullNameType);
- }
- }
-
- public static IEnumerable<object[]> TestingCreateInstanceObjectHandleFullSignatureData()
- {
- // string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, returnedFullNameType
- yield return new object[] { "TestLoadAssembly", "PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PublicClassSample" , false };
- yield return new object[] { "testloadassembly", "publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PublicClassSample" , false };
- yield return new object[] { "TestLoadAssembly", "PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PublicClassSample" , false };
- yield return new object[] { "testloadassembly", "publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PublicClassSample" , false };
-
- yield return new object[] { "TestLoadAssembly", "PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PrivateClassSample", false };
- yield return new object[] { "testloadassembly", "privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "PrivateClassSample", false };
- yield return new object[] { "TestLoadAssembly", "PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PrivateClassSample", false };
- yield return new object[] { "testloadassembly", "privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "PrivateClassSample", false };
-
- yield return new object[] { null, typeof(PublicType).FullName, false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, typeof(PublicType).FullName, false };
- yield return new object[] { null, typeof(PrivateType).FullName, false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, typeof(PrivateType).FullName, false };
-
- yield return new object[] { "mscorlib", "System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "", true };
- yield return new object[] { "mscorlib", "SyStEm.NULLABLE`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "", true };
- }
-
- [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsWinUISupported))]
- [PlatformSpecific(TestPlatforms.Windows)]
- [MemberData(nameof(TestingCreateInstanceObjectHandleFullSignatureWinRTData))]
- public static void TestingCreateInstanceObjectHandleFullSignatureWinRT(string assemblyName, string type, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, string returnedFullNameType)
- {
- ObjectHandle oh = Activator.CreateInstance(assemblyName: assemblyName, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
- CheckValidity(oh, returnedFullNameType);
- }
-
- public static IEnumerable<object[]> TestingCreateInstanceObjectHandleFullSignatureWinRTData()
- {
- // string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, returnedFullNameType
- yield return new object[] { "Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime", "Windows.Foundation.Collections.StringMap", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "Windows.Foundation.Collections.StringMap" };
- }
-
- private static void CheckValidity(ObjectHandle instance, string expected)
- {
- Assert.NotNull(instance);
- Assert.Equal(expected, instance.Unwrap().GetType().FullName);
- }
-
- public class PublicType
- {
- public PublicType() { }
- }
-
- [Fact]
- public static void CreateInstanceAssemblyResolve()
- {
- RemoteExecutor.Invoke(() =>
- {
- AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs args) => Assembly.LoadFile(Path.Combine(Directory.GetCurrentDirectory(), "TestLoadAssembly.dll"));
- Assert.Throws<FileLoadException>(() => Activator.CreateInstance(",,,,", "PublicClassSample"));
- }).Dispose();
- }
-
- [Fact]
- public void CreateInstance_TypeBuilder_ThrowsNotSupportedException()
- {
- AssemblyName assemblyName = new AssemblyName("Assembly");
- AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
- ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
- TypeBuilder typeBuilder = moduleBuilder.DefineType("Type", TypeAttributes.Public);
-
- Assert.Throws<ArgumentException>("type", () => Activator.CreateInstance(typeBuilder));
- Assert.Throws<NotSupportedException>(() => Activator.CreateInstance(typeBuilder, new object[0]));
- }
- }
-}
AssertExtensions.Throws<ArgumentException>(null, () => new ArraySegment<T>(new T[10], 10, 1)); // Offset + count > array.Length
AssertExtensions.Throws<ArgumentException>(null, () => new ArraySegment<T>(new T[10], 9, 2)); // Offset + count > array.Length
}
+
+ [Fact]
+ public void CopyTo_Default_ThrowsInvalidOperationException()
+ {
+ // Source is default
+ Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).CopyTo(new T[0]));
+ Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).CopyTo(new T[0], 0));
+ Assert.Throws<InvalidOperationException>(() => ((ICollection<T>)default(ArraySegment<T>)).CopyTo(new T[0], 0));
+ Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).CopyTo(new ArraySegment<T>(new T[0])));
+
+ // Destination is default
+ Assert.Throws<InvalidOperationException>(() => new ArraySegment<T>(new T[0]).CopyTo(default(ArraySegment<T>)));
+ }
+
+ [Fact]
+ public void Empty()
+ {
+ ArraySegment<T> empty = ArraySegment<T>.Empty;
+
+ // Assert.NotEqual uses its own Comparer, when it is comparing IEnumerables it calls GetEnumerator()
+ // ArraySegment<T>.GetEnumerator() throws InvalidOperationException when the array is null and default() returns null
+ Assert.True(default(ArraySegment<T>) != empty);
+
+ // Check that two Empty invocations return equal ArraySegments.
+ Assert.Equal(empty, ArraySegment<T>.Empty);
+
+ // Check that two Empty invocations return ArraySegments with a cached empty array.
+ // An empty array is necessary to ensure that someone doesn't use the indexer to store data in the array Empty refers to.
+ Assert.Same(empty.Array, ArraySegment<T>.Empty.Array);
+ Assert.Equal(0, empty.Array.Length);
+ Assert.Equal(0, empty.Offset);
+ Assert.Equal(0, empty.Count);
+ }
+
+ [Fact]
+ public void GetEnumerator_TypeProperties()
+ {
+ var arraySegment = new ArraySegment<T>(new T[1], 0, 1);
+ var ienumerableoft = (IEnumerable<T>)arraySegment;
+ var ienumerable = (IEnumerable)arraySegment;
+
+ ArraySegment<T>.Enumerator enumerator = arraySegment.GetEnumerator();
+ Assert.IsType<ArraySegment<T>.Enumerator>(enumerator);
+ Assert.IsAssignableFrom<IEnumerator<T>>(enumerator);
+ Assert.IsAssignableFrom<IEnumerator>(enumerator);
+
+ IEnumerator<T> ienumeratoroft = ienumerableoft.GetEnumerator();
+ IEnumerator ienumerator = ienumerable.GetEnumerator();
+
+ Assert.Equal(enumerator.GetType(), ienumeratoroft.GetType());
+ Assert.Equal(ienumeratoroft.GetType(), ienumerator.GetType());
+ }
+
+ [Fact]
+ public void GetEnumerator_Default_ThrowsInvalidOperationException()
+ {
+ Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).GetEnumerator());
+ }
+
+ [Fact]
+ public void Slice_Default_ThrowsInvalidOperationException()
+ {
+ Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).Slice(0));
+ Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).Slice(0, 0));
+ }
+
+ [Fact]
+ public void ToArray_Default_ThrowsInvalidOperationException()
+ {
+ Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).ToArray());
+ }
+
+ [Fact]
+ public void ToArray_Empty_ReturnsSameArray()
+ {
+ T[] cachedArray = ArraySegment<T>.Empty.ToArray();
+ Assert.Same(cachedArray, ArraySegment<T>.Empty.ToArray());
+ Assert.Same(cachedArray, new ArraySegment<T>(new T[0]).ToArray());
+ Assert.Same(cachedArray, new ArraySegment<T>(new T[1], 0, 0).ToArray());
+ }
+
+ [Fact]
+ public void ToArray_NonEmptyArray_DoesNotReturnSameArray()
+ {
+ // Prevent a faulty implementation like `if (Count == 0) { return Array; }`
+ var emptyArraySegment = new ArraySegment<T>(new T[1], 0, 0);
+ Assert.NotSame(emptyArraySegment.Array, emptyArraySegment.ToArray());
+ }
+
+ [Fact]
+ public void Cast_FromNullArray_ReturnsDefault()
+ {
+ ArraySegment<T> fromNull = null;
+ Assert.Null(fromNull.Array);
+ Assert.Equal(0, fromNull.Offset);
+ Assert.Equal(0, fromNull.Count);
+
+ Assert.True(default(ArraySegment<T>) == null);
+ Assert.True(new ArraySegment<T>(Array.Empty<T>()) != null);
+ }
+
+ [Fact]
+ public void Cast_FromValidArray_ReturnsSegmentForWholeArray()
+ {
+ var array = new T[42];
+ ArraySegment<T> fromArray = array;
+ Assert.Same(array, fromArray.Array);
+ Assert.Equal(0, fromArray.Offset);
+ Assert.Equal(42, fromArray.Count);
+ }
}
public class ArraySegment_Tests_string : ArraySegment_Tests<string>
(enumerator as IEnumerator<int>).Reset();
}
}
+
+ [Theory]
+ [MemberData(nameof(Conversion_FromArray_TestData))]
+ public static void Conversion_FromArray(int[] array)
+ {
+ ArraySegment<int> implicitlyConverted = array;
+ ArraySegment<int> explicitlyConverted = (ArraySegment<int>)array;
+
+ var expected = new ArraySegment<int>(array);
+ Assert.Equal(expected, implicitlyConverted);
+ Assert.Equal(expected, explicitlyConverted);
+ }
+
+ public static IEnumerable<object[]> Conversion_FromArray_TestData()
+ {
+ yield return new object[] { new int[0] };
+ yield return new object[] { new int[1] };
+ }
+
+ [Theory]
+ [MemberData(nameof(ArraySegment_TestData))]
+ public static void CopyTo(ArraySegment<int> arraySegment)
+ {
+ const int CopyPadding = 5;
+ const int DestinationSegmentPadding = 3;
+
+ int count = arraySegment.Count;
+
+ var destinationModel = new int[count + 2 * CopyPadding];
+
+ // CopyTo(T[])
+ CopyAndInvoke(destinationModel, destination =>
+ {
+ arraySegment.CopyTo(destination);
+
+ Assert.Equal(Enumerable.Repeat(default(int), 2 * CopyPadding), destination.Skip(count));
+
+ Assert.Equal(arraySegment, destination.Take(count));
+ });
+
+ // CopyTo(T[], int)
+ CopyAndInvoke(destinationModel, destination =>
+ {
+ arraySegment.CopyTo(destination, CopyPadding);
+
+ Assert.Equal(Enumerable.Repeat(default(int), CopyPadding), destination.Take(CopyPadding));
+ Assert.Equal(Enumerable.Repeat(default(int), CopyPadding), destination.Skip(CopyPadding + count));
+
+ Assert.Equal(arraySegment, destination.Skip(CopyPadding).Take(count));
+ });
+
+ // ICollection<T>.CopyTo(T[], int)
+ CopyAndInvoke(destinationModel, destination =>
+ {
+ ((ICollection<int>)arraySegment).CopyTo(destination, CopyPadding);
+
+ Assert.Equal(Enumerable.Repeat(default(int), CopyPadding), destination.Take(CopyPadding));
+ Assert.Equal(Enumerable.Repeat(default(int), CopyPadding), destination.Skip(CopyPadding + count));
+
+ Assert.Equal(arraySegment, destination.Skip(CopyPadding).Take(count));
+ });
+
+ // CopyTo(ArraySegment<T>)
+ CopyAndInvoke(destinationModel, destination =>
+ {
+ // We want to make sure this overload is handling edge cases correctly, like ArraySegments that
+ // do not begin at the array's start, do not end at the array's end, or have a bigger count than
+ // the source ArraySegment. Construct an ArraySegment that will test all of these conditions.
+ int destinationIndex = DestinationSegmentPadding;
+ int destinationCount = destination.Length - 2 * DestinationSegmentPadding;
+ var destinationSegment = new ArraySegment<int>(destination, destinationIndex, destinationCount);
+
+ arraySegment.CopyTo(destinationSegment);
+
+ Assert.Equal(Enumerable.Repeat(default(int), destinationIndex), destination.Take(destinationIndex));
+ int remainder = destination.Length - destinationIndex - count;
+ Assert.Equal(Enumerable.Repeat(default(int), remainder), destination.Skip(destinationIndex + count));
+
+ Assert.Equal(arraySegment, destination.Skip(destinationIndex).Take(count));
+ });
+ }
+
+ private static void CopyAndInvoke<T>(T[] array, Action<T[]> action) => action(array.ToArray());
+
+ [Theory]
+ [MemberData(nameof(ArraySegment_TestData))]
+ public static void CopyTo_Invalid(ArraySegment<int> arraySegment)
+ {
+ int count = arraySegment.Count;
+
+ // ArraySegment.CopyTo calls Array.Copy internally, so the exception parameter names come from there.
+
+ // Destination is null
+ AssertExtensions.Throws<ArgumentNullException>("destinationArray", () => arraySegment.CopyTo(null));
+ AssertExtensions.Throws<ArgumentNullException>("destinationArray", () => arraySegment.CopyTo(null, 0));
+
+ // Destination index not within range
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("destinationIndex", () => arraySegment.CopyTo(new int[0], -1));
+
+ // Destination array too small arraySegment.Count + destinationIndex > destinationArray.Length
+ AssertExtensions.Throws<ArgumentException>("destinationArray", () => arraySegment.CopyTo(new int[arraySegment.Count * 2], arraySegment.Count + 1));
+
+ if (arraySegment.Any())
+ {
+ // Destination not large enough
+ AssertExtensions.Throws<ArgumentException>("destinationArray", () => arraySegment.CopyTo(new int[count - 1]));
+ AssertExtensions.Throws<ArgumentException>("destinationArray", () => arraySegment.CopyTo(new int[count - 1], 0));
+ AssertExtensions.Throws<ArgumentException>("destination", null, () => arraySegment.CopyTo(new ArraySegment<int>(new int[count - 1])));
+
+ // Don't write beyond the limits of the destination in cases where source.Count > destination.Count
+ AssertExtensions.Throws<ArgumentException>("destination", null, () => arraySegment.CopyTo(new ArraySegment<int>(new int[count], 1, 0))); // destination.Array can't fit source at destination.Offset
+ AssertExtensions.Throws<ArgumentException>("destination", null, () => arraySegment.CopyTo(new ArraySegment<int>(new int[count], 0, count - 1))); // destination.Array can fit source at destination.Offset, but destination can't
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArraySegment_TestData))]
+ public static void GetEnumerator(ArraySegment<int> arraySegment)
+ {
+ int[] array = arraySegment.Array;
+ int index = arraySegment.Offset;
+ int count = arraySegment.Count;
+
+ ArraySegment<int>.Enumerator enumerator = arraySegment.GetEnumerator();
+
+ var actual = new List<int>();
+
+ while (enumerator.MoveNext())
+ {
+ actual.Add(enumerator.Current);
+ }
+
+ // After MoveNext returns false once, it should return false the second time.
+ Assert.False(enumerator.MoveNext());
+
+ IEnumerable<int> expected = array.Skip(index).Take(count);
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory]
+ [MemberData(nameof(ArraySegment_TestData))]
+ public static void GetEnumerator_Dispose(ArraySegment<int> arraySegment)
+ {
+ int[] array = arraySegment.Array;
+ int index = arraySegment.Offset;
+
+ ArraySegment<int>.Enumerator enumerator = arraySegment.GetEnumerator();
+
+ bool expected = arraySegment.Count > 0;
+
+ // Dispose shouldn't do anything. Call it twice and then assert like nothing happened.
+ enumerator.Dispose();
+ enumerator.Dispose();
+
+ Assert.Equal(expected, enumerator.MoveNext());
+ if (expected)
+ {
+ Assert.Equal(array[index], enumerator.Current);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArraySegment_TestData))]
+ public static void GetEnumerator_Reset(ArraySegment<int> arraySegment)
+ {
+ int[] array = arraySegment.Array;
+ int index = arraySegment.Offset;
+ int count = arraySegment.Count;
+
+ var enumerator = (IEnumerator<int>)arraySegment.GetEnumerator();
+
+ int[] expected = array.Skip(index).Take(count).ToArray();
+
+ // Reset at a variety of different positions to ensure the implementation
+ // isn't something like `position -= CONSTANT`.
+ for (int i = 0; i < 3; i++)
+ {
+ for (int j = 0; j < i; j++)
+ {
+ if (enumerator.MoveNext())
+ {
+ Assert.Equal(expected[j], enumerator.Current);
+ }
+ }
+
+ enumerator.Reset();
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArraySegment_TestData))]
+ public static void GetEnumerator_Invalid(ArraySegment<int> arraySegment)
+ {
+ ArraySegment<int>.Enumerator enumerator = arraySegment.GetEnumerator();
+
+ // Before beginning
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current);
+ Assert.Throws<InvalidOperationException>(() => ((IEnumerator<int>)enumerator).Current);
+ Assert.Throws<InvalidOperationException>(() => ((IEnumerator)enumerator).Current);
+
+ while (enumerator.MoveNext()) ;
+
+ // After end
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current);
+ Assert.Throws<InvalidOperationException>(() => ((IEnumerator<int>)enumerator).Current);
+ Assert.Throws<InvalidOperationException>(() => ((IEnumerator)enumerator).Current);
+ }
+
+ [Theory]
+ [MemberData(nameof(ArraySegment_TestData))]
+ public static void GetSetItem_InRange(ArraySegment<int> arraySegment)
+ {
+ int[] array = arraySegment.Array;
+ int index = arraySegment.Offset;
+ int count = arraySegment.Count;
+
+ int[] expected = array.Skip(index).Take(count).ToArray();
+
+ for (int i = 0; i < count; i++)
+ {
+ Assert.Equal(expected[i], arraySegment[i]);
+ Assert.Equal(expected[i], ((IList<int>)arraySegment)[i]);
+ Assert.Equal(expected[i], ((IReadOnlyList<int>)arraySegment)[i]);
+ }
+
+ var r = new Random(0);
+
+ for (int i = 0; i < count; i++)
+ {
+ int next = r.Next(int.MinValue, int.MaxValue);
+
+ // When we modify the underlying array, the indexer should return the updated values.
+ array[arraySegment.Offset + i] ^= next;
+ Assert.Equal(expected[i] ^ next, arraySegment[i]);
+
+ // When the indexer's set method is called, the underlying array should be modified.
+ arraySegment[i] ^= next;
+ Assert.Equal(expected[i], array[arraySegment.Offset + i]);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ArraySegment_TestData))]
+ public static void GetSetItem_NotInRange_Invalid(ArraySegment<int> arraySegment)
+ {
+ int[] array = arraySegment.Array;
+
+ // Before array start
+ Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-arraySegment.Offset - 1]);
+ Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-arraySegment.Offset - 1] = default(int));
+
+ // After array start (if Offset > 0), before start
+ Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-1]);
+ Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-1] = default(int));
+
+ // Before array end (if Offset + Count < Array.Length), after end
+ Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[arraySegment.Count]);
+ Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[arraySegment.Count] = default(int));
+
+ // After array end
+ Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-arraySegment.Offset + array.Length]);
+ Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-arraySegment.Offset + array.Length] = default(int));
+ }
+
+ [Theory]
+ [MemberData(nameof(Slice_TestData))]
+ public static void Slice(ArraySegment<int> arraySegment, int index, int count)
+ {
+ var expected = new ArraySegment<int>(arraySegment.Array, arraySegment.Offset + index, count);
+
+ if (index + count == arraySegment.Count)
+ {
+ Assert.Equal(expected, arraySegment.Slice(index));
+ }
+
+ Assert.Equal(expected, arraySegment.Slice(index, count));
+ }
+
+ public static IEnumerable<object[]> Slice_TestData()
+ {
+ IEnumerable<ArraySegment<int>> arraySegments = ArraySegment_TestData().Select(array => array.Single()).Cast<ArraySegment<int>>();
+
+ foreach (ArraySegment<int> arraySegment in arraySegments)
+ {
+ yield return new object[] { arraySegment, 0, 0 }; // Preserve start, no items
+ yield return new object[] { arraySegment, 0, arraySegment.Count }; // Preserve start, preserve count (noop)
+ yield return new object[] { arraySegment, arraySegment.Count, 0 }; // Start at end, no items
+
+ if (arraySegment.Any())
+ {
+ yield return new object[] { arraySegment, 1, 0 }; // Start at middle or end, no items
+ yield return new object[] { arraySegment, 1, arraySegment.Count - 1 }; // Start at middle or end, rest of items
+ yield return new object[] { arraySegment, arraySegment.Count - 1, 1 }; // Preserve start or start at middle, one item
+ }
+
+ yield return new object[] { arraySegment, 0, arraySegment.Count / 2 }; // Preserve start, multiple items, end at middle
+ yield return new object[] { arraySegment, arraySegment.Count / 2, arraySegment.Count / 2 }; // Start at middle, multiple items, end at middle (due to integer division truncation) or preserve end
+ yield return new object[] { arraySegment, arraySegment.Count / 4, arraySegment.Count / 2 }; // Start at middle, multiple items, end at middle
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(Slice_Invalid_TestData))]
+ public static void Slice_Invalid(ArraySegment<int> arraySegment, int index, int count)
+ {
+ if (index + count == arraySegment.Count)
+ {
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => arraySegment.Slice(index));
+ }
+
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => arraySegment.Slice(index, count));
+ }
+
+ public static IEnumerable<object[]> Slice_Invalid_TestData()
+ {
+ var arraySegment = new ArraySegment<int>(new int[3], offset: 1, count: 1);
+
+ yield return new object[] { arraySegment, -arraySegment.Offset, arraySegment.Offset };
+ yield return new object[] { arraySegment, -arraySegment.Offset, arraySegment.Offset + arraySegment.Count };
+ yield return new object[] { arraySegment, -arraySegment.Offset, arraySegment.Array.Length };
+ yield return new object[] { arraySegment, 0, arraySegment.Array.Length - arraySegment.Offset };
+ yield return new object[] { arraySegment, arraySegment.Count, arraySegment.Array.Length - arraySegment.Offset - arraySegment.Count };
+ }
+
+ [Theory]
+ [MemberData(nameof(ArraySegment_TestData))]
+ public static void ToArray(ArraySegment<int> arraySegment)
+ {
+ // ToList is called here so we copy the data and raise an assert if ToArray modifies the underlying array.
+ List<int> expected = arraySegment.Array.Skip(arraySegment.Offset).Take(arraySegment.Count).ToList();
+ Assert.Equal(expected, arraySegment.ToArray());
+ }
+
+ public static IEnumerable<object[]> ArraySegment_TestData()
+ {
+ var arraySegments = new (int[] array, int index, int count)[]
+ {
+ (array: new int[0], index: 0, 0), // Empty array
+ (array: new[] { 3, 4, 5, 6 }, index: 0, count: 4), // Full span of non-empty array
+ (array: new[] { 3, 4, 5, 6 }, index: 0, count: 3), // Starts at beginning, ends in middle
+ (array: new[] { 3, 4, 5, 6 }, index: 1, count: 3), // Starts in middle, ends at end
+ (array: new[] { 3, 4, 5, 6 }, index: 1, count: 2), // Starts in middle, ends in middle
+ (array: new[] { 3, 4, 5, 6 }, index: 1, count: 0) // Non-empty array, count == 0
+ };
+
+ return arraySegments.Select(aseg => new object[] { new ArraySegment<int>(aseg.array, aseg.index, aseg.count) });
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using Xunit;
-
-namespace System.Tests
-{
- public abstract partial class ArraySegment_Tests<T>
- {
- [Fact]
- public void CopyTo_Default_ThrowsInvalidOperationException()
- {
- // Source is default
- Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).CopyTo(new T[0]));
- Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).CopyTo(new T[0], 0));
- Assert.Throws<InvalidOperationException>(() => ((ICollection<T>)default(ArraySegment<T>)).CopyTo(new T[0], 0));
- Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).CopyTo(new ArraySegment<T>(new T[0])));
-
- // Destination is default
- Assert.Throws<InvalidOperationException>(() => new ArraySegment<T>(new T[0]).CopyTo(default(ArraySegment<T>)));
- }
-
- [Fact]
- public void Empty()
- {
- ArraySegment<T> empty = ArraySegment<T>.Empty;
-
- // Assert.NotEqual uses its own Comparer, when it is comparing IEnumerables it calls GetEnumerator()
- // ArraySegment<T>.GetEnumerator() throws InvalidOperationException when the array is null and default() returns null
- Assert.True(default(ArraySegment<T>) != empty);
-
- // Check that two Empty invocations return equal ArraySegments.
- Assert.Equal(empty, ArraySegment<T>.Empty);
-
- // Check that two Empty invocations return ArraySegments with a cached empty array.
- // An empty array is necessary to ensure that someone doesn't use the indexer to store data in the array Empty refers to.
- Assert.Same(empty.Array, ArraySegment<T>.Empty.Array);
- Assert.Equal(0, empty.Array.Length);
- Assert.Equal(0, empty.Offset);
- Assert.Equal(0, empty.Count);
- }
-
- [Fact]
- public void GetEnumerator_TypeProperties()
- {
- var arraySegment = new ArraySegment<T>(new T[1], 0, 1);
- var ienumerableoft = (IEnumerable<T>)arraySegment;
- var ienumerable = (IEnumerable)arraySegment;
-
- ArraySegment<T>.Enumerator enumerator = arraySegment.GetEnumerator();
- Assert.IsType<ArraySegment<T>.Enumerator>(enumerator);
- Assert.IsAssignableFrom<IEnumerator<T>>(enumerator);
- Assert.IsAssignableFrom<IEnumerator>(enumerator);
-
- IEnumerator<T> ienumeratoroft = ienumerableoft.GetEnumerator();
- IEnumerator ienumerator = ienumerable.GetEnumerator();
-
- Assert.Equal(enumerator.GetType(), ienumeratoroft.GetType());
- Assert.Equal(ienumeratoroft.GetType(), ienumerator.GetType());
- }
-
- [Fact]
- public void GetEnumerator_Default_ThrowsInvalidOperationException()
- {
- Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).GetEnumerator());
- }
-
- [Fact]
- public void Slice_Default_ThrowsInvalidOperationException()
- {
- Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).Slice(0));
- Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).Slice(0, 0));
- }
-
- [Fact]
- public void ToArray_Default_ThrowsInvalidOperationException()
- {
- Assert.Throws<InvalidOperationException>(() => default(ArraySegment<T>).ToArray());
- }
-
- [Fact]
- public void ToArray_Empty_ReturnsSameArray()
- {
- T[] cachedArray = ArraySegment<T>.Empty.ToArray();
- Assert.Same(cachedArray, ArraySegment<T>.Empty.ToArray());
- Assert.Same(cachedArray, new ArraySegment<T>(new T[0]).ToArray());
- Assert.Same(cachedArray, new ArraySegment<T>(new T[1], 0, 0).ToArray());
- }
-
- [Fact]
- public void ToArray_NonEmptyArray_DoesNotReturnSameArray()
- {
- // Prevent a faulty implementation like `if (Count == 0) { return Array; }`
- var emptyArraySegment = new ArraySegment<T>(new T[1], 0, 0);
- Assert.NotSame(emptyArraySegment.Array, emptyArraySegment.ToArray());
- }
-
- [Fact]
- public void Cast_FromNullArray_ReturnsDefault()
- {
- ArraySegment<T> fromNull = null;
- Assert.Null(fromNull.Array);
- Assert.Equal(0, fromNull.Offset);
- Assert.Equal(0, fromNull.Count);
-
- Assert.True(default(ArraySegment<T>) == null);
- Assert.True(new ArraySegment<T>(Array.Empty<T>()) != null);
- }
-
- [Fact]
- public void Cast_FromValidArray_ReturnsSegmentForWholeArray()
- {
- var array = new T[42];
- ArraySegment<T> fromArray = array;
- Assert.Same(array, fromArray.Array);
- Assert.Equal(0, fromArray.Offset);
- Assert.Equal(42, fromArray.Count);
- }
- }
-
- public static partial class ArraySegment_Tests
- {
- [Theory]
- [MemberData(nameof(Conversion_FromArray_TestData))]
- public static void Conversion_FromArray(int[] array)
- {
- ArraySegment<int> implicitlyConverted = array;
- ArraySegment<int> explicitlyConverted = (ArraySegment<int>)array;
-
- var expected = new ArraySegment<int>(array);
- Assert.Equal(expected, implicitlyConverted);
- Assert.Equal(expected, explicitlyConverted);
- }
-
- public static IEnumerable<object[]> Conversion_FromArray_TestData()
- {
- yield return new object[] { new int[0] };
- yield return new object[] { new int[1] };
- }
-
- [Theory]
- [MemberData(nameof(ArraySegment_TestData))]
- public static void CopyTo(ArraySegment<int> arraySegment)
- {
- const int CopyPadding = 5;
- const int DestinationSegmentPadding = 3;
-
- int count = arraySegment.Count;
-
- var destinationModel = new int[count + 2 * CopyPadding];
-
- // CopyTo(T[])
- CopyAndInvoke(destinationModel, destination =>
- {
- arraySegment.CopyTo(destination);
-
- Assert.Equal(Enumerable.Repeat(default(int), 2 * CopyPadding), destination.Skip(count));
-
- Assert.Equal(arraySegment, destination.Take(count));
- });
-
- // CopyTo(T[], int)
- CopyAndInvoke(destinationModel, destination =>
- {
- arraySegment.CopyTo(destination, CopyPadding);
-
- Assert.Equal(Enumerable.Repeat(default(int), CopyPadding), destination.Take(CopyPadding));
- Assert.Equal(Enumerable.Repeat(default(int), CopyPadding), destination.Skip(CopyPadding + count));
-
- Assert.Equal(arraySegment, destination.Skip(CopyPadding).Take(count));
- });
-
- // ICollection<T>.CopyTo(T[], int)
- CopyAndInvoke(destinationModel, destination =>
- {
- ((ICollection<int>)arraySegment).CopyTo(destination, CopyPadding);
-
- Assert.Equal(Enumerable.Repeat(default(int), CopyPadding), destination.Take(CopyPadding));
- Assert.Equal(Enumerable.Repeat(default(int), CopyPadding), destination.Skip(CopyPadding + count));
-
- Assert.Equal(arraySegment, destination.Skip(CopyPadding).Take(count));
- });
-
- // CopyTo(ArraySegment<T>)
- CopyAndInvoke(destinationModel, destination =>
- {
- // We want to make sure this overload is handling edge cases correctly, like ArraySegments that
- // do not begin at the array's start, do not end at the array's end, or have a bigger count than
- // the source ArraySegment. Construct an ArraySegment that will test all of these conditions.
- int destinationIndex = DestinationSegmentPadding;
- int destinationCount = destination.Length - 2 * DestinationSegmentPadding;
- var destinationSegment = new ArraySegment<int>(destination, destinationIndex, destinationCount);
-
- arraySegment.CopyTo(destinationSegment);
-
- Assert.Equal(Enumerable.Repeat(default(int), destinationIndex), destination.Take(destinationIndex));
- int remainder = destination.Length - destinationIndex - count;
- Assert.Equal(Enumerable.Repeat(default(int), remainder), destination.Skip(destinationIndex + count));
-
- Assert.Equal(arraySegment, destination.Skip(destinationIndex).Take(count));
- });
- }
-
- private static void CopyAndInvoke<T>(T[] array, Action<T[]> action) => action(array.ToArray());
-
- [Theory]
- [MemberData(nameof(ArraySegment_TestData))]
- public static void CopyTo_Invalid(ArraySegment<int> arraySegment)
- {
- int count = arraySegment.Count;
-
- // ArraySegment.CopyTo calls Array.Copy internally, so the exception parameter names come from there.
-
- // Destination is null
- AssertExtensions.Throws<ArgumentNullException>("destinationArray", () => arraySegment.CopyTo(null));
- AssertExtensions.Throws<ArgumentNullException>("destinationArray", () => arraySegment.CopyTo(null, 0));
-
- // Destination index not within range
- AssertExtensions.Throws<ArgumentOutOfRangeException>("destinationIndex", () => arraySegment.CopyTo(new int[0], -1));
-
- // Destination array too small arraySegment.Count + destinationIndex > destinationArray.Length
- AssertExtensions.Throws<ArgumentException>("destinationArray", () => arraySegment.CopyTo(new int[arraySegment.Count * 2], arraySegment.Count + 1));
-
- if (arraySegment.Any())
- {
- // Destination not large enough
- AssertExtensions.Throws<ArgumentException>("destinationArray", () => arraySegment.CopyTo(new int[count - 1]));
- AssertExtensions.Throws<ArgumentException>("destinationArray", () => arraySegment.CopyTo(new int[count - 1], 0));
- AssertExtensions.Throws<ArgumentException>("destination", null, () => arraySegment.CopyTo(new ArraySegment<int>(new int[count - 1])));
-
- // Don't write beyond the limits of the destination in cases where source.Count > destination.Count
- AssertExtensions.Throws<ArgumentException>("destination", null, () => arraySegment.CopyTo(new ArraySegment<int>(new int[count], 1, 0))); // destination.Array can't fit source at destination.Offset
- AssertExtensions.Throws<ArgumentException>("destination", null, () => arraySegment.CopyTo(new ArraySegment<int>(new int[count], 0, count - 1))); // destination.Array can fit source at destination.Offset, but destination can't
- }
- }
-
- [Theory]
- [MemberData(nameof(ArraySegment_TestData))]
- public static void GetEnumerator(ArraySegment<int> arraySegment)
- {
- int[] array = arraySegment.Array;
- int index = arraySegment.Offset;
- int count = arraySegment.Count;
-
- ArraySegment<int>.Enumerator enumerator = arraySegment.GetEnumerator();
-
- var actual = new List<int>();
-
- while (enumerator.MoveNext())
- {
- actual.Add(enumerator.Current);
- }
-
- // After MoveNext returns false once, it should return false the second time.
- Assert.False(enumerator.MoveNext());
-
- IEnumerable<int> expected = array.Skip(index).Take(count);
- Assert.Equal(expected, actual);
- }
-
- [Theory]
- [MemberData(nameof(ArraySegment_TestData))]
- public static void GetEnumerator_Dispose(ArraySegment<int> arraySegment)
- {
- int[] array = arraySegment.Array;
- int index = arraySegment.Offset;
-
- ArraySegment<int>.Enumerator enumerator = arraySegment.GetEnumerator();
-
- bool expected = arraySegment.Count > 0;
-
- // Dispose shouldn't do anything. Call it twice and then assert like nothing happened.
- enumerator.Dispose();
- enumerator.Dispose();
-
- Assert.Equal(expected, enumerator.MoveNext());
- if (expected)
- {
- Assert.Equal(array[index], enumerator.Current);
- }
- }
-
- [Theory]
- [MemberData(nameof(ArraySegment_TestData))]
- public static void GetEnumerator_Reset(ArraySegment<int> arraySegment)
- {
- int[] array = arraySegment.Array;
- int index = arraySegment.Offset;
- int count = arraySegment.Count;
-
- var enumerator = (IEnumerator<int>)arraySegment.GetEnumerator();
-
- int[] expected = array.Skip(index).Take(count).ToArray();
-
- // Reset at a variety of different positions to ensure the implementation
- // isn't something like `position -= CONSTANT`.
- for (int i = 0; i < 3; i++)
- {
- for (int j = 0; j < i; j++)
- {
- if (enumerator.MoveNext())
- {
- Assert.Equal(expected[j], enumerator.Current);
- }
- }
-
- enumerator.Reset();
- }
- }
-
- [Theory]
- [MemberData(nameof(ArraySegment_TestData))]
- public static void GetEnumerator_Invalid(ArraySegment<int> arraySegment)
- {
- ArraySegment<int>.Enumerator enumerator = arraySegment.GetEnumerator();
-
- // Before beginning
- Assert.Throws<InvalidOperationException>(() => enumerator.Current);
- Assert.Throws<InvalidOperationException>(() => ((IEnumerator<int>)enumerator).Current);
- Assert.Throws<InvalidOperationException>(() => ((IEnumerator)enumerator).Current);
-
- while (enumerator.MoveNext()) ;
-
- // After end
- Assert.Throws<InvalidOperationException>(() => enumerator.Current);
- Assert.Throws<InvalidOperationException>(() => ((IEnumerator<int>)enumerator).Current);
- Assert.Throws<InvalidOperationException>(() => ((IEnumerator)enumerator).Current);
- }
-
- [Theory]
- [MemberData(nameof(ArraySegment_TestData))]
- public static void GetSetItem_InRange(ArraySegment<int> arraySegment)
- {
- int[] array = arraySegment.Array;
- int index = arraySegment.Offset;
- int count = arraySegment.Count;
-
- int[] expected = array.Skip(index).Take(count).ToArray();
-
- for (int i = 0; i < count; i++)
- {
- Assert.Equal(expected[i], arraySegment[i]);
- Assert.Equal(expected[i], ((IList<int>)arraySegment)[i]);
- Assert.Equal(expected[i], ((IReadOnlyList<int>)arraySegment)[i]);
- }
-
- var r = new Random(0);
-
- for (int i = 0; i < count; i++)
- {
- int next = r.Next(int.MinValue, int.MaxValue);
-
- // When we modify the underlying array, the indexer should return the updated values.
- array[arraySegment.Offset + i] ^= next;
- Assert.Equal(expected[i] ^ next, arraySegment[i]);
-
- // When the indexer's set method is called, the underlying array should be modified.
- arraySegment[i] ^= next;
- Assert.Equal(expected[i], array[arraySegment.Offset + i]);
- }
- }
-
- [Theory]
- [MemberData(nameof(ArraySegment_TestData))]
- public static void GetSetItem_NotInRange_Invalid(ArraySegment<int> arraySegment)
- {
- int[] array = arraySegment.Array;
-
- // Before array start
- Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-arraySegment.Offset - 1]);
- Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-arraySegment.Offset - 1] = default(int));
-
- // After array start (if Offset > 0), before start
- Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-1]);
- Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-1] = default(int));
-
- // Before array end (if Offset + Count < Array.Length), after end
- Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[arraySegment.Count]);
- Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[arraySegment.Count] = default(int));
-
- // After array end
- Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-arraySegment.Offset + array.Length]);
- Assert.Throws<ArgumentOutOfRangeException>(() => arraySegment[-arraySegment.Offset + array.Length] = default(int));
- }
-
- [Theory]
- [MemberData(nameof(Slice_TestData))]
- public static void Slice(ArraySegment<int> arraySegment, int index, int count)
- {
- var expected = new ArraySegment<int>(arraySegment.Array, arraySegment.Offset + index, count);
-
- if (index + count == arraySegment.Count)
- {
- Assert.Equal(expected, arraySegment.Slice(index));
- }
-
- Assert.Equal(expected, arraySegment.Slice(index, count));
- }
-
- public static IEnumerable<object[]> Slice_TestData()
- {
- IEnumerable<ArraySegment<int>> arraySegments = ArraySegment_TestData().Select(array => array.Single()).Cast<ArraySegment<int>>();
-
- foreach (ArraySegment<int> arraySegment in arraySegments)
- {
- yield return new object[] { arraySegment, 0, 0 }; // Preserve start, no items
- yield return new object[] { arraySegment, 0, arraySegment.Count }; // Preserve start, preserve count (noop)
- yield return new object[] { arraySegment, arraySegment.Count, 0 }; // Start at end, no items
-
- if (arraySegment.Any())
- {
- yield return new object[] { arraySegment, 1, 0 }; // Start at middle or end, no items
- yield return new object[] { arraySegment, 1, arraySegment.Count - 1 }; // Start at middle or end, rest of items
- yield return new object[] { arraySegment, arraySegment.Count - 1, 1 }; // Preserve start or start at middle, one item
- }
-
- yield return new object[] { arraySegment, 0, arraySegment.Count / 2 }; // Preserve start, multiple items, end at middle
- yield return new object[] { arraySegment, arraySegment.Count / 2, arraySegment.Count / 2 }; // Start at middle, multiple items, end at middle (due to integer division truncation) or preserve end
- yield return new object[] { arraySegment, arraySegment.Count / 4, arraySegment.Count / 2 }; // Start at middle, multiple items, end at middle
- }
- }
-
- [Theory]
- [MemberData(nameof(Slice_Invalid_TestData))]
- public static void Slice_Invalid(ArraySegment<int> arraySegment, int index, int count)
- {
- if (index + count == arraySegment.Count)
- {
- AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => arraySegment.Slice(index));
- }
-
- AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => arraySegment.Slice(index, count));
- }
-
- public static IEnumerable<object[]> Slice_Invalid_TestData()
- {
- var arraySegment = new ArraySegment<int>(new int[3], offset: 1, count: 1);
-
- yield return new object[] { arraySegment, -arraySegment.Offset, arraySegment.Offset };
- yield return new object[] { arraySegment, -arraySegment.Offset, arraySegment.Offset + arraySegment.Count };
- yield return new object[] { arraySegment, -arraySegment.Offset, arraySegment.Array.Length };
- yield return new object[] { arraySegment, 0, arraySegment.Array.Length - arraySegment.Offset };
- yield return new object[] { arraySegment, arraySegment.Count, arraySegment.Array.Length - arraySegment.Offset - arraySegment.Count };
- }
-
- [Theory]
- [MemberData(nameof(ArraySegment_TestData))]
- public static void ToArray(ArraySegment<int> arraySegment)
- {
- // ToList is called here so we copy the data and raise an assert if ToArray modifies the underlying array.
- List<int> expected = arraySegment.Array.Skip(arraySegment.Offset).Take(arraySegment.Count).ToList();
- Assert.Equal(expected, arraySegment.ToArray());
- }
-
- public static IEnumerable<object[]> ArraySegment_TestData()
- {
- var arraySegments = new (int[] array, int index, int count)[]
- {
- (array: new int[0], index: 0, 0), // Empty array
- (array: new[] { 3, 4, 5, 6 }, index: 0, count: 4), // Full span of non-empty array
- (array: new[] { 3, 4, 5, 6 }, index: 0, count: 3), // Starts at beginning, ends in middle
- (array: new[] { 3, 4, 5, 6 }, index: 1, count: 3), // Starts in middle, ends at end
- (array: new[] { 3, 4, 5, 6 }, index: 1, count: 2), // Starts in middle, ends in middle
- (array: new[] { 3, 4, 5, 6 }, index: 1, count: 0) // Non-empty array, count == 0
- };
-
- return arraySegments.Select(aseg => new object[] { new ArraySegment<int>(aseg.array, aseg.index, aseg.count) });
- }
- }
-}
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
+using System.Runtime.CompilerServices;
using Xunit;
namespace System.Tests
{
- public partial class ArrayTests
+ public class ArrayTests
{
[Fact]
public static void IList_GetSetItem()
Array.Reverse((Array)new int*[1]);
}
+ public static IEnumerable<object[]> Fill_Generic_TestData()
+ {
+ var data = Enumerable.Empty<object[]>();
+
+ var r = new Random(0x051778f7);
+ int[] lengths = { 0, 1, 2, 3, 5, 8, 13 };
+
+ foreach (int length in lengths)
+ {
+ IEnumerable<int> source = Enumerable.Range(1, length).Select(_ => r.Next());
+
+ data = data.Concat(GenerateFillData(source, r.Next(), i => i))
+ .Concat(GenerateFillData(source, r.Next(), i => unchecked((byte)i)))
+ .Concat(GenerateFillData(source, r.Next(), i => unchecked((short)i)))
+ .Concat(GenerateFillData(source, r.Next(), i => (long)i))
+ .Concat(GenerateFillData(source, r.Next(), i => new StrongBox<int>(i)))
+ .Concat(GenerateFillData(source, r.Next(), i => i.ToString()))
+ .Concat(GenerateFillData(source, r.Next(), i => unchecked((ByteEnum)i)))
+ .Concat(GenerateFillData(source, r.Next(), i => unchecked((Int16Enum)i)))
+ .Concat(GenerateFillData(source, r.Next(), i => (Int32Enum)i))
+ .Concat(GenerateFillData(source, r.Next(), i => (Int64Enum)i))
+ .Concat(GenerateFillData(source, r.Next(), i => new object()));
+ }
+
+ return data;
+ }
+
+ public static IEnumerable<object[]> GenerateFillData<TSource, TResult>(IEnumerable<TSource> source, TSource seed, Func<TSource, TResult> transform)
+ {
+ int count = source.Count();
+ TResult repeatedValue = transform(seed);
+ // Force evaluation so neither `source` or `transform` are re-run if the sequence is enumerated more than once.
+ IEnumerable<TResult> transformed = source.Select(transform).ToList();
+
+ yield return new object[] { transformed, repeatedValue, 0, count }; // Fill the entire array.
+ yield return new object[] { transformed, repeatedValue, 0, count / 2 }; // Fill the beginning of the array.
+ yield return new object[] { transformed, repeatedValue, count / 2, count / 2 }; // Fill the end of the array, assuming `length` is even.
+ yield return new object[] { transformed, repeatedValue, count / 4, count / 2 }; // Fill the middle of the array.
+ yield return new object[] { transformed, repeatedValue, count, 0 }; // Fill nothing.
+ }
+
+ [Theory]
+ [MemberData(nameof(Fill_Generic_TestData))]
+ public static void Fill_Generic<T>(IEnumerable<T> source, T value, int startIndex, int count)
+ {
+ if (startIndex == 0 && count == source.Count())
+ {
+ T[] array = source.ToArray();
+ Array.Fill(array, value);
+ Assert.Equal(Enumerable.Repeat(value, count), array);
+ }
+
+ {
+ T[] array = source.ToArray();
+
+ // Before calling Fill, we want to capture the segments before/after the filled region.
+ // We want to ensure that in addition to filling in what it's supposed to, Fill does
+ // not touch the adjacent segments.
+ T[] before = source.Take(startIndex).ToArray();
+ T[] after = source.Skip(startIndex + count).ToArray();
+
+ Array.Fill(array, value, startIndex, count);
+
+ Assert.Equal(before, array.Take(startIndex));
+ Assert.Equal(Enumerable.Repeat(value, count), array.Skip(startIndex).Take(count));
+ Assert.Equal(after, array.Skip(startIndex + count));
+ }
+ }
+
+ [Fact]
+ public void Fill_NullArray_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("array", () => Array.Fill(null, 1));
+ AssertExtensions.Throws<ArgumentNullException>("array", () => Array.Fill(null, 1, 0, 0));
+ }
+
+ [Theory]
+ [InlineData(-1)]
+ [InlineData(2)]
+ public void Fill_InvalidStartIndex_ThrowsArgumentOutOfRangeException(int startIndex)
+ {
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => Array.Fill(new string[1], "", startIndex, 0));
+ }
+
+ [Theory]
+ [InlineData(1, 0, -1)]
+ [InlineData(0, 0, 1)]
+ [InlineData(3, 3, 1)]
+ [InlineData(3, 2, 2)]
+ [InlineData(3, 1, 3)]
+ [InlineData(3, 0, 4)]
+ public void Fill_InvalidStartIndexCount_ThrowsArgumentOutOfRangeException(int arrayLength, int startIndex, int count)
+ {
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => Array.Fill(new string[arrayLength], "", startIndex, count));
+ }
+
+ public static IEnumerable<object[]> Reverse_Generic_Int_TestData()
+ {
+ // TODO: use (or merge this data into) Reverse_TestData if/when xunit/xunit#965 is merged
+ yield return new object[] { new int[] { 1, 2, 3 }, 0, 3, new int[] { 3, 2, 1 } };
+ yield return new object[] { new int[] { 1, 2, 3 }, 0, 2, new int[] { 2, 1, 3 } };
+ yield return new object[] { new int[] { 1, 2, 3 }, 1, 2, new int[] { 1, 3, 2 } };
+
+ // Nothing to reverse
+ yield return new object[] { new int[] { 1, 2, 3 }, 2, 1, new int[] { 1, 2, 3 } };
+ yield return new object[] { new int[] { 1, 2, 3 }, 0, 1, new int[] { 1, 2, 3 } };
+ yield return new object[] { new int[] { 1, 2, 3 }, 0, 0, new int[] { 1, 2, 3 } };
+ yield return new object[] { new int[] { 1, 2, 3 }, 3, 0, new int[] { 1, 2, 3 } };
+ yield return new object[] { new int[0], 0, 0, new int[0] };
+ }
+
+ [Theory]
+ [MemberData(nameof(Reverse_Generic_Int_TestData))]
+ public static void Reverse_Generic(int[] array, int index, int length, int[] expected)
+ {
+ if (index == 0 && length == array.Length)
+ {
+ int[] arrayClone1 = (int[])array.Clone();
+ Array.Reverse(arrayClone1);
+ Assert.Equal(expected, arrayClone1);
+ }
+ int[] arrayClone2 = (int[])array.Clone();
+ Array.Reverse(arrayClone2, index, length);
+ Assert.Equal(expected, arrayClone2);
+ }
+
+ [Fact]
+ public static void Reverse_Generic_NullArray_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("array", () => Array.Reverse((string[])null));
+ AssertExtensions.Throws<ArgumentNullException>("array", () => Array.Reverse((string[])null, 0, 0));
+ }
+
+ [Fact]
+ public static void Reverse_Generic_NegativeIndex_ThrowsArgumentOutOfRangeException()
+ {
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => Array.Reverse(new string[0], -1, 0));
+ }
+
+ [Fact]
+ public static void Reverse_Generic_NegativeLength_ThrowsArgumentOutOfRangeException()
+ {
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("length", () => Array.Reverse(new string[0], 0, -1));
+ }
+
+ [Theory]
+ [InlineData(0, 0, 1)]
+ [InlineData(3, 4, 0)]
+ [InlineData(3, 3, 1)]
+ [InlineData(3, 2, 2)]
+ [InlineData(3, 1, 3)]
+ [InlineData(3, 0, 4)]
+ public static void Reverse_Generic_InvalidOffsetPlusLength_ThrowsArgumentException(int arrayLength, int index, int length)
+ {
+ AssertExtensions.Throws<ArgumentException>(null, () => Array.Reverse(new string[arrayLength], index, length));
+ }
+
+ [Fact]
+ public static void Reverse_NonSZArrayWithMinValueLowerBound()
+ {
+ Array array = NonZeroLowerBoundArray(new int[] { 1, 2, 3 }, int.MinValue);
+
+ Reverse(array, int.MinValue, 0, new int[] { 1, 2, 3 });
+ Reverse(array, int.MinValue, 1, new int[] { 1, 2, 3 });
+ Reverse(array, int.MinValue, 2, new int[] { 2, 1, 3 });
+ }
+
+ [Fact]
+ public void CreateInstance_TypeNotRuntimeType_ThrowsArgumentException()
+ {
+ // This cannot be a [Theory] due to https://github.com/xunit/xunit/issues/1325.
+ foreach (Type elementType in Helpers.NonRuntimeTypes)
+ {
+ AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, 1));
+ AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, 1, 1));
+ AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, 1, 1, 1));
+ AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, new int[1]));
+ AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, new long[1]));
+ AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, new int[1], new int[1]));
+ }
+ }
+
private static void VerifyArray(Array array, Type elementType, int[] lengths, int[] lowerBounds, object repeatedValue)
{
VerifyArray(array, elementType, lengths, lowerBounds);
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class ArrayTests
- {
- public static IEnumerable<object[]> Fill_Generic_TestData()
- {
- var data = Enumerable.Empty<object[]>();
-
- var r = new Random(0x051778f7);
- int[] lengths = { 0, 1, 2, 3, 5, 8, 13 };
-
- foreach (int length in lengths)
- {
- IEnumerable<int> source = Enumerable.Range(1, length).Select(_ => r.Next());
-
- data = data.Concat(GenerateFillData(source, r.Next(), i => i))
- .Concat(GenerateFillData(source, r.Next(), i => unchecked((byte)i)))
- .Concat(GenerateFillData(source, r.Next(), i => unchecked((short)i)))
- .Concat(GenerateFillData(source, r.Next(), i => (long)i))
- .Concat(GenerateFillData(source, r.Next(), i => new StrongBox<int>(i)))
- .Concat(GenerateFillData(source, r.Next(), i => i.ToString()))
- .Concat(GenerateFillData(source, r.Next(), i => unchecked((ByteEnum)i)))
- .Concat(GenerateFillData(source, r.Next(), i => unchecked((Int16Enum)i)))
- .Concat(GenerateFillData(source, r.Next(), i => (Int32Enum)i))
- .Concat(GenerateFillData(source, r.Next(), i => (Int64Enum)i))
- .Concat(GenerateFillData(source, r.Next(), i => new object()));
- }
-
- return data;
- }
-
- public static IEnumerable<object[]> GenerateFillData<TSource, TResult>(IEnumerable<TSource> source, TSource seed, Func<TSource, TResult> transform)
- {
- int count = source.Count();
- TResult repeatedValue = transform(seed);
- // Force evaluation so neither `source` or `transform` are re-run if the sequence is enumerated more than once.
- IEnumerable<TResult> transformed = source.Select(transform).ToList();
-
- yield return new object[] { transformed, repeatedValue, 0, count }; // Fill the entire array.
- yield return new object[] { transformed, repeatedValue, 0, count / 2 }; // Fill the beginning of the array.
- yield return new object[] { transformed, repeatedValue, count / 2, count / 2 }; // Fill the end of the array, assuming `length` is even.
- yield return new object[] { transformed, repeatedValue, count / 4, count / 2 }; // Fill the middle of the array.
- yield return new object[] { transformed, repeatedValue, count, 0 }; // Fill nothing.
- }
-
- [Theory]
- [MemberData(nameof(Fill_Generic_TestData))]
- public static void Fill_Generic<T>(IEnumerable<T> source, T value, int startIndex, int count)
- {
- if (startIndex == 0 && count == source.Count())
- {
- T[] array = source.ToArray();
- Array.Fill(array, value);
- Assert.Equal(Enumerable.Repeat(value, count), array);
- }
-
- {
- T[] array = source.ToArray();
-
- // Before calling Fill, we want to capture the segments before/after the filled region.
- // We want to ensure that in addition to filling in what it's supposed to, Fill does
- // not touch the adjacent segments.
- T[] before = source.Take(startIndex).ToArray();
- T[] after = source.Skip(startIndex + count).ToArray();
-
- Array.Fill(array, value, startIndex, count);
-
- Assert.Equal(before, array.Take(startIndex));
- Assert.Equal(Enumerable.Repeat(value, count), array.Skip(startIndex).Take(count));
- Assert.Equal(after, array.Skip(startIndex + count));
- }
- }
-
- [Fact]
- public void Fill_NullArray_ThrowsArgumentNullException()
- {
- AssertExtensions.Throws<ArgumentNullException>("array", () => Array.Fill(null, 1));
- AssertExtensions.Throws<ArgumentNullException>("array", () => Array.Fill(null, 1, 0, 0));
- }
-
- [Theory]
- [InlineData(-1)]
- [InlineData(2)]
- public void Fill_InvalidStartIndex_ThrowsArgumentOutOfRangeException(int startIndex)
- {
- AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => Array.Fill(new string[1], "", startIndex, 0));
- }
-
- [Theory]
- [InlineData(1, 0, -1)]
- [InlineData(0, 0, 1)]
- [InlineData(3, 3, 1)]
- [InlineData(3, 2, 2)]
- [InlineData(3, 1, 3)]
- [InlineData(3, 0, 4)]
- public void Fill_InvalidStartIndexCount_ThrowsArgumentOutOfRangeException(int arrayLength, int startIndex, int count)
- {
- AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => Array.Fill(new string[arrayLength], "", startIndex, count));
- }
-
- public static IEnumerable<object[]> Reverse_Generic_Int_TestData()
- {
- // TODO: use (or merge this data into) Reverse_TestData if/when xunit/xunit#965 is merged
- yield return new object[] { new int[] { 1, 2, 3 }, 0, 3, new int[] { 3, 2, 1 } };
- yield return new object[] { new int[] { 1, 2, 3 }, 0, 2, new int[] { 2, 1, 3 } };
- yield return new object[] { new int[] { 1, 2, 3 }, 1, 2, new int[] { 1, 3, 2 } };
-
- // Nothing to reverse
- yield return new object[] { new int[] { 1, 2, 3 }, 2, 1, new int[] { 1, 2, 3 } };
- yield return new object[] { new int[] { 1, 2, 3 }, 0, 1, new int[] { 1, 2, 3 } };
- yield return new object[] { new int[] { 1, 2, 3 }, 0, 0, new int[] { 1, 2, 3 } };
- yield return new object[] { new int[] { 1, 2, 3 }, 3, 0, new int[] { 1, 2, 3 } };
- yield return new object[] { new int[0], 0, 0, new int[0] };
- }
-
- [Theory]
- [MemberData(nameof(Reverse_Generic_Int_TestData))]
- public static void Reverse_Generic(int[] array, int index, int length, int[] expected)
- {
- if (index == 0 && length == array.Length)
- {
- int[] arrayClone1 = (int[])array.Clone();
- Array.Reverse(arrayClone1);
- Assert.Equal(expected, arrayClone1);
- }
- int[] arrayClone2 = (int[])array.Clone();
- Array.Reverse(arrayClone2, index, length);
- Assert.Equal(expected, arrayClone2);
- }
-
- [Fact]
- public static void Reverse_Generic_NullArray_ThrowsArgumentNullException()
- {
- AssertExtensions.Throws<ArgumentNullException>("array", () => Array.Reverse((string[])null));
- AssertExtensions.Throws<ArgumentNullException>("array", () => Array.Reverse((string[])null, 0, 0));
- }
-
- [Fact]
- public static void Reverse_Generic_NegativeIndex_ThrowsArgumentOutOfRangeException()
- {
- AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => Array.Reverse(new string[0], -1, 0));
- }
-
- [Fact]
- public static void Reverse_Generic_NegativeLength_ThrowsArgumentOutOfRangeException()
- {
- AssertExtensions.Throws<ArgumentOutOfRangeException>("length", () => Array.Reverse(new string[0], 0, -1));
- }
-
- [Theory]
- [InlineData(0, 0, 1)]
- [InlineData(3, 4, 0)]
- [InlineData(3, 3, 1)]
- [InlineData(3, 2, 2)]
- [InlineData(3, 1, 3)]
- [InlineData(3, 0, 4)]
- public static void Reverse_Generic_InvalidOffsetPlusLength_ThrowsArgumentException(int arrayLength, int index, int length)
- {
- AssertExtensions.Throws<ArgumentException>(null, () => Array.Reverse(new string[arrayLength], index, length));
- }
-
- [Fact]
- public static void Reverse_NonSZArrayWithMinValueLowerBound()
- {
- Array array = NonZeroLowerBoundArray(new int[] { 1, 2, 3 }, int.MinValue);
-
- Reverse(array, int.MinValue, 0, new int[] { 1, 2, 3 });
- Reverse(array, int.MinValue, 1, new int[] { 1, 2, 3 });
- Reverse(array, int.MinValue, 2, new int[] { 2, 1, 3 });
- }
-
- [Fact]
- public void CreateInstance_TypeNotRuntimeType_ThrowsArgumentException()
- {
- // This cannot be a [Theory] due to https://github.com/xunit/xunit/issues/1325.
- foreach (Type elementType in Helpers.NonRuntimeTypes)
- {
- AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, 1));
- AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, 1, 1));
- AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, 1, 1, 1));
- AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, new int[1]));
- AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, new long[1]));
- AssertExtensions.Throws<ArgumentException>("elementType", () => Array.CreateInstance(elementType, new int[1], new int[1]));
- }
- }
- }
-}
{
Assert.Equal(TypeCode.Boolean, true.GetTypeCode());
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1] };
+ }
+
+ yield return new object[] { " \0 \0 TrueFalse \0 ", 6, 4, true };
+ yield return new object[] { " \0 \0 TrueFalse \0 ", 10, 5, false };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, bool expected)
+ {
+ Assert.Equal(expected, bool.Parse(value.AsSpan(offset, count)));
+
+ Assert.True(bool.TryParse(value.AsSpan(offset, count), out bool result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, Type exceptionType)
+ {
+ if (value != null)
+ {
+ Assert.Throws(exceptionType, () => bool.Parse(value.AsSpan()));
+
+ Assert.False(bool.TryParse(value.AsSpan(), out bool result));
+ Assert.False(result);
+ }
+ }
+
+ [Theory]
+ [InlineData(true, "True")]
+ [InlineData(false, "False")]
+ public static void TryFormat(bool i, string expected)
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual));
+
+ // Longer than needed
+ actual = new char[expected.Length + 1];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (expected.Length > 0)
+ {
+ actual = new char[expected.Length - 1];
+ Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten));
+ Assert.Equal(0, charsWritten);
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class BooleanTests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1] };
- }
-
- yield return new object[] { " \0 \0 TrueFalse \0 ", 6, 4, true };
- yield return new object[] { " \0 \0 TrueFalse \0 ", 10, 5, false };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, bool expected)
- {
- Assert.Equal(expected, bool.Parse(value.AsSpan(offset, count)));
-
- Assert.True(bool.TryParse(value.AsSpan(offset, count), out bool result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, Type exceptionType)
- {
- if (value != null)
- {
- Assert.Throws(exceptionType, () => bool.Parse(value.AsSpan()));
-
- Assert.False(bool.TryParse(value.AsSpan(), out bool result));
- Assert.False(result);
- }
- }
-
- [Theory]
- [InlineData(true, "True")]
- [InlineData(false, "False")]
- public static void TryFormat(bool i, string expected)
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual));
-
- // Longer than needed
- actual = new char[expected.Length + 1];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual, 0, charsWritten));
-
- // Too short
- if (expected.Length > 0)
- {
- actual = new char[expected.Length - 1];
- Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten));
- Assert.Equal(0, charsWritten);
- }
- }
- }
-}
namespace System.Tests
{
- public partial class ByteTests
+ public class ByteTests
{
[Fact]
public static void Ctor_Empty()
AssertExtensions.Throws<ArgumentException>(paramName, () => byte.Parse("1", style));
AssertExtensions.Throws<ArgumentException>(paramName, () => byte.Parse("1", style, null));
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ yield return new object[] { "123", 0, 2, NumberStyles.Integer, null, (byte)12 };
+ yield return new object[] { "+123", 0, 2, NumberStyles.Integer, null, (byte)1 };
+ yield return new object[] { "+123", 1, 3, NumberStyles.Integer, null, (byte)123 };
+ yield return new object[] { " 123 ", 4, 1, NumberStyles.Integer, null, (byte)3 };
+ yield return new object[] { "12", 1, 1, NumberStyles.HexNumber, null, (byte)0x2 };
+ yield return new object[] { "10", 0, 1, NumberStyles.AllowThousands, null, (byte)1 };
+ yield return new object[] { "$100", 0, 2, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (byte)1 };
+ }
+
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, byte expected)
+ {
+ byte result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.True(byte.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+ }
+
+ Assert.Equal(expected, byte.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(byte.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ byte result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.False(byte.TryParse(value.AsSpan(), out result));
+ Assert.Equal(0u, result);
+ }
+
+ Assert.Throws(exceptionType, () => byte.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(byte.TryParse(value.AsSpan(), style, provider, out result));
+ Assert.Equal(0u, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat(byte i, string format, IFormatProvider provider, string expected)
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual));
+
+ // Longer than needed
+ actual = new char[expected.Length + 1];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (expected.Length > 0)
+ {
+ actual = new char[expected.Length - 1];
+ Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(0, charsWritten);
+ }
+
+ if (format != null)
+ {
+ // Upper format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToUpperInvariant(), new string(actual));
+
+ // Lower format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToLowerInvariant(), new string(actual));
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class ByteTests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- yield return new object[] { "123", 0, 2, NumberStyles.Integer, null, (byte)12 };
- yield return new object[] { "+123", 0, 2, NumberStyles.Integer, null, (byte)1 };
- yield return new object[] { "+123", 1, 3, NumberStyles.Integer, null, (byte)123 };
- yield return new object[] { " 123 ", 4, 1, NumberStyles.Integer, null, (byte)3 };
- yield return new object[] { "12", 1, 1, NumberStyles.HexNumber, null, (byte)0x2 };
- yield return new object[] { "10", 0, 1, NumberStyles.AllowThousands, null, (byte)1 };
- yield return new object[] { "$100", 0, 2, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (byte)1 };
- }
-
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, byte expected)
- {
- byte result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.True(byte.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
- }
-
- Assert.Equal(expected, byte.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(byte.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- byte result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.False(byte.TryParse(value.AsSpan(), out result));
- Assert.Equal(0u, result);
- }
-
- Assert.Throws(exceptionType, () => byte.Parse(value.AsSpan(), style, provider));
-
- Assert.False(byte.TryParse(value.AsSpan(), style, provider, out result));
- Assert.Equal(0u, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat(byte i, string format, IFormatProvider provider, string expected)
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual));
-
- // Longer than needed
- actual = new char[expected.Length + 1];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual, 0, charsWritten));
-
- // Too short
- if (expected.Length > 0)
- {
- actual = new char[expected.Length - 1];
- Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(0, charsWritten);
- }
-
- if (format != null)
- {
- // Upper format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToUpperInvariant(), new string(actual));
-
- // Lower format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToLowerInvariant(), new string(actual));
- }
- }
- }
-}
using System.Collections.Generic;
using System.Globalization;
using System.Text;
+using System.Text.Unicode.Tests;
using Xunit;
+using Xunit.Sdk;
namespace System.Tests
{
- public partial class CharTests
+ public class CharTests
{
[Theory]
[InlineData('h', 'h', 0)]
Assert.Equal(lowerForm, char.ToLower(upperForm, ci));
Assert.Equal(upperForm, char.ToUpper(lowerForm, ci));
}
+
+ [OuterLoop]
+ [Fact]
+ public static void GetUnicodeCategory_Char_AllInputs()
+ {
+ // This tests calls char.GetUnicodeCategory for every possible input, ensuring that
+ // the runtime agrees with the data in the core Unicode files.
+
+ for (uint i = 0; i <= char.MaxValue; i++)
+ {
+ UnicodeCategory expected;
+
+ // The code points in the switch block below must be special-cased
+ // because they switched categories between versions of the Unicode
+ // specification. For compatibility reasons Char keeps its own copy
+ // of the categories for the first 256 code points, as it's locked
+ // to an earlier version of the standard. For an example of a code
+ // point that switched categories, see the discussion on U+00AD
+ // SOFT HYPHEN at https://www.unicode.org/versions/Unicode4.0.0/.
+
+ switch (i)
+ {
+ case '\u00a7':
+ case '\u00b6':
+ expected = UnicodeCategory.OtherSymbol;
+ break;
+
+ case '\u00aa':
+ case '\u00ba':
+ expected = UnicodeCategory.LowercaseLetter;
+ break;
+
+ case '\u00ad':
+ expected = UnicodeCategory.DashPunctuation;
+ break;
+
+ default:
+ expected = UnicodeData.GetUnicodeCategory(i);
+ break;
+ }
+
+ if (expected != char.GetUnicodeCategory((char)i))
+ {
+ // We'll build up the exception message ourselves so the dev knows what code point failed.
+ throw new AssertActualExpectedException(
+ expected: expected,
+ actual: char.GetUnicodeCategory((char)i),
+ userMessage: FormattableString.Invariant($@"char.GetUnicodeCategory('\u{i:X4}') returned wrong value."));
+ }
+ }
+ }
+
+ [OuterLoop]
+ [Fact]
+ public static void IsLetter_Char_AllInputs()
+ {
+ // This tests calls char.IsLetter for every possible input, ensuring that
+ // the runtime agrees with the data in the core Unicode files.
+
+ for (uint i = 0; i <= char.MaxValue; i++)
+ {
+ if (UnicodeData.IsLetter((char)i) != char.IsLetter((char)i))
+ {
+ // We'll build up the exception message ourselves so the dev knows what code point failed.
+ throw new AssertActualExpectedException(
+ expected: UnicodeData.IsLetter((char)i),
+ actual: char.IsLetter((char)i),
+ userMessage: FormattableString.Invariant($@"char.IsLetter('\u{i:X4}') returned wrong value."));
+ }
+ }
+ }
+
+ [OuterLoop]
+ [Fact]
+ public static void IsLower_Char_AllInputs()
+ {
+ // This tests calls char.IsLower for every possible input, ensuring that
+ // the runtime agrees with the data in the core Unicode files.
+
+ for (uint i = 0; i <= char.MaxValue; i++)
+ {
+ bool expected;
+
+ switch (i)
+ {
+ case '\u00AA': // FEMININE ORDINAL INDICATOR
+ case '\u00BA': // MASCULINE ORDINAL INDICATOR
+
+ // In Unicode 6.1 the code points U+00AA and U+00BA were reassigned
+ // from category Ll to category Lo. However, for compatibility reasons,
+ // Char uses the older version of the Unicode standard for code points
+ // in the range U+0000..U+00FF. So we'll special-case these here.
+ // More info: https://www.unicode.org/review/pri181/
+
+ expected = true;
+ break;
+
+ default:
+ expected = UnicodeData.GetUnicodeCategory((char)i) == UnicodeCategory.LowercaseLetter;
+ break;
+ }
+
+ if (expected != char.IsLower((char)i))
+ {
+ // We'll build up the exception message ourselves so the dev knows what code point failed.
+ throw new AssertActualExpectedException(
+ expected: expected,
+ actual: char.IsLower((char)i),
+ userMessage: FormattableString.Invariant($@"char.IsLower('\u{i:X4}') returned wrong value."));
+ }
+ }
+ }
+
+ [OuterLoop]
+ [Fact]
+ public static void IsUpper_Char_AllInputs()
+ {
+ // This tests calls char.IsUpper for every possible input, ensuring that
+ // the runtime agrees with the data in the core Unicode files.
+
+ for (uint i = 0; i <= char.MaxValue; i++)
+ {
+ bool expected = UnicodeData.GetUnicodeCategory((char)i) == UnicodeCategory.UppercaseLetter;
+
+ if (expected != char.IsUpper((char)i))
+ {
+ // We'll build up the exception message ourselves so the dev knows what code point failed.
+ throw new AssertActualExpectedException(
+ expected: expected,
+ actual: char.IsUpper((char)i),
+ userMessage: FormattableString.Invariant($@"char.IsUpper('\u{i:X4}') returned wrong value."));
+ }
+ }
+ }
+
+ [OuterLoop]
+ [Fact]
+ public static void IsWhiteSpace_Char_AllInputs()
+ {
+ // This tests calls char.IsWhiteSpace for every possible input, ensuring that
+ // the runtime agrees with the data in the core Unicode files.
+
+ for (uint i = 0; i <= char.MaxValue; i++)
+ {
+ if (UnicodeData.IsWhiteSpace(i) != char.IsWhiteSpace((char)i))
+ {
+ // We'll build up the exception message ourselves so the dev knows what code point failed.
+ throw new AssertActualExpectedException(
+ expected: UnicodeData.IsWhiteSpace(i),
+ actual: char.IsWhiteSpace((char)i),
+ userMessage: FormattableString.Invariant($@"char.IsWhiteSpace('\u{i:X4}') returned wrong value."));
+ }
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Globalization;
-using System.Text.Unicode.Tests;
-using Xunit;
-using Xunit.Sdk;
-
-namespace System.Tests
-{
- public partial class CharTests
- {
- [OuterLoop]
- [Fact]
- public static void GetUnicodeCategory_Char_AllInputs()
- {
- // This tests calls char.GetUnicodeCategory for every possible input, ensuring that
- // the runtime agrees with the data in the core Unicode files.
-
- for (uint i = 0; i <= char.MaxValue; i++)
- {
- UnicodeCategory expected;
-
- // The code points in the switch block below must be special-cased
- // because they switched categories between versions of the Unicode
- // specification. For compatibility reasons Char keeps its own copy
- // of the categories for the first 256 code points, as it's locked
- // to an earlier version of the standard. For an example of a code
- // point that switched categories, see the discussion on U+00AD
- // SOFT HYPHEN at https://www.unicode.org/versions/Unicode4.0.0/.
-
- switch (i)
- {
- case '\u00a7':
- case '\u00b6':
- expected = UnicodeCategory.OtherSymbol;
- break;
-
- case '\u00aa':
- case '\u00ba':
- expected = UnicodeCategory.LowercaseLetter;
- break;
-
- case '\u00ad':
- expected = UnicodeCategory.DashPunctuation;
- break;
-
- default:
- expected = UnicodeData.GetUnicodeCategory(i);
- break;
- }
-
- if (expected != char.GetUnicodeCategory((char)i))
- {
- // We'll build up the exception message ourselves so the dev knows what code point failed.
- throw new AssertActualExpectedException(
- expected: expected,
- actual: char.GetUnicodeCategory((char)i),
- userMessage: FormattableString.Invariant($@"char.GetUnicodeCategory('\u{i:X4}') returned wrong value."));
- }
- }
- }
-
- [OuterLoop]
- [Fact]
- public static void IsLetter_Char_AllInputs()
- {
- // This tests calls char.IsLetter for every possible input, ensuring that
- // the runtime agrees with the data in the core Unicode files.
-
- for (uint i = 0; i <= char.MaxValue; i++)
- {
- if (UnicodeData.IsLetter((char)i) != char.IsLetter((char)i))
- {
- // We'll build up the exception message ourselves so the dev knows what code point failed.
- throw new AssertActualExpectedException(
- expected: UnicodeData.IsLetter((char)i),
- actual: char.IsLetter((char)i),
- userMessage: FormattableString.Invariant($@"char.IsLetter('\u{i:X4}') returned wrong value."));
- }
- }
- }
-
- [OuterLoop]
- [Fact]
- public static void IsLower_Char_AllInputs()
- {
- // This tests calls char.IsLower for every possible input, ensuring that
- // the runtime agrees with the data in the core Unicode files.
-
- for (uint i = 0; i <= char.MaxValue; i++)
- {
- bool expected;
-
- switch (i)
- {
- case '\u00AA': // FEMININE ORDINAL INDICATOR
- case '\u00BA': // MASCULINE ORDINAL INDICATOR
-
- // In Unicode 6.1 the code points U+00AA and U+00BA were reassigned
- // from category Ll to category Lo. However, for compatibility reasons,
- // Char uses the older version of the Unicode standard for code points
- // in the range U+0000..U+00FF. So we'll special-case these here.
- // More info: https://www.unicode.org/review/pri181/
-
- expected = true;
- break;
-
- default:
- expected = UnicodeData.GetUnicodeCategory((char)i) == UnicodeCategory.LowercaseLetter;
- break;
- }
-
- if (expected != char.IsLower((char)i))
- {
- // We'll build up the exception message ourselves so the dev knows what code point failed.
- throw new AssertActualExpectedException(
- expected: expected,
- actual: char.IsLower((char)i),
- userMessage: FormattableString.Invariant($@"char.IsLower('\u{i:X4}') returned wrong value."));
- }
- }
- }
-
- [OuterLoop]
- [Fact]
- public static void IsUpper_Char_AllInputs()
- {
- // This tests calls char.IsUpper for every possible input, ensuring that
- // the runtime agrees with the data in the core Unicode files.
-
- for (uint i = 0; i <= char.MaxValue; i++)
- {
- bool expected = UnicodeData.GetUnicodeCategory((char)i) == UnicodeCategory.UppercaseLetter;
-
- if (expected != char.IsUpper((char)i))
- {
- // We'll build up the exception message ourselves so the dev knows what code point failed.
- throw new AssertActualExpectedException(
- expected: expected,
- actual: char.IsUpper((char)i),
- userMessage: FormattableString.Invariant($@"char.IsUpper('\u{i:X4}') returned wrong value."));
- }
- }
- }
-
- [OuterLoop]
- [Fact]
- public static void IsWhiteSpace_Char_AllInputs()
- {
- // This tests calls char.IsWhiteSpace for every possible input, ensuring that
- // the runtime agrees with the data in the core Unicode files.
-
- for (uint i = 0; i <= char.MaxValue; i++)
- {
- if (UnicodeData.IsWhiteSpace(i) != char.IsWhiteSpace((char)i))
- {
- // We'll build up the exception message ourselves so the dev knows what code point failed.
- throw new AssertActualExpectedException(
- expected: UnicodeData.IsWhiteSpace(i),
- actual: char.IsWhiteSpace((char)i),
- userMessage: FormattableString.Invariant($@"char.IsWhiteSpace('\u{i:X4}') returned wrong value."));
- }
- }
- }
- }
-}
namespace System.Collections.Generic.Tests
{
- public partial class KeyValuePairTests
+ public class KeyValuePairTests
{
[Fact]
public void Ctor_KeyValue_ReturnsExpected()
var keyValuePair = new KeyValuePair<string, string>(null, null);
Assert.Equal("[, ]", keyValuePair.ToString());
}
+
+ [Fact]
+ public void Create_ReturnsExpected()
+ {
+ KeyValuePair<int, string> keyValuePair = KeyValuePair.Create(1, "2");
+ Assert.Equal(1, keyValuePair.Key);
+ Assert.Equal("2", keyValuePair.Value);
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Xunit;
-
-namespace System.Collections.Generic.Tests
-{
- public partial class KeyValuePairTests
- {
- [Fact]
- public void Create_ReturnsExpected()
- {
- KeyValuePair<int, string> keyValuePair = KeyValuePair.Create(1, "2");
- Assert.Equal(1, keyValuePair.Key);
- Assert.Equal("2", keyValuePair.Value);
- }
- }
-}
namespace System.ComponentModel.Tests
{
- public partial class DefaultValueAttributeTests
+ public class DefaultValueAttributeTests
{
[Fact]
public static void Ctor()
Assert.Equal(3.14f, new DefaultValueAttribute(3.14f).Value);
Assert.Equal((byte)1, new DefaultValueAttribute((byte)1).Value);
+ Assert.Equal((sbyte)42, new DefaultValueAttribute((sbyte)42).Value);
+
Assert.Equal(42, new DefaultValueAttribute(42).Value);
+ Assert.Equal((uint)42, new DefaultValueAttribute((uint)42).Value);
+
Assert.Equal(42L, new DefaultValueAttribute(42L).Value);
+ Assert.Equal((ulong)42, new DefaultValueAttribute((ulong)42).Value);
+
Assert.Equal((short)42, new DefaultValueAttribute((short)42).Value);
+ Assert.Equal((ushort)42, new DefaultValueAttribute((ushort)42).Value);
Assert.Equal('c', new DefaultValueAttribute('c').Value);
Assert.Equal("test", new DefaultValueAttribute("test").Value);
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using Xunit;
-
-namespace System.ComponentModel.Tests
-{
- public partial class DefaultValueAttributeTests
- {
- [Fact]
- public static void Ctor_netcoreapp11()
- {
- Assert.Equal((sbyte)42, new DefaultValueAttribute((sbyte)42).Value);
- Assert.Equal((ushort)42, new DefaultValueAttribute((ushort)42).Value);
- Assert.Equal((uint)42, new DefaultValueAttribute((uint)42).Value);
- Assert.Equal((ulong)42, new DefaultValueAttribute((ulong)42).Value);
- }
- }
-}
namespace System.Tests
{
- public static partial class DateTimeOffsetTests
+ public static class DateTimeOffsetTests
{
[Fact]
public static void MaxValue()
{
Assert.Equal(expected, dateTimeOffset.ToString(format, culture));
}
+
+ [Fact]
+ public static void ToString_ParseSpan_RoundtripsSuccessfully()
+ {
+ DateTimeOffset expected = DateTimeOffset.MaxValue;
+ string expectedString = expected.ToString();
+
+ Assert.Equal(expectedString, DateTimeOffset.Parse(expectedString.AsSpan()).ToString());
+ Assert.Equal(expectedString, DateTimeOffset.Parse(expectedString.AsSpan(), null).ToString());
+ Assert.Equal(expectedString, DateTimeOffset.Parse(expectedString.AsSpan(), null, DateTimeStyles.None).ToString());
+
+ Assert.True(DateTimeOffset.TryParse(expectedString.AsSpan(), out DateTimeOffset actual));
+ Assert.Equal(expectedString, actual.ToString());
+ Assert.True(DateTimeOffset.TryParse(expectedString.AsSpan(), null, DateTimeStyles.None, out actual));
+ Assert.Equal(expectedString, actual.ToString());
+ }
+
+ [Theory]
+ [InlineData("r")]
+ [InlineData("o")]
+ public static void ToString_Slice_ParseSpan_RoundtripsSuccessfully(string roundtripFormat)
+ {
+ string expectedString = DateTimeOffset.UtcNow.ToString(roundtripFormat);
+ ReadOnlySpan<char> expectedSpan = ("abcd" + expectedString + "1234").AsSpan("abcd".Length, expectedString.Length);
+
+ Assert.Equal(expectedString, DateTimeOffset.Parse(expectedSpan).ToString(roundtripFormat));
+ Assert.Equal(expectedString, DateTimeOffset.Parse(expectedSpan, null).ToString(roundtripFormat));
+ Assert.Equal(expectedString, DateTimeOffset.Parse(expectedSpan, null, DateTimeStyles.None).ToString(roundtripFormat));
+
+ Assert.True(DateTimeOffset.TryParse(expectedSpan, out DateTimeOffset actual));
+ Assert.Equal(expectedString, actual.ToString(roundtripFormat));
+ Assert.True(DateTimeOffset.TryParse(expectedSpan, null, DateTimeStyles.None, out actual));
+ Assert.Equal(expectedString, actual.ToString(roundtripFormat));
+ }
+
+ [Fact]
+ public static void ToString_ParseExactSpan_RoundtripsSuccessfully()
+ {
+ DateTimeOffset expected = DateTimeOffset.MaxValue;
+ string expectedString = expected.ToString("u");
+
+ Assert.Equal(expectedString, DateTimeOffset.ParseExact(expectedString, "u", null, DateTimeStyles.None).ToString("u"));
+ Assert.Equal(expectedString, DateTimeOffset.ParseExact(expectedString, new[] { "u" }, null, DateTimeStyles.None).ToString("u"));
+
+ Assert.True(DateTimeOffset.TryParseExact(expectedString, "u", null, DateTimeStyles.None, out DateTimeOffset actual));
+ Assert.Equal(expectedString, actual.ToString("u"));
+ Assert.True(DateTimeOffset.TryParseExact(expectedString, new[] { "u" }, null, DateTimeStyles.None, out actual));
+ Assert.Equal(expectedString, actual.ToString("u"));
+ }
+
+ [Fact]
+ public static void TryFormat_ToString_EqualResults()
+ {
+ DateTimeOffset expected = DateTimeOffset.MaxValue;
+ string expectedString = expected.ToString();
+
+ // Just the right amount of space, succeeds
+ Span<char> actual = new char[expectedString.Length];
+ Assert.True(expected.TryFormat(actual, out int charsWritten));
+ Assert.Equal(expectedString.Length, charsWritten);
+ Assert.Equal<char>(expectedString.ToCharArray(), actual.ToArray());
+
+ // Too little space, fails
+ actual = new char[expectedString.Length - 1];
+ Assert.False(expected.TryFormat(actual, out charsWritten));
+ Assert.Equal(0, charsWritten);
+
+ // More than enough space, succeeds
+ actual = new char[expectedString.Length + 1];
+ Assert.True(expected.TryFormat(actual, out charsWritten));
+ Assert.Equal(expectedString.Length, charsWritten);
+ Assert.Equal<char>(expectedString.ToCharArray(), actual.Slice(0, expectedString.Length).ToArray());
+ Assert.Equal(0, actual[actual.Length - 1]);
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_MatchesExpected_MemberData))]
+ public static void TryFormat_MatchesExpected(DateTimeOffset dateTimeOffset, string format, IFormatProvider provider, string expected)
+ {
+ var destination = new char[expected.Length];
+
+ Assert.False(dateTimeOffset.TryFormat(destination.AsSpan(0, destination.Length - 1), out _, format, provider));
+
+ Assert.True(dateTimeOffset.TryFormat(destination, out int charsWritten, format, provider));
+ Assert.Equal(destination.Length, charsWritten);
+ Assert.Equal(expected, new string(destination));
+ }
+
+ [Fact]
+ public static void UnixEpoch()
+ {
+ VerifyDateTimeOffset(DateTimeOffset.UnixEpoch, 1970, 1, 1, 0, 0, 0, 0, TimeSpan.Zero);
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public static partial class DateTimeOffsetTests
- {
- [Fact]
- public static void ToString_ParseSpan_RoundtripsSuccessfully()
- {
- DateTimeOffset expected = DateTimeOffset.MaxValue;
- string expectedString = expected.ToString();
-
- Assert.Equal(expectedString, DateTimeOffset.Parse(expectedString.AsSpan()).ToString());
- Assert.Equal(expectedString, DateTimeOffset.Parse(expectedString.AsSpan(), null).ToString());
- Assert.Equal(expectedString, DateTimeOffset.Parse(expectedString.AsSpan(), null, DateTimeStyles.None).ToString());
-
- Assert.True(DateTimeOffset.TryParse(expectedString.AsSpan(), out DateTimeOffset actual));
- Assert.Equal(expectedString, actual.ToString());
- Assert.True(DateTimeOffset.TryParse(expectedString.AsSpan(), null, DateTimeStyles.None, out actual));
- Assert.Equal(expectedString, actual.ToString());
- }
-
- [Theory]
- [InlineData("r")]
- [InlineData("o")]
- public static void ToString_Slice_ParseSpan_RoundtripsSuccessfully(string roundtripFormat)
- {
- string expectedString = DateTimeOffset.UtcNow.ToString(roundtripFormat);
- ReadOnlySpan<char> expectedSpan = ("abcd" + expectedString + "1234").AsSpan("abcd".Length, expectedString.Length);
-
- Assert.Equal(expectedString, DateTimeOffset.Parse(expectedSpan).ToString(roundtripFormat));
- Assert.Equal(expectedString, DateTimeOffset.Parse(expectedSpan, null).ToString(roundtripFormat));
- Assert.Equal(expectedString, DateTimeOffset.Parse(expectedSpan, null, DateTimeStyles.None).ToString(roundtripFormat));
-
- Assert.True(DateTimeOffset.TryParse(expectedSpan, out DateTimeOffset actual));
- Assert.Equal(expectedString, actual.ToString(roundtripFormat));
- Assert.True(DateTimeOffset.TryParse(expectedSpan, null, DateTimeStyles.None, out actual));
- Assert.Equal(expectedString, actual.ToString(roundtripFormat));
- }
-
- [Fact]
- public static void ToString_ParseExactSpan_RoundtripsSuccessfully()
- {
- DateTimeOffset expected = DateTimeOffset.MaxValue;
- string expectedString = expected.ToString("u");
-
- Assert.Equal(expectedString, DateTimeOffset.ParseExact(expectedString, "u", null, DateTimeStyles.None).ToString("u"));
- Assert.Equal(expectedString, DateTimeOffset.ParseExact(expectedString, new[] { "u" }, null, DateTimeStyles.None).ToString("u"));
-
- Assert.True(DateTimeOffset.TryParseExact(expectedString, "u", null, DateTimeStyles.None, out DateTimeOffset actual));
- Assert.Equal(expectedString, actual.ToString("u"));
- Assert.True(DateTimeOffset.TryParseExact(expectedString, new[] { "u" }, null, DateTimeStyles.None, out actual));
- Assert.Equal(expectedString, actual.ToString("u"));
- }
-
- [Fact]
- public static void TryFormat_ToString_EqualResults()
- {
- DateTimeOffset expected = DateTimeOffset.MaxValue;
- string expectedString = expected.ToString();
-
- // Just the right amount of space, succeeds
- Span<char> actual = new char[expectedString.Length];
- Assert.True(expected.TryFormat(actual, out int charsWritten));
- Assert.Equal(expectedString.Length, charsWritten);
- Assert.Equal<char>(expectedString.ToCharArray(), actual.ToArray());
-
- // Too little space, fails
- actual = new char[expectedString.Length - 1];
- Assert.False(expected.TryFormat(actual, out charsWritten));
- Assert.Equal(0, charsWritten);
-
- // More than enough space, succeeds
- actual = new char[expectedString.Length + 1];
- Assert.True(expected.TryFormat(actual, out charsWritten));
- Assert.Equal(expectedString.Length, charsWritten);
- Assert.Equal<char>(expectedString.ToCharArray(), actual.Slice(0, expectedString.Length).ToArray());
- Assert.Equal(0, actual[actual.Length - 1]);
- }
-
- [Theory]
- [MemberData(nameof(ToString_MatchesExpected_MemberData))]
- public static void TryFormat_MatchesExpected(DateTimeOffset dateTimeOffset, string format, IFormatProvider provider, string expected)
- {
- var destination = new char[expected.Length];
-
- Assert.False(dateTimeOffset.TryFormat(destination.AsSpan(0, destination.Length - 1), out _, format, provider));
-
- Assert.True(dateTimeOffset.TryFormat(destination, out int charsWritten, format, provider));
- Assert.Equal(destination.Length, charsWritten);
- Assert.Equal(expected, new string(destination));
- }
-
- [Fact]
- public static void UnixEpoch()
- {
- VerifyDateTimeOffset(DateTimeOffset.UnixEpoch, 1970, 1, 1, 0, 0, 0, 0, TimeSpan.Zero);
- }
- }
-}
namespace System.Tests
{
- public partial class DateTimeTests
+ public class DateTimeTests
{
[Fact]
public static void MaxValue()
return DateTime.MaxValue;
}
}
+
+ [Theory]
+ [MemberData(nameof(StandardFormatSpecifiers))]
+ public static void TryFormat_MatchesToString(string format)
+ {
+ DateTime dt = DateTime.UtcNow;
+ string expected = dt.ToString(format);
+
+ // Just the right length, succeeds
+ Span<char> dest = new char[expected.Length];
+ Assert.True(dt.TryFormat(dest, out int charsWritten, format));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal<char>(expected.ToCharArray(), dest.ToArray());
+
+ // Too short, fails
+ dest = new char[expected.Length - 1];
+ Assert.False(dt.TryFormat(dest, out charsWritten, format));
+ Assert.Equal(0, charsWritten);
+
+ // Longer than needed, succeeds
+ dest = new char[expected.Length + 1];
+ Assert.True(dt.TryFormat(dest, out charsWritten, format));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal<char>(expected.ToCharArray(), dest.Slice(0, expected.Length).ToArray());
+ Assert.Equal(0, dest[dest.Length - 1]);
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_MatchesExpected_MemberData))]
+ public static void TryFormat_MatchesExpected(DateTime dateTime, string format, IFormatProvider provider, string expected)
+ {
+ var destination = new char[expected.Length];
+
+ Assert.False(dateTime.TryFormat(destination.AsSpan(0, destination.Length - 1), out _, format, provider));
+
+ Assert.True(dateTime.TryFormat(destination, out int charsWritten, format, provider));
+ Assert.Equal(destination.Length, charsWritten);
+ Assert.Equal(expected, new string(destination));
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidInput_Succeeds_MemberData))]
+ public static void Parse_Span_ValidInput_Succeeds(string input, CultureInfo culture, DateTime? expected)
+ {
+ Assert.Equal(expected, DateTime.Parse(input.AsSpan(), culture));
+ }
+
+ [Theory]
+ [MemberData(nameof(ParseExact_ValidInput_Succeeds_MemberData))]
+ public static void ParseExact_Span_ValidInput_Succeeds(string input, string format, CultureInfo culture, DateTimeStyles style, DateTime? expected)
+ {
+ DateTime result1 = DateTime.ParseExact(input.AsSpan(), format, culture, style);
+ DateTime result2 = DateTime.ParseExact(input.AsSpan(), new[] { format }, culture, style);
+
+ Assert.True(DateTime.TryParseExact(input.AsSpan(), format, culture, style, out DateTime result3));
+ Assert.True(DateTime.TryParseExact(input.AsSpan(), new[] { format }, culture, style, out DateTime result4));
+
+ Assert.Equal(result1, result2);
+ Assert.Equal(result1, result3);
+ Assert.Equal(result1, result4);
+
+ if (expected != null) // some inputs don't roundtrip well
+ {
+ // Normalize values to make comparison easier
+ if (expected.Value.Kind != DateTimeKind.Utc)
+ {
+ expected = expected.Value.ToUniversalTime();
+ }
+ if (result1.Kind != DateTimeKind.Utc)
+ {
+ result1 = result1.ToUniversalTime();
+ }
+
+ Assert.Equal(expected, result1);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ParseExact_InvalidInputs_Fail_MemberData))]
+ public static void ParseExact_Span_InvalidInputs_Fail(string input, string format, CultureInfo culture, DateTimeStyles style)
+ {
+ Assert.Throws<FormatException>(() => DateTime.ParseExact(input.AsSpan(), format, culture, style));
+ Assert.Throws<FormatException>(() => DateTime.ParseExact(input.AsSpan(), new[] { format }, culture, style));
+
+ Assert.False(DateTime.TryParseExact(input.AsSpan(), format, culture, style, out DateTime result));
+ Assert.False(DateTime.TryParseExact(input.AsSpan(), new[] { format }, culture, style, out result));
+ }
+
+ [Fact]
+ public static void UnixEpoch()
+ {
+ VerifyDateTime(DateTime.UnixEpoch, 1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class DateTimeTests
- {
- [Theory]
- [MemberData(nameof(StandardFormatSpecifiers))]
- public static void TryFormat_MatchesToString(string format)
- {
- DateTime dt = DateTime.UtcNow;
- string expected = dt.ToString(format);
-
- // Just the right length, succeeds
- Span<char> dest = new char[expected.Length];
- Assert.True(dt.TryFormat(dest, out int charsWritten, format));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal<char>(expected.ToCharArray(), dest.ToArray());
-
- // Too short, fails
- dest = new char[expected.Length - 1];
- Assert.False(dt.TryFormat(dest, out charsWritten, format));
- Assert.Equal(0, charsWritten);
-
- // Longer than needed, succeeds
- dest = new char[expected.Length + 1];
- Assert.True(dt.TryFormat(dest, out charsWritten, format));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal<char>(expected.ToCharArray(), dest.Slice(0, expected.Length).ToArray());
- Assert.Equal(0, dest[dest.Length - 1]);
- }
-
- [Theory]
- [MemberData(nameof(ToString_MatchesExpected_MemberData))]
- public static void TryFormat_MatchesExpected(DateTime dateTime, string format, IFormatProvider provider, string expected)
- {
- var destination = new char[expected.Length];
-
- Assert.False(dateTime.TryFormat(destination.AsSpan(0, destination.Length - 1), out _, format, provider));
-
- Assert.True(dateTime.TryFormat(destination, out int charsWritten, format, provider));
- Assert.Equal(destination.Length, charsWritten);
- Assert.Equal(expected, new string(destination));
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidInput_Succeeds_MemberData))]
- public static void Parse_Span_ValidInput_Succeeds(string input, CultureInfo culture, DateTime? expected)
- {
- Assert.Equal(expected, DateTime.Parse(input.AsSpan(), culture));
- }
-
- [Theory]
- [MemberData(nameof(ParseExact_ValidInput_Succeeds_MemberData))]
- public static void ParseExact_Span_ValidInput_Succeeds(string input, string format, CultureInfo culture, DateTimeStyles style, DateTime? expected)
- {
- DateTime result1 = DateTime.ParseExact(input.AsSpan(), format, culture, style);
- DateTime result2 = DateTime.ParseExact(input.AsSpan(), new[] { format }, culture, style);
-
- Assert.True(DateTime.TryParseExact(input.AsSpan(), format, culture, style, out DateTime result3));
- Assert.True(DateTime.TryParseExact(input.AsSpan(), new[] { format }, culture, style, out DateTime result4));
-
- Assert.Equal(result1, result2);
- Assert.Equal(result1, result3);
- Assert.Equal(result1, result4);
-
- if (expected != null) // some inputs don't roundtrip well
- {
- // Normalize values to make comparison easier
- if (expected.Value.Kind != DateTimeKind.Utc)
- {
- expected = expected.Value.ToUniversalTime();
- }
- if (result1.Kind != DateTimeKind.Utc)
- {
- result1 = result1.ToUniversalTime();
- }
-
- Assert.Equal(expected, result1);
- }
- }
-
- [Theory]
- [MemberData(nameof(ParseExact_InvalidInputs_Fail_MemberData))]
- public static void ParseExact_Span_InvalidInputs_Fail(string input, string format, CultureInfo culture, DateTimeStyles style)
- {
- Assert.Throws<FormatException>(() => DateTime.ParseExact(input.AsSpan(), format, culture, style));
- Assert.Throws<FormatException>(() => DateTime.ParseExact(input.AsSpan(), new[] { format }, culture, style));
-
- Assert.False(DateTime.TryParseExact(input.AsSpan(), format, culture, style, out DateTime result));
- Assert.False(DateTime.TryParseExact(input.AsSpan(), new[] { format }, culture, style, out result));
- }
-
- [Fact]
- public static void UnixEpoch()
- {
- VerifyDateTime(DateTime.UnixEpoch, 1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
- }
- }
-}
namespace System.Tests
{
- public partial class DecimalTests
+ public class DecimalTests
{
[Fact]
public void MaxValue_Get_ReturnsExpected()
return new BigDecimal(res, (byte)scale);
}
}
+
+ [Theory]
+ [InlineData(MidpointRounding.ToEven - 1)]
+ [InlineData(MidpointRounding.ToPositiveInfinity + 1)]
+ public void Round_InvalidMidpointRounding_ThrowsArgumentException(MidpointRounding mode)
+ {
+ AssertExtensions.Throws<ArgumentException>("mode", () => decimal.Round(1, 2, mode));
+ }
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ yield return new object[] { "-123", 1, 3, NumberStyles.Number, null, 123m };
+ yield return new object[] { "-123", 0, 3, NumberStyles.Number, null, -12m };
+ yield return new object[] { 1000.ToString("N0"), 0, 4, NumberStyles.AllowThousands, null, 100m };
+ yield return new object[] { 1000.ToString("N0"), 2, 3, NumberStyles.AllowThousands, null, 0m };
+ yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, new NumberFormatInfo() { NumberDecimalSeparator = "." }, 123m };
+ yield return new object[] { "1234567890123456789012345.678456", 1, 4, NumberStyles.Number, new NumberFormatInfo() { NumberDecimalSeparator = "." }, 2345m };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, decimal expected)
+ {
+ bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo;
+ decimal result;
+ if ((style & ~NumberStyles.Number) == 0 && style != NumberStyles.None)
+ {
+ // Use Parse(string) or Parse(string, IFormatProvider)
+ if (isDefaultProvider)
+ {
+ Assert.True(decimal.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+
+ Assert.Equal(expected, decimal.Parse(value.AsSpan(offset, count)));
+ }
+
+ Assert.Equal(expected, decimal.Parse(value.AsSpan(offset, count), provider: provider));
+ }
+
+ Assert.Equal(expected, decimal.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(decimal.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ Assert.Throws(exceptionType, () => decimal.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(decimal.TryParse(value.AsSpan(), style, provider, out decimal result));
+ Assert.Equal(0, result);
+ }
+ }
+
+ [Fact]
+ public static void TryFormat()
+ {
+ using (new ThreadCultureChange(CultureInfo.InvariantCulture))
+ {
+ foreach (object[] testdata in ToString_TestData())
+ {
+ decimal localI = (decimal)testdata[0];
+ string localFormat = (string)testdata[1];
+ IFormatProvider localProvider = (IFormatProvider)testdata[2];
+ string localExpected = (string)testdata[3];
+
+ try
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[localExpected.Length];
+ Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
+ Assert.Equal(localExpected.Length, charsWritten);
+ Assert.Equal(localExpected, new string(actual));
+
+ // Longer than needed
+ actual = new char[localExpected.Length + 1];
+ Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
+ Assert.Equal(localExpected.Length, charsWritten);
+ Assert.Equal(localExpected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (localExpected.Length > 0)
+ {
+ actual = new char[localExpected.Length - 1];
+ Assert.False(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
+ Assert.Equal(0, charsWritten);
+ }
+
+ if (localFormat != null)
+ {
+ // Upper localFormat
+ actual = new char[localExpected.Length];
+ Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat.ToUpperInvariant(), localProvider));
+ Assert.Equal(localExpected.Length, charsWritten);
+ Assert.Equal(localExpected.ToUpperInvariant(), new string(actual));
+
+ // Lower format
+ actual = new char[localExpected.Length];
+ Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat.ToLowerInvariant(), localProvider));
+ Assert.Equal(localExpected.Length, charsWritten);
+ Assert.Equal(localExpected.ToLowerInvariant(), new string(actual));
+ }
+ }
+ catch (Exception exc)
+ {
+ throw new Exception($"Failed on `{localI}`, `{localFormat}`, `{localProvider}`, `{localExpected}`. {exc}");
+ }
+ }
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Microsoft.DotNet.RemoteExecutor;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class DecimalTests
- {
- [Theory]
- [InlineData(MidpointRounding.ToEven - 1)]
- [InlineData(MidpointRounding.ToPositiveInfinity + 1)]
- public void Round_InvalidMidpointRounding_ThrowsArgumentException(MidpointRounding mode)
- {
- AssertExtensions.Throws<ArgumentException>("mode", () => decimal.Round(1, 2, mode));
- }
-
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- yield return new object[] { "-123", 1, 3, NumberStyles.Number, null, 123m };
- yield return new object[] { "-123", 0, 3, NumberStyles.Number, null, -12m };
- yield return new object[] { 1000.ToString("N0"), 0, 4, NumberStyles.AllowThousands, null, 100m };
- yield return new object[] { 1000.ToString("N0"), 2, 3, NumberStyles.AllowThousands, null, 0m };
- yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, new NumberFormatInfo() { NumberDecimalSeparator = "." }, 123m };
- yield return new object[] { "1234567890123456789012345.678456", 1, 4, NumberStyles.Number, new NumberFormatInfo() { NumberDecimalSeparator = "." }, 2345m };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, decimal expected)
- {
- bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo;
- decimal result;
- if ((style & ~NumberStyles.Number) == 0 && style != NumberStyles.None)
- {
- // Use Parse(string) or Parse(string, IFormatProvider)
- if (isDefaultProvider)
- {
- Assert.True(decimal.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
-
- Assert.Equal(expected, decimal.Parse(value.AsSpan(offset, count)));
- }
-
- Assert.Equal(expected, decimal.Parse(value.AsSpan(offset, count), provider: provider));
- }
-
- Assert.Equal(expected, decimal.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(decimal.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- Assert.Throws(exceptionType, () => decimal.Parse(value.AsSpan(), style, provider));
-
- Assert.False(decimal.TryParse(value.AsSpan(), style, provider, out decimal result));
- Assert.Equal(0, result);
- }
- }
-
- [Fact]
- public static void TryFormat()
- {
- using (new ThreadCultureChange(CultureInfo.InvariantCulture))
- {
- foreach (object[] testdata in ToString_TestData())
- {
- decimal localI = (decimal)testdata[0];
- string localFormat = (string)testdata[1];
- IFormatProvider localProvider = (IFormatProvider)testdata[2];
- string localExpected = (string)testdata[3];
-
- try
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[localExpected.Length];
- Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
- Assert.Equal(localExpected.Length, charsWritten);
- Assert.Equal(localExpected, new string(actual));
-
- // Longer than needed
- actual = new char[localExpected.Length + 1];
- Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
- Assert.Equal(localExpected.Length, charsWritten);
- Assert.Equal(localExpected, new string(actual, 0, charsWritten));
-
- // Too short
- if (localExpected.Length > 0)
- {
- actual = new char[localExpected.Length - 1];
- Assert.False(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
- Assert.Equal(0, charsWritten);
- }
-
- if (localFormat != null)
- {
- // Upper localFormat
- actual = new char[localExpected.Length];
- Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat.ToUpperInvariant(), localProvider));
- Assert.Equal(localExpected.Length, charsWritten);
- Assert.Equal(localExpected.ToUpperInvariant(), new string(actual));
-
- // Lower format
- actual = new char[localExpected.Length];
- Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat.ToLowerInvariant(), localProvider));
- Assert.Equal(localExpected.Length, charsWritten);
- Assert.Equal(localExpected.ToLowerInvariant(), new string(actual));
- }
- }
- catch (Exception exc)
- {
- throw new Exception($"Failed on `{localI}`, `{localFormat}`, `{localProvider}`, `{localExpected}`. {exc}");
- }
- }
- }
- }
- }
-}
namespace System.Tests
{
- public partial class DoubleTests
+ public class DoubleTests
{
// NOTE: Consider duplicating any tests added here in SingleTests.cs
Assert.Throws<FormatException>(() => d.ToString("Y")); // Invalid format
Assert.Throws<FormatException>(() => d.ToString("Y", null)); // Invalid format
}
+
+ [Theory]
+ [InlineData(double.NegativeInfinity, false)] // Negative Infinity
+ [InlineData(double.MinValue, true)] // Min Negative Normal
+ [InlineData(-2.2250738585072014E-308, true)] // Max Negative Normal
+ [InlineData(-2.2250738585072009E-308, true)] // Min Negative Subnormal
+ [InlineData(-4.94065645841247E-324, true)] // Max Negative Subnormal
+ [InlineData(-0.0, true)] // Negative Zero
+ [InlineData(double.NaN, false)] // NaN
+ [InlineData(0.0, true)] // Positive Zero
+ [InlineData(4.94065645841247E-324, true)] // Min Positive Subnormal
+ [InlineData(2.2250738585072009E-308, true)] // Max Positive Subnormal
+ [InlineData(2.2250738585072014E-308, true)] // Min Positive Normal
+ [InlineData(double.MaxValue, true)] // Max Positive Normal
+ [InlineData(double.PositiveInfinity, false)] // Positive Infinity
+ public static void IsFinite(double d, bool expected)
+ {
+ Assert.Equal(expected, double.IsFinite(d));
+ }
+
+ [Theory]
+ [InlineData(double.NegativeInfinity, true)] // Negative Infinity
+ [InlineData(double.MinValue, true)] // Min Negative Normal
+ [InlineData(-2.2250738585072014E-308, true)] // Max Negative Normal
+ [InlineData(-2.2250738585072009E-308, true)] // Min Negative Subnormal
+ [InlineData(-4.94065645841247E-324, true)] // Max Negative Subnormal
+ [InlineData(-0.0, true)] // Negative Zero
+ [InlineData(double.NaN, true)] // NaN
+ [InlineData(0.0, false)] // Positive Zero
+ [InlineData(4.94065645841247E-324, false)] // Min Positive Subnormal
+ [InlineData(2.2250738585072009E-308, false)] // Max Positive Subnormal
+ [InlineData(2.2250738585072014E-308, false)] // Min Positive Normal
+ [InlineData(double.MaxValue, false)] // Max Positive Normal
+ [InlineData(double.PositiveInfinity, false)] // Positive Infinity
+ public static void IsNegative(double d, bool expected)
+ {
+ Assert.Equal(expected, double.IsNegative(d));
+ }
+
+ [Theory]
+ [InlineData(double.NegativeInfinity, false)] // Negative Infinity
+ [InlineData(double.MinValue, true)] // Min Negative Normal
+ [InlineData(-2.2250738585072014E-308, true)] // Max Negative Normal
+ [InlineData(-2.2250738585072009E-308, false)] // Min Negative Subnormal
+ [InlineData(-4.94065645841247E-324, false)] // Max Negative Subnormal
+ [InlineData(-0.0, false)] // Negative Zero
+ [InlineData(double.NaN, false)] // NaN
+ [InlineData(0.0, false)] // Positive Zero
+ [InlineData(4.94065645841247E-324, false)] // Min Positive Subnormal
+ [InlineData(2.2250738585072009E-308, false)] // Max Positive Subnormal
+ [InlineData(2.2250738585072014E-308, true)] // Min Positive Normal
+ [InlineData(double.MaxValue, true)] // Max Positive Normal
+ [InlineData(double.PositiveInfinity, false)] // Positive Infinity
+ public static void IsNormal(double d, bool expected)
+ {
+ Assert.Equal(expected, double.IsNormal(d));
+ }
+
+ [Theory]
+ [InlineData(double.NegativeInfinity, false)] // Negative Infinity
+ [InlineData(double.MinValue, false)] // Min Negative Normal
+ [InlineData(-2.2250738585072014E-308, false)] // Max Negative Normal
+ [InlineData(-2.2250738585072009E-308, true)] // Min Negative Subnormal
+ [InlineData(-4.94065645841247E-324, true)] // Max Negative Subnormal
+ [InlineData(-0.0, false)] // Negative Zero
+ [InlineData(double.NaN, false)] // NaN
+ [InlineData(0.0, false)] // Positive Zero
+ [InlineData(4.94065645841247E-324, true)] // Min Positive Subnormal
+ [InlineData(2.2250738585072009E-308, true)] // Max Positive Subnormal
+ [InlineData(2.2250738585072014E-308, false)] // Min Positive Normal
+ [InlineData(double.MaxValue, false)] // Max Positive Normal
+ [InlineData(double.PositiveInfinity, false)] // Positive Infinity
+ public static void IsSubnormal(double d, bool expected)
+ {
+ Assert.Equal(expected, double.IsSubnormal(d));
+ }
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ const NumberStyles DefaultStyle = NumberStyles.Float | NumberStyles.AllowThousands;
+ yield return new object[] { "-123", 0, 3, DefaultStyle, null, (double)-12 };
+ yield return new object[] { "-123", 1, 3, DefaultStyle, null, (double)123 };
+ yield return new object[] { "1E23", 0, 3, DefaultStyle, null, 1E2 };
+ yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, new NumberFormatInfo() { NumberDecimalSeparator = "." }, 123 };
+ yield return new object[] { "-Infinity", 1, 8, NumberStyles.Any, NumberFormatInfo.InvariantInfo, double.PositiveInfinity };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, double expected)
+ {
+ bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo;
+ double result;
+ if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None)
+ {
+ // Use Parse(string) or Parse(string, IFormatProvider)
+ if (isDefaultProvider)
+ {
+ Assert.True(double.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+
+ Assert.Equal(expected, double.Parse(value.AsSpan(offset, count)));
+ }
+
+ Assert.Equal(expected, double.Parse(value.AsSpan(offset, count), provider: provider));
+ }
+
+ Assert.Equal(expected, double.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(double.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ Assert.Throws(exceptionType, () => double.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(double.TryParse(value.AsSpan(), style, provider, out double result));
+ Assert.Equal(0, result);
+ }
+ }
+
+ [Fact]
+ public static void TryFormat()
+ {
+ using (new ThreadCultureChange(CultureInfo.InvariantCulture))
+ {
+ foreach (var testdata in ToString_TestData_NotNetFramework())
+ {
+ double localI = (double)testdata[0];
+ string localFormat = (string)testdata[1];
+ IFormatProvider localProvider = (IFormatProvider)testdata[2];
+ string localExpected = (string)testdata[3];
+
+ try
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[localExpected.Length];
+ Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
+ Assert.Equal(localExpected.Length, charsWritten);
+ Assert.Equal(localExpected, new string(actual));
+
+ // Longer than needed
+ actual = new char[localExpected.Length + 1];
+ Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
+ Assert.Equal(localExpected.Length, charsWritten);
+ Assert.Equal(localExpected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (localExpected.Length > 0)
+ {
+ actual = new char[localExpected.Length - 1];
+ Assert.False(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
+ Assert.Equal(0, charsWritten);
+ }
+ }
+ catch (Exception exc)
+ {
+ throw new Exception($"Failed on `{localI}`, `{localFormat}`, `{localProvider}`, `{localExpected}`. {exc}");
+ }
+ }
+ }
+ }
+
+ public static IEnumerable<object[]> ToStringRoundtrip_TestData()
+ {
+ yield return new object[] { double.NegativeInfinity };
+ yield return new object[] { double.MinValue };
+ yield return new object[] { -Math.PI };
+ yield return new object[] { -Math.E };
+ yield return new object[] { -double.Epsilon };
+ yield return new object[] { -0.84551240822557006 };
+ yield return new object[] { -0.0 };
+ yield return new object[] { double.NaN };
+ yield return new object[] { 0.0 };
+ yield return new object[] { 0.84551240822557006 };
+ yield return new object[] { double.Epsilon };
+ yield return new object[] { Math.E };
+ yield return new object[] { Math.PI };
+ yield return new object[] { double.MaxValue };
+ yield return new object[] { double.PositiveInfinity };
+ }
+
+ [Theory]
+ [MemberData(nameof(ToStringRoundtrip_TestData))]
+ public static void ToStringRoundtrip(double value)
+ {
+ double result = double.Parse(value.ToString());
+ Assert.Equal(BitConverter.DoubleToInt64Bits(value), BitConverter.DoubleToInt64Bits(result));
+ }
+
+ [Theory]
+ [MemberData(nameof(ToStringRoundtrip_TestData))]
+ public static void ToStringRoundtrip_R(double value)
+ {
+ double result = double.Parse(value.ToString("R"));
+ Assert.Equal(BitConverter.DoubleToInt64Bits(value), BitConverter.DoubleToInt64Bits(result));
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Microsoft.DotNet.RemoteExecutor;
-using Xunit;
-
-#pragma warning disable xUnit1025 // reporting duplicate test cases due to not distinguishing 0.0 from -0.0, NaN from -NaN
-
-namespace System.Tests
-{
- public partial class DoubleTests
- {
- [Theory]
- [InlineData(double.NegativeInfinity, false)] // Negative Infinity
- [InlineData(double.MinValue, true)] // Min Negative Normal
- [InlineData(-2.2250738585072014E-308, true)] // Max Negative Normal
- [InlineData(-2.2250738585072009E-308, true)] // Min Negative Subnormal
- [InlineData(-4.94065645841247E-324, true)] // Max Negative Subnormal
- [InlineData(-0.0, true)] // Negative Zero
- [InlineData(double.NaN, false)] // NaN
- [InlineData(0.0, true)] // Positive Zero
- [InlineData(4.94065645841247E-324, true)] // Min Positive Subnormal
- [InlineData(2.2250738585072009E-308, true)] // Max Positive Subnormal
- [InlineData(2.2250738585072014E-308, true)] // Min Positive Normal
- [InlineData(double.MaxValue, true)] // Max Positive Normal
- [InlineData(double.PositiveInfinity, false)] // Positive Infinity
- public static void IsFinite(double d, bool expected)
- {
- Assert.Equal(expected, double.IsFinite(d));
- }
-
- [Theory]
- [InlineData(double.NegativeInfinity, true)] // Negative Infinity
- [InlineData(double.MinValue, true)] // Min Negative Normal
- [InlineData(-2.2250738585072014E-308, true)] // Max Negative Normal
- [InlineData(-2.2250738585072009E-308, true)] // Min Negative Subnormal
- [InlineData(-4.94065645841247E-324, true)] // Max Negative Subnormal
- [InlineData(-0.0, true)] // Negative Zero
- [InlineData(double.NaN, true)] // NaN
- [InlineData(0.0, false)] // Positive Zero
- [InlineData(4.94065645841247E-324, false)] // Min Positive Subnormal
- [InlineData(2.2250738585072009E-308, false)] // Max Positive Subnormal
- [InlineData(2.2250738585072014E-308, false)] // Min Positive Normal
- [InlineData(double.MaxValue, false)] // Max Positive Normal
- [InlineData(double.PositiveInfinity, false)] // Positive Infinity
- public static void IsNegative(double d, bool expected)
- {
- Assert.Equal(expected, double.IsNegative(d));
- }
-
- [Theory]
- [InlineData(double.NegativeInfinity, false)] // Negative Infinity
- [InlineData(double.MinValue, true)] // Min Negative Normal
- [InlineData(-2.2250738585072014E-308, true)] // Max Negative Normal
- [InlineData(-2.2250738585072009E-308, false)] // Min Negative Subnormal
- [InlineData(-4.94065645841247E-324, false)] // Max Negative Subnormal
- [InlineData(-0.0, false)] // Negative Zero
- [InlineData(double.NaN, false)] // NaN
- [InlineData(0.0, false)] // Positive Zero
- [InlineData(4.94065645841247E-324, false)] // Min Positive Subnormal
- [InlineData(2.2250738585072009E-308, false)] // Max Positive Subnormal
- [InlineData(2.2250738585072014E-308, true)] // Min Positive Normal
- [InlineData(double.MaxValue, true)] // Max Positive Normal
- [InlineData(double.PositiveInfinity, false)] // Positive Infinity
- public static void IsNormal(double d, bool expected)
- {
- Assert.Equal(expected, double.IsNormal(d));
- }
-
- [Theory]
- [InlineData(double.NegativeInfinity, false)] // Negative Infinity
- [InlineData(double.MinValue, false)] // Min Negative Normal
- [InlineData(-2.2250738585072014E-308, false)] // Max Negative Normal
- [InlineData(-2.2250738585072009E-308, true)] // Min Negative Subnormal
- [InlineData(-4.94065645841247E-324, true)] // Max Negative Subnormal
- [InlineData(-0.0, false)] // Negative Zero
- [InlineData(double.NaN, false)] // NaN
- [InlineData(0.0, false)] // Positive Zero
- [InlineData(4.94065645841247E-324, true)] // Min Positive Subnormal
- [InlineData(2.2250738585072009E-308, true)] // Max Positive Subnormal
- [InlineData(2.2250738585072014E-308, false)] // Min Positive Normal
- [InlineData(double.MaxValue, false)] // Max Positive Normal
- [InlineData(double.PositiveInfinity, false)] // Positive Infinity
- public static void IsSubnormal(double d, bool expected)
- {
- Assert.Equal(expected, double.IsSubnormal(d));
- }
-
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- const NumberStyles DefaultStyle = NumberStyles.Float | NumberStyles.AllowThousands;
- yield return new object[] { "-123", 0, 3, DefaultStyle, null, (double)-12 };
- yield return new object[] { "-123", 1, 3, DefaultStyle, null, (double)123 };
- yield return new object[] { "1E23", 0, 3, DefaultStyle, null, 1E2 };
- yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, new NumberFormatInfo() { NumberDecimalSeparator = "." }, 123 };
- yield return new object[] { "-Infinity", 1, 8, NumberStyles.Any, NumberFormatInfo.InvariantInfo, double.PositiveInfinity };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, double expected)
- {
- bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo;
- double result;
- if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None)
- {
- // Use Parse(string) or Parse(string, IFormatProvider)
- if (isDefaultProvider)
- {
- Assert.True(double.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
-
- Assert.Equal(expected, double.Parse(value.AsSpan(offset, count)));
- }
-
- Assert.Equal(expected, double.Parse(value.AsSpan(offset, count), provider: provider));
- }
-
- Assert.Equal(expected, double.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(double.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- Assert.Throws(exceptionType, () => double.Parse(value.AsSpan(), style, provider));
-
- Assert.False(double.TryParse(value.AsSpan(), style, provider, out double result));
- Assert.Equal(0, result);
- }
- }
-
- [Fact]
- public static void TryFormat()
- {
- using (new ThreadCultureChange(CultureInfo.InvariantCulture))
- {
- foreach (var testdata in ToString_TestData_NotNetFramework())
- {
- double localI = (double)testdata[0];
- string localFormat = (string)testdata[1];
- IFormatProvider localProvider = (IFormatProvider)testdata[2];
- string localExpected = (string)testdata[3];
-
- try
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[localExpected.Length];
- Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
- Assert.Equal(localExpected.Length, charsWritten);
- Assert.Equal(localExpected, new string(actual));
-
- // Longer than needed
- actual = new char[localExpected.Length + 1];
- Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
- Assert.Equal(localExpected.Length, charsWritten);
- Assert.Equal(localExpected, new string(actual, 0, charsWritten));
-
- // Too short
- if (localExpected.Length > 0)
- {
- actual = new char[localExpected.Length - 1];
- Assert.False(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
- Assert.Equal(0, charsWritten);
- }
- }
- catch (Exception exc)
- {
- throw new Exception($"Failed on `{localI}`, `{localFormat}`, `{localProvider}`, `{localExpected}`. {exc}");
- }
- }
- }
- }
-
- public static IEnumerable<object[]> ToStringRoundtrip_TestData()
- {
- yield return new object[] { double.NegativeInfinity };
- yield return new object[] { double.MinValue };
- yield return new object[] { -Math.PI };
- yield return new object[] { -Math.E };
- yield return new object[] { -double.Epsilon };
- yield return new object[] { -0.84551240822557006 };
- yield return new object[] { -0.0 };
- yield return new object[] { double.NaN };
- yield return new object[] { 0.0 };
- yield return new object[] { 0.84551240822557006 };
- yield return new object[] { double.Epsilon };
- yield return new object[] { Math.E };
- yield return new object[] { Math.PI };
- yield return new object[] { double.MaxValue };
- yield return new object[] { double.PositiveInfinity };
- }
-
- [Theory]
- [MemberData(nameof(ToStringRoundtrip_TestData))]
- public static void ToStringRoundtrip(double value)
- {
- double result = double.Parse(value.ToString());
- Assert.Equal(BitConverter.DoubleToInt64Bits(value), BitConverter.DoubleToInt64Bits(result));
- }
-
- [Theory]
- [MemberData(nameof(ToStringRoundtrip_TestData))]
- public static void ToStringRoundtrip_R(double value)
- {
- double result = double.Parse(value.ToString("R"));
- Assert.Equal(BitConverter.DoubleToInt64Bits(value), BitConverter.DoubleToInt64Bits(result));
- }
- }
-}
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.Reflection.Emit;
using Xunit;
namespace System.Tests
{
- public partial class EnumTests
+ public class EnumTests
{
public static IEnumerable<object[]> Parse_TestData()
{
Assert.Equal(expected, result);
Assert.Equal(expected, Enum.Parse(expected.GetType(), value));
+ Assert.Equal(expected, Enum.Parse<T>(value));
}
Assert.True(Enum.TryParse(value, ignoreCase, out result));
Assert.Equal(expected, result);
Assert.Equal(expected, Enum.Parse(expected.GetType(), value, ignoreCase));
+ Assert.Equal(expected, Enum.Parse<T>(value, ignoreCase));
}
public static IEnumerable<object[]> Parse_Invalid_TestData()
private static void Parse_Generic_Invalid<T>(Type enumType, string value, bool ignoreCase, Type exceptionType) where T : struct
{
- T result;
+ object result = null;
if (!ignoreCase)
{
- Assert.False(Enum.TryParse(value, out result));
- Assert.Equal(default(T), result);
-
- Assert.Throws(exceptionType, () => Enum.Parse(enumType, value));
+ if (enumType != null && enumType.IsEnum)
+ {
+ Assert.False(Enum.TryParse(enumType, value, out result));
+ Assert.Equal(default(object), result);
+
+ Assert.Throws(exceptionType, () => Enum.Parse<T>(value));
+ }
+ else
+ {
+ Assert.Throws(exceptionType, () => Enum.TryParse(enumType, value, out result));
+ Assert.Equal(default(object), result);
+ }
}
- Assert.False(Enum.TryParse(value, ignoreCase, out result));
- Assert.Equal(default(T), result);
+ if (enumType != null && enumType.IsEnum)
+ {
+ Assert.False(Enum.TryParse(enumType, value, ignoreCase, out result));
+ Assert.Equal(default(object), result);
- Assert.Throws(exceptionType, () => Enum.Parse(enumType, value, ignoreCase));
+ Assert.Throws(exceptionType, () => Enum.Parse<T>(value, ignoreCase));
+ }
+ else
+ {
+ Assert.Throws(exceptionType, () => Enum.TryParse(enumType, value, ignoreCase, out result));
+ Assert.Equal(default(object), result);
+ }
}
public static IEnumerable<object[]> GetName_TestData()
Assert.Throws<FormatException>(() => Enum.Format(typeof(SimpleEnum), SimpleEnum.Red, " \t")); // Format is whitespace
Assert.Throws<FormatException>(() => Enum.Format(typeof(SimpleEnum), SimpleEnum.Red, "t")); // No such format
}
+
+ public static IEnumerable<object[]> UnsupportedEnumType_TestData()
+ {
+#if NETCOREAPP
+ yield return new object[] { s_floatEnumType, 1.0f };
+ yield return new object[] { s_doubleEnumType, 1.0 };
+ yield return new object[] { s_intPtrEnumType, (IntPtr)1 };
+ yield return new object[] { s_uintPtrEnumType, (UIntPtr)1 };
+#else
+ return Array.Empty<object[]>();
+#endif
+ }
+
+ [Theory]
+ [MemberData(nameof(UnsupportedEnumType_TestData))]
+ public static void GetName_Unsupported_ThrowsArgumentException(Type enumType, object value)
+ {
+ AssertExtensions.Throws<ArgumentException>("value", () => Enum.GetName(enumType, value));
+ }
+
+ [Theory]
+ [MemberData(nameof(UnsupportedEnumType_TestData))]
+ public static void IsDefined_UnsupportedEnumType_ThrowsInvalidOperationException(Type enumType, object value)
+ {
+ Exception ex = Assert.ThrowsAny<Exception>(() => Enum.IsDefined(enumType, value));
+ string exName = ex.GetType().Name;
+ Assert.True(exName == nameof(InvalidOperationException) || exName == "ContractException");
+ }
+
+ public static IEnumerable<object[]> UnsupportedEnum_TestData()
+ {
+ yield return new object[] { Enum.ToObject(s_floatEnumType, 1) };
+ yield return new object[] { Enum.ToObject(s_doubleEnumType, 2) };
+ yield return new object[] { Enum.ToObject(s_intPtrEnumType, 1) };
+ yield return new object[] { Enum.ToObject(s_uintPtrEnumType, 2) };
+ }
+
+ [Theory]
+ [MemberData(nameof(UnsupportedEnum_TestData))]
+ public static void ToString_UnsupportedEnumType_ThrowsArgumentException(Enum e)
+ {
+ Exception formatXException = Assert.ThrowsAny<Exception>(() => e.ToString("X"));
+ string formatXExceptionName = formatXException.GetType().Name;
+ Assert.True(formatXExceptionName == nameof(InvalidOperationException) || formatXExceptionName == "ContractException");
+ }
+
+ [Theory]
+ [MemberData(nameof(UnsupportedEnumType_TestData))]
+ public static void Format_UnsupportedEnumType_ThrowsArgumentException(Type enumType, object value)
+ {
+ Exception formatGException = Assert.ThrowsAny<Exception>(() => Enum.Format(enumType, value, "G"));
+ string formatGExceptionName = formatGException.GetType().Name;
+ Assert.True(formatGExceptionName == nameof(InvalidOperationException) || formatGExceptionName == "ContractException");
+
+ Exception formatXException = Assert.ThrowsAny<Exception>(() => Enum.Format(enumType, value, "X"));
+ string formatXExceptionName = formatXException.GetType().Name;
+ Assert.True(formatXExceptionName == nameof(InvalidOperationException) || formatXExceptionName == "ContractException");
+
+ Exception formatFException = Assert.ThrowsAny<Exception>(() => Enum.Format(enumType, value, "F"));
+ string formatFExceptionName = formatFException.GetType().Name;
+ Assert.True(formatFExceptionName == nameof(InvalidOperationException) || formatFExceptionName == "ContractException");
+ }
+
+ private static EnumBuilder GetNonRuntimeEnumTypeBuilder(Type underlyingType)
+ {
+ AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.Run);
+ ModuleBuilder module = assembly.DefineDynamicModule("Name");
+
+ return module.DefineEnum("TestName_" + underlyingType.Name, TypeAttributes.Public, underlyingType);
+ }
+
+ private static Type s_boolEnumType = GetBoolEnumType();
+ private static Type GetBoolEnumType()
+ {
+ EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(bool));
+ enumBuilder.DefineLiteral("Value1", true);
+ enumBuilder.DefineLiteral("Value2", false);
+
+ return enumBuilder.CreateTypeInfo().AsType();
+ }
+
+ private static Type s_charEnumType = GetCharEnumType();
+ private static Type GetCharEnumType()
+ {
+ EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(char));
+ enumBuilder.DefineLiteral("Value1", (char)1);
+ enumBuilder.DefineLiteral("Value2", (char)2);
+
+ enumBuilder.DefineLiteral("Value0x3f06", (char)0x3f06);
+ enumBuilder.DefineLiteral("Value0x3000", (char)0x3000);
+ enumBuilder.DefineLiteral("Value0x0f06", (char)0x0f06);
+ enumBuilder.DefineLiteral("Value0x1000", (char)0x1000);
+ enumBuilder.DefineLiteral("Value0x0000", (char)0x0000);
+ enumBuilder.DefineLiteral("Value0x0010", (char)0x0010);
+ enumBuilder.DefineLiteral("Value0x3f16", (char)0x3f16);
+
+ return enumBuilder.CreateTypeInfo().AsType();
+ }
+
+ private static Type s_floatEnumType = GetFloatEnumType();
+ private static Type GetFloatEnumType()
+ {
+ EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(float));
+ enumBuilder.DefineLiteral("Value1", 1.0f);
+ enumBuilder.DefineLiteral("Value2", 2.0f);
+
+ enumBuilder.DefineLiteral("Value0x3f06", (float)0x3f06);
+ enumBuilder.DefineLiteral("Value0x3000", (float)0x3000);
+ enumBuilder.DefineLiteral("Value0x0f06", (float)0x0f06);
+ enumBuilder.DefineLiteral("Value0x1000", (float)0x1000);
+ enumBuilder.DefineLiteral("Value0x0000", (float)0x0000);
+ enumBuilder.DefineLiteral("Value0x0010", (float)0x0010);
+ enumBuilder.DefineLiteral("Value0x3f16", (float)0x3f16);
+
+ return enumBuilder.CreateTypeInfo().AsType();
+ }
+
+ private static Type s_doubleEnumType = GetDoubleEnumType();
+ private static Type GetDoubleEnumType()
+ {
+ EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(double));
+ enumBuilder.DefineLiteral("Value1", 1.0);
+ enumBuilder.DefineLiteral("Value2", 2.0);
+
+ enumBuilder.DefineLiteral("Value0x3f06", (double)0x3f06);
+ enumBuilder.DefineLiteral("Value0x3000", (double)0x3000);
+ enumBuilder.DefineLiteral("Value0x0f06", (double)0x0f06);
+ enumBuilder.DefineLiteral("Value0x1000", (double)0x1000);
+ enumBuilder.DefineLiteral("Value0x0000", (double)0x0000);
+ enumBuilder.DefineLiteral("Value0x0010", (double)0x0010);
+ enumBuilder.DefineLiteral("Value0x3f16", (double)0x3f16);
+
+ return enumBuilder.CreateTypeInfo().AsType();
+ }
+
+ private static Type s_intPtrEnumType = GetIntPtrEnumType();
+ private static Type GetIntPtrEnumType()
+ {
+ EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(IntPtr));
+
+ return enumBuilder.CreateTypeInfo().AsType();
+ }
+
+ private static Type s_uintPtrEnumType = GetUIntPtrEnumType();
+ private static Type GetUIntPtrEnumType()
+ {
+ EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(UIntPtr));
+
+ return enumBuilder.CreateTypeInfo().AsType();
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Reflection;
-using System.Reflection.Emit;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class EnumTests
- {
- [Theory]
- [MemberData(nameof(Parse_TestData))]
- public static void Parse_NetCoreApp11<T>(string value, bool ignoreCase, T expected) where T : struct
- {
- object result;
- if (!ignoreCase)
- {
- Assert.True(Enum.TryParse(expected.GetType(), value, out result));
- Assert.Equal(expected, result);
-
- Assert.Equal(expected, Enum.Parse<T>(value));
- }
-
- Assert.True(Enum.TryParse(expected.GetType(), value, ignoreCase, out result));
- Assert.Equal(expected, result);
-
- Assert.Equal(expected, Enum.Parse<T>(value, ignoreCase));
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Invalid_NetCoreApp11(Type enumType, string value, bool ignoreCase, Type exceptionType)
- {
- Type typeArgument = enumType == null || !enumType.IsValueType ? typeof(SimpleEnum) : enumType;
- MethodInfo parseMethod = typeof(EnumTests).GetTypeInfo().GetMethod(nameof(Parse_Generic_Invalid_NetCoreApp11), BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(typeArgument);
- parseMethod.Invoke(null, new object[] { enumType, value, ignoreCase, exceptionType });
- }
-
- private static void Parse_Generic_Invalid_NetCoreApp11<T>(Type enumType, string value, bool ignoreCase, Type exceptionType) where T : struct
- {
- object result = null;
- if (!ignoreCase)
- {
- if (enumType != null && enumType.IsEnum)
- {
- Assert.False(Enum.TryParse(enumType, value, out result));
- Assert.Equal(default(object), result);
-
- Assert.Throws(exceptionType, () => Enum.Parse<T>(value));
- }
- else
- {
- Assert.Throws(exceptionType, () => Enum.TryParse(enumType, value, out result));
- Assert.Equal(default(object), result);
- }
- }
-
- if (enumType != null && enumType.IsEnum)
- {
- Assert.False(Enum.TryParse(enumType, value, ignoreCase, out result));
- Assert.Equal(default(object), result);
-
- Assert.Throws(exceptionType, () => Enum.Parse<T>(value, ignoreCase));
- }
- else
- {
- Assert.Throws(exceptionType, () => Enum.TryParse(enumType, value, ignoreCase, out result));
- Assert.Equal(default(object), result);
- }
- }
-
- public static IEnumerable<object[]> UnsupportedEnumType_TestData()
- {
-#if NETCOREAPP
- yield return new object[] { s_floatEnumType, 1.0f };
- yield return new object[] { s_doubleEnumType, 1.0 };
- yield return new object[] { s_intPtrEnumType, (IntPtr)1 };
- yield return new object[] { s_uintPtrEnumType, (UIntPtr)1 };
-#else
- return Array.Empty<object[]>();
-#endif
- }
-
- [Theory]
- [MemberData(nameof(UnsupportedEnumType_TestData))]
- public static void GetName_Unsupported_ThrowsArgumentException(Type enumType, object value)
- {
- AssertExtensions.Throws<ArgumentException>("value", () => Enum.GetName(enumType, value));
- }
-
- [Theory]
- [MemberData(nameof(UnsupportedEnumType_TestData))]
- public static void IsDefined_UnsupportedEnumType_ThrowsInvalidOperationException(Type enumType, object value)
- {
- Exception ex = Assert.ThrowsAny<Exception>(() => Enum.IsDefined(enumType, value));
- string exName = ex.GetType().Name;
- Assert.True(exName == nameof(InvalidOperationException) || exName == "ContractException");
- }
-
- public static IEnumerable<object[]> UnsupportedEnum_TestData()
- {
-#if NETCOREAPP
- yield return new object[] { Enum.ToObject(s_floatEnumType, 1) };
- yield return new object[] { Enum.ToObject(s_doubleEnumType, 2) };
- yield return new object[] { Enum.ToObject(s_intPtrEnumType, 1) };
- yield return new object[] { Enum.ToObject(s_uintPtrEnumType, 2) };
-#else
- return Array.Empty<object[]>();
-#endif
- }
-
- [Theory]
- [MemberData(nameof(UnsupportedEnum_TestData))]
- public static void ToString_UnsupportedEnumType_ThrowsArgumentException(Enum e)
- {
- Exception formatXException = Assert.ThrowsAny<Exception>(() => e.ToString("X"));
- string formatXExceptionName = formatXException.GetType().Name;
- Assert.True(formatXExceptionName == nameof(InvalidOperationException) || formatXExceptionName == "ContractException");
- }
-
- [Theory]
- [MemberData(nameof(UnsupportedEnumType_TestData))]
- public static void Format_UnsupportedEnumType_ThrowsArgumentException(Type enumType, object value)
- {
- Exception formatGException = Assert.ThrowsAny<Exception>(() => Enum.Format(enumType, value, "G"));
- string formatGExceptionName = formatGException.GetType().Name;
- Assert.True(formatGExceptionName == nameof(InvalidOperationException) || formatGExceptionName == "ContractException");
-
- Exception formatXException = Assert.ThrowsAny<Exception>(() => Enum.Format(enumType, value, "X"));
- string formatXExceptionName = formatXException.GetType().Name;
- Assert.True(formatXExceptionName == nameof(InvalidOperationException) || formatXExceptionName == "ContractException");
-
- Exception formatFException = Assert.ThrowsAny<Exception>(() => Enum.Format(enumType, value, "F"));
- string formatFExceptionName = formatFException.GetType().Name;
- Assert.True(formatFExceptionName == nameof(InvalidOperationException) || formatFExceptionName == "ContractException");
- }
-
- private static EnumBuilder GetNonRuntimeEnumTypeBuilder(Type underlyingType)
- {
- AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.Run);
- ModuleBuilder module = assembly.DefineDynamicModule("Name");
-
- return module.DefineEnum("TestName_" + underlyingType.Name, TypeAttributes.Public, underlyingType);
- }
-
- private static Type s_boolEnumType = GetBoolEnumType();
- private static Type GetBoolEnumType()
- {
- EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(bool));
- enumBuilder.DefineLiteral("Value1", true);
- enumBuilder.DefineLiteral("Value2", false);
-
- return enumBuilder.CreateTypeInfo().AsType();
- }
-
- private static Type s_charEnumType = GetCharEnumType();
- private static Type GetCharEnumType()
- {
- EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(char));
- enumBuilder.DefineLiteral("Value1", (char)1);
- enumBuilder.DefineLiteral("Value2", (char)2);
-
- enumBuilder.DefineLiteral("Value0x3f06", (char)0x3f06);
- enumBuilder.DefineLiteral("Value0x3000", (char)0x3000);
- enumBuilder.DefineLiteral("Value0x0f06", (char)0x0f06);
- enumBuilder.DefineLiteral("Value0x1000", (char)0x1000);
- enumBuilder.DefineLiteral("Value0x0000", (char)0x0000);
- enumBuilder.DefineLiteral("Value0x0010", (char)0x0010);
- enumBuilder.DefineLiteral("Value0x3f16", (char)0x3f16);
-
- return enumBuilder.CreateTypeInfo().AsType();
- }
-
- private static Type s_floatEnumType = GetFloatEnumType();
- private static Type GetFloatEnumType()
- {
- EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(float));
- enumBuilder.DefineLiteral("Value1", 1.0f);
- enumBuilder.DefineLiteral("Value2", 2.0f);
-
- enumBuilder.DefineLiteral("Value0x3f06", (float)0x3f06);
- enumBuilder.DefineLiteral("Value0x3000", (float)0x3000);
- enumBuilder.DefineLiteral("Value0x0f06", (float)0x0f06);
- enumBuilder.DefineLiteral("Value0x1000", (float)0x1000);
- enumBuilder.DefineLiteral("Value0x0000", (float)0x0000);
- enumBuilder.DefineLiteral("Value0x0010", (float)0x0010);
- enumBuilder.DefineLiteral("Value0x3f16", (float)0x3f16);
-
- return enumBuilder.CreateTypeInfo().AsType();
- }
-
- private static Type s_doubleEnumType = GetDoubleEnumType();
- private static Type GetDoubleEnumType()
- {
- EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(double));
- enumBuilder.DefineLiteral("Value1", 1.0);
- enumBuilder.DefineLiteral("Value2", 2.0);
-
- enumBuilder.DefineLiteral("Value0x3f06", (double)0x3f06);
- enumBuilder.DefineLiteral("Value0x3000", (double)0x3000);
- enumBuilder.DefineLiteral("Value0x0f06", (double)0x0f06);
- enumBuilder.DefineLiteral("Value0x1000", (double)0x1000);
- enumBuilder.DefineLiteral("Value0x0000", (double)0x0000);
- enumBuilder.DefineLiteral("Value0x0010", (double)0x0010);
- enumBuilder.DefineLiteral("Value0x3f16", (double)0x3f16);
-
- return enumBuilder.CreateTypeInfo().AsType();
- }
-
- private static Type s_intPtrEnumType = GetIntPtrEnumType();
- private static Type GetIntPtrEnumType()
- {
- EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(IntPtr));
-
- return enumBuilder.CreateTypeInfo().AsType();
- }
-
- private static Type s_uintPtrEnumType = GetUIntPtrEnumType();
- private static Type GetUIntPtrEnumType()
- {
- EnumBuilder enumBuilder = GetNonRuntimeEnumTypeBuilder(typeof(UIntPtr));
-
- return enumBuilder.CreateTypeInfo().AsType();
- }
- }
-}
namespace System.Tests
{
- public partial class FormattableStringTests
+ public class FormattableStringTests
{
[Fact]
public static void Invariant_Null_ThrowsArgumentNullException()
}
}
+ [Fact]
+ public static void CurrentCulture_ImplicityAndExplicitMethodsReturnSameString()
+ {
+ double d = 123.456;
+ string text1 = $"This will be formatted using current culture {d}";
+ string text2 = FormattableString.CurrentCulture($"This will be formatted using current culture {d}");
+ Assert.Equal(text1, text2);
+ }
+
+ [Fact]
+ public static void CurrentCulture_Null_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("formattable", () => FormattableString.CurrentCulture(null));
+ }
+
+ [Fact]
+ public static void CurrentCulture_DutchCulture_FormatsDoubleBasedOnCurrentCulture()
+ {
+ var dutchCulture = new CultureInfo("nl");
+ using (new ThreadCultureChange(dutchCulture))
+ {
+ double d = 123.456;
+ string expected = string.Format(dutchCulture, "Dutch decimal separator is comma {0}", d);
+ string actual = FormattableString.CurrentCulture($"Dutch decimal separator is comma {d}");
+ Assert.Equal(expected, actual);
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Globalization;
-using Microsoft.DotNet.RemoteExecutor;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class FormattableStringTests
- {
- [Fact]
- public static void CurrentCulture_ImplicityAndExplicitMethodsReturnSameString()
- {
- double d = 123.456;
- string text1 = $"This will be formatted using current culture {d}";
- string text2 = FormattableString.CurrentCulture($"This will be formatted using current culture {d}");
- Assert.Equal(text1, text2);
- }
-
- [Fact]
- public static void CurrentCulture_Null_ThrowsArgumentNullException()
- {
- AssertExtensions.Throws<ArgumentNullException>("formattable", () => FormattableString.CurrentCulture(null));
- }
-
- [Fact]
- public static void CurrentCulture_DutchCulture_FormatsDoubleBasedOnCurrentCulture()
- {
- var dutchCulture = new CultureInfo("nl");
- using (new ThreadCultureChange(dutchCulture))
- {
- double d = 123.456;
- string expected = string.Format(dutchCulture, "Dutch decimal separator is comma {0}", d);
- string actual = FormattableString.CurrentCulture($"Dutch decimal separator is comma {d}");
- Assert.Equal(expected, actual);
- }
- }
- }
-}
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
using System.Runtime;
namespace System.Tests
{
- public static partial class GCTests
+ public static class GCTests
{
private static bool s_is32Bits = IntPtr.Size == 4; // Skip IntPtr tests on 32-bit platforms
Thread.Sleep(500);
GC.CancelFullGCNotification();
}
+
+ [Theory]
+ [InlineData(1000)]
+ [InlineData(100000)]
+ public static void GetAllocatedBytesForCurrentThread(int size)
+ {
+ long start = GC.GetAllocatedBytesForCurrentThread();
+
+ GC.KeepAlive(new string('a', size));
+
+ long end = GC.GetAllocatedBytesForCurrentThread();
+
+ Assert.True((end - start) > size, $"Allocated too little: start: {start} end: {end} size: {size}");
+ Assert.True((end - start) < 5 * size, $"Allocated too much: start: {start} end: {end} size: {size}");
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))] // [ActiveIssue(37378)]
+ public static void GetGCMemoryInfo()
+ {
+ RemoteExecutor.Invoke(() =>
+ {
+ // Allows to update the value returned by GC.GetGCMemoryInfo
+ GC.Collect();
+
+ GCMemoryInfo memoryInfo1 = GC.GetGCMemoryInfo();
+
+ Assert.InRange(memoryInfo1.HighMemoryLoadThresholdBytes, 1, long.MaxValue);
+ Assert.InRange(memoryInfo1.MemoryLoadBytes, 1, long.MaxValue);
+ Assert.InRange(memoryInfo1.TotalAvailableMemoryBytes, 1, long.MaxValue);
+ Assert.InRange(memoryInfo1.HeapSizeBytes, 1, long.MaxValue);
+ Assert.InRange(memoryInfo1.FragmentedBytes, 0, long.MaxValue);
+
+ GCHandle[] gch = new GCHandle[64 * 1024];
+ for (int i = 0; i < gch.Length * 2; ++i)
+ {
+ byte[] arr = new byte[64];
+ if (i % 2 == 0)
+ {
+ gch[i / 2] = GCHandle.Alloc(arr, GCHandleType.Pinned);
+ }
+ }
+
+ // Allows to update the value returned by GC.GetGCMemoryInfo
+ GC.Collect();
+
+ GCMemoryInfo memoryInfo2 = GC.GetGCMemoryInfo();
+
+ string scenario = null;
+ try
+ {
+ scenario = nameof(memoryInfo2.HighMemoryLoadThresholdBytes);
+ Assert.Equal(memoryInfo2.HighMemoryLoadThresholdBytes, memoryInfo1.HighMemoryLoadThresholdBytes);
+
+ // Even though we have allocated, the overall load may decrease or increase depending what other processes are doing.
+ // It cannot go above total available though.
+ scenario = nameof(memoryInfo2.MemoryLoadBytes);
+ Assert.InRange(memoryInfo2.MemoryLoadBytes, 1, memoryInfo1.TotalAvailableMemoryBytes);
+
+ scenario = nameof(memoryInfo2.TotalAvailableMemoryBytes);
+ Assert.Equal(memoryInfo2.TotalAvailableMemoryBytes, memoryInfo1.TotalAvailableMemoryBytes);
+
+ scenario = nameof(memoryInfo2.HeapSizeBytes);
+ Assert.InRange(memoryInfo2.HeapSizeBytes, memoryInfo1.HeapSizeBytes + 1, long.MaxValue);
+
+ scenario = nameof(memoryInfo2.FragmentedBytes);
+ Assert.InRange(memoryInfo2.FragmentedBytes, memoryInfo1.FragmentedBytes + 1, long.MaxValue);
+
+ scenario = null;
+ }
+ finally
+ {
+ if (scenario != null)
+ {
+ System.Console.WriteLine("FAILED: " + scenario);
+ }
+ }
+ }).Dispose();
+ }
+
+ [Fact]
+ public static void GetTotalAllocatedBytes()
+ {
+ byte[] stash;
+
+ long CallGetTotalAllocatedBytesAndCheck(long previous, out long differenceBetweenPreciseAndImprecise)
+ {
+ long precise = GC.GetTotalAllocatedBytes(true);
+ long imprecise = GC.GetTotalAllocatedBytes(false);
+
+ if (precise <= 0)
+ {
+ throw new Exception($"Bytes allocated is not positive, this is unlikely. precise = {precise}");
+ }
+
+ if (imprecise < precise)
+ {
+ throw new Exception($"Imprecise total bytes allocated less than precise, imprecise is required to be a conservative estimate (that estimates high). imprecise = {imprecise}, precise = {precise}");
+ }
+
+ if (previous > precise)
+ {
+ throw new Exception($"Expected more memory to be allocated. previous = {previous}, precise = {precise}, difference = {previous - precise}");
+ }
+
+ differenceBetweenPreciseAndImprecise = imprecise - precise;
+ return precise;
+ }
+
+ long CallGetTotalAllocatedBytes(long previous)
+ {
+ long differenceBetweenPreciseAndImprecise;
+ previous = CallGetTotalAllocatedBytesAndCheck(previous, out differenceBetweenPreciseAndImprecise);
+ stash = new byte[differenceBetweenPreciseAndImprecise];
+ previous = CallGetTotalAllocatedBytesAndCheck(previous, out differenceBetweenPreciseAndImprecise);
+ return previous;
+ }
+
+ long previous = 0;
+
+ for (int i = 0; i < 1000; ++i)
+ {
+ stash = new byte[1234];
+ previous = CallGetTotalAllocatedBytes(previous);
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Runtime.InteropServices;
-using Microsoft.DotNet.RemoteExecutor;
-using Xunit;
-
-namespace System.Tests
-{
- public static partial class GCTests
- {
- [Theory]
- [InlineData(1000)]
- [InlineData(100000)]
- public static void GetAllocatedBytesForCurrentThread(int size)
- {
- long start = GC.GetAllocatedBytesForCurrentThread();
-
- GC.KeepAlive(new string('a', size));
-
- long end = GC.GetAllocatedBytesForCurrentThread();
-
- Assert.True((end - start) > size, $"Allocated too little: start: {start} end: {end} size: {size}");
- Assert.True((end - start) < 5 * size, $"Allocated too much: start: {start} end: {end} size: {size}");
- }
-
- [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotArmProcess))] // [ActiveIssue(37378)]
- public static void GetGCMemoryInfo()
- {
- RemoteExecutor.Invoke(() =>
- {
- // Allows to update the value returned by GC.GetGCMemoryInfo
- GC.Collect();
-
- GCMemoryInfo memoryInfo1 = GC.GetGCMemoryInfo();
-
- Assert.InRange(memoryInfo1.HighMemoryLoadThresholdBytes, 1, long.MaxValue);
- Assert.InRange(memoryInfo1.MemoryLoadBytes, 1, long.MaxValue);
- Assert.InRange(memoryInfo1.TotalAvailableMemoryBytes, 1, long.MaxValue);
- Assert.InRange(memoryInfo1.HeapSizeBytes, 1, long.MaxValue);
- Assert.InRange(memoryInfo1.FragmentedBytes, 0, long.MaxValue);
-
- GCHandle[] gch = new GCHandle[64 * 1024];
- for (int i = 0; i < gch.Length * 2; ++i)
- {
- byte[] arr = new byte[64];
- if (i % 2 == 0)
- {
- gch[i / 2] = GCHandle.Alloc(arr, GCHandleType.Pinned);
- }
- }
-
- // Allows to update the value returned by GC.GetGCMemoryInfo
- GC.Collect();
-
- GCMemoryInfo memoryInfo2 = GC.GetGCMemoryInfo();
-
- string scenario = null;
- try
- {
- scenario = nameof(memoryInfo2.HighMemoryLoadThresholdBytes);
- Assert.Equal(memoryInfo2.HighMemoryLoadThresholdBytes, memoryInfo1.HighMemoryLoadThresholdBytes);
-
- // Even though we have allocated, the overall load may decrease or increase depending what other processes are doing.
- // It cannot go above total available though.
- scenario = nameof(memoryInfo2.MemoryLoadBytes);
- Assert.InRange(memoryInfo2.MemoryLoadBytes, 1, memoryInfo1.TotalAvailableMemoryBytes);
-
- scenario = nameof(memoryInfo2.TotalAvailableMemoryBytes);
- Assert.Equal(memoryInfo2.TotalAvailableMemoryBytes, memoryInfo1.TotalAvailableMemoryBytes);
-
- scenario = nameof(memoryInfo2.HeapSizeBytes);
- Assert.InRange(memoryInfo2.HeapSizeBytes, memoryInfo1.HeapSizeBytes + 1, long.MaxValue);
-
- scenario = nameof(memoryInfo2.FragmentedBytes);
- Assert.InRange(memoryInfo2.FragmentedBytes, memoryInfo1.FragmentedBytes + 1, long.MaxValue);
-
- scenario = null;
- }
- finally
- {
- if (scenario != null)
- {
- System.Console.WriteLine("FAILED: " + scenario);
- }
- }
- }).Dispose();
- }
-
- [Fact]
- public static void GetTotalAllocatedBytes()
- {
- byte[] stash;
-
- long CallGetTotalAllocatedBytesAndCheck(long previous, out long differenceBetweenPreciseAndImprecise)
- {
- long precise = GC.GetTotalAllocatedBytes(true);
- long imprecise = GC.GetTotalAllocatedBytes(false);
-
- if (precise <= 0)
- {
- throw new Exception($"Bytes allocated is not positive, this is unlikely. precise = {precise}");
- }
-
- if (imprecise < precise)
- {
- throw new Exception($"Imprecise total bytes allocated less than precise, imprecise is required to be a conservative estimate (that estimates high). imprecise = {imprecise}, precise = {precise}");
- }
-
- if (previous > precise)
- {
- throw new Exception($"Expected more memory to be allocated. previous = {previous}, precise = {precise}, difference = {previous - precise}");
- }
-
- differenceBetweenPreciseAndImprecise = imprecise - precise;
- return precise;
- }
-
- long CallGetTotalAllocatedBytes(long previous)
- {
- long differenceBetweenPreciseAndImprecise;
- previous = CallGetTotalAllocatedBytesAndCheck(previous, out differenceBetweenPreciseAndImprecise);
- stash = new byte[differenceBetweenPreciseAndImprecise];
- previous = CallGetTotalAllocatedBytesAndCheck(previous, out differenceBetweenPreciseAndImprecise);
- return previous;
- }
-
- long previous = 0;
-
- for (int i = 0; i < 1000; ++i)
- {
- stash = new byte[1234];
- previous = CallGetTotalAllocatedBytes(previous);
- }
- }
- }
-}
namespace System.Tests
{
- public static partial class GuidTests
+ public static class GuidTests
{
private static readonly Guid s_testGuid = new Guid("a8a110d5-fc49-43c5-bf46-802db8f843ff");
private static readonly Guid s_fullGuid = new Guid(uint.MaxValue, ushort.MaxValue, ushort.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
{
Assert.Equal(expected, Math.Sign(guid.CompareTo(obj)));
}
+
+ [Theory]
+ [MemberData(nameof(Ctor_ByteArray_TestData))]
+ public static void Ctor_ReadOnlySpan(byte[] b, Guid expected)
+ {
+ Assert.Equal(expected, new Guid(new ReadOnlySpan<byte>(b)));
+ }
+
+ [Theory]
+ [InlineData(15)]
+ [InlineData(17)]
+ public static void CtorSpan_InvalidLengthByteArray_ThrowsArgumentException(int length)
+ {
+ AssertExtensions.Throws<ArgumentException>("b", null, () => new Guid(new ReadOnlySpan<byte>(new byte[length])));
+ }
+
+ [Theory]
+ [MemberData(nameof(Ctor_ByteArray_TestData))]
+ public static void TryWriteBytes_ValidLength_ReturnsTrue(byte[] b, Guid guid)
+ {
+ var bytes = new byte[16];
+ Assert.True(guid.TryWriteBytes(new Span<byte>(bytes)));
+ Assert.Equal(b, bytes);
+ }
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(15)]
+ public static void TryWriteBytes_LengthTooShort_ReturnsFalse(int length)
+ {
+ Assert.False(s_testGuid.TryWriteBytes(new Span<byte>(new byte[length])));
+ }
+
+ [Theory]
+ [MemberData(nameof(InvalidFormat_TestData))]
+ public static void TryFormat_InvalidFormat_ThrowsFormatException(string format)
+ {
+ Assert.Throws<FormatException>(() => s_testGuid.TryFormat(new Span<char>(), out int charsWritten, format));
+ Assert.Throws<FormatException>(() => s_testGuid.TryFormat(new Span<char>(), out int charsWritten, format.ToUpperInvariant()));
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat_LengthTooSmall_ReturnsFalse(Guid guid, string format, string expected)
+ {
+ _ = expected;
+ Assert.False(guid.TryFormat(new Span<char>(new char[guid.ToString(format).Length - 1]), out int charsWritten, format));
+ Assert.Equal(0, charsWritten);
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat_CharsWritten_EqualsZero_WhenSpanTooSmall(Guid guid, string format, string expected)
+ {
+ _ = expected;
+ Assert.False(guid.TryFormat(new Span<char>(new char[guid.ToString(format).Length - 1]), out int charsWritten, format));
+ Assert.Equal(0, charsWritten);
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat_ValidLength_ReturnsTrue(Guid guid, string format, string expected)
+ {
+ char[] chars = new char[guid.ToString(format).Length];
+ Assert.True(guid.TryFormat(new Span<char>(chars), out int charsWritten, format));
+ Assert.Equal(chars, expected.ToCharArray());
+ }
+
+ [Theory]
+ [MemberData(nameof(GuidStrings_Valid_TestData))]
+ public static void Parse_Span_ValidInput_Success(string input, string format, Guid expected)
+ {
+ Assert.Equal(expected, Guid.Parse(input.AsSpan()));
+ Assert.Equal(expected, Guid.ParseExact(input.AsSpan(), format.ToUpperInvariant()));
+ Assert.Equal(expected, Guid.ParseExact(input.AsSpan(), format.ToLowerInvariant())); // Format should be case insensitive
+
+ Guid result;
+
+ Assert.True(Guid.TryParse(input.AsSpan(), out result));
+ Assert.Equal(expected, result);
+
+ Assert.True(Guid.TryParseExact(input.AsSpan(), format.ToUpperInvariant(), out result));
+ Assert.Equal(expected, result);
+
+ Assert.True(Guid.TryParseExact(input.AsSpan(), format.ToLowerInvariant(), out result)); // Format should be case insensitive
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(GuidStrings_Invalid_TestData))]
+ public static void Parse_Span_InvalidInput_Fails(string input, Type exceptionType)
+ {
+ if (input == null)
+ {
+ return;
+ }
+
+ // Overflow exceptions throw as format exceptions in Parse
+ if (exceptionType.Equals(typeof(OverflowException)))
+ {
+ exceptionType = typeof(FormatException);
+ }
+ Assert.Throws(exceptionType, () => Guid.Parse(input.AsSpan()));
+
+ Assert.False(Guid.TryParse(input.AsSpan(), out Guid result));
+ Assert.Equal(Guid.Empty, result);
+
+ foreach (string format in new[] { "N", "D", "B", "P", "X" })
+ {
+ Assert.Throws(exceptionType, () => Guid.ParseExact(input.AsSpan(), format));
+
+ Assert.False(Guid.TryParseExact(input.AsSpan(), format, out result));
+ Assert.Equal(Guid.Empty, result);
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Xunit;
-
-namespace System.Tests
-{
- public static partial class GuidTests
- {
- [Theory]
- [MemberData(nameof(Ctor_ByteArray_TestData))]
- public static void Ctor_ReadOnlySpan(byte[] b, Guid expected)
- {
- Assert.Equal(expected, new Guid(new ReadOnlySpan<byte>(b)));
- }
-
- [Theory]
- [InlineData(15)]
- [InlineData(17)]
- public static void CtorSpan_InvalidLengthByteArray_ThrowsArgumentException(int length)
- {
- AssertExtensions.Throws<ArgumentException>("b", null, () => new Guid(new ReadOnlySpan<byte>(new byte[length])));
- }
-
- [Theory]
- [MemberData(nameof(Ctor_ByteArray_TestData))]
- public static void TryWriteBytes_ValidLength_ReturnsTrue(byte[] b, Guid guid)
- {
- var bytes = new byte[16];
- Assert.True(guid.TryWriteBytes(new Span<byte>(bytes)));
- Assert.Equal(b, bytes);
- }
-
- [Theory]
- [InlineData(0)]
- [InlineData(15)]
- public static void TryWriteBytes_LengthTooShort_ReturnsFalse(int length)
- {
- Assert.False(s_testGuid.TryWriteBytes(new Span<byte>(new byte[length])));
- }
-
- [Theory]
- [MemberData(nameof(InvalidFormat_TestData))]
- public static void TryFormat_InvalidFormat_ThrowsFormatException(string format)
- {
- Assert.Throws<FormatException>(() => s_testGuid.TryFormat(new Span<char>(), out int charsWritten, format));
- Assert.Throws<FormatException>(() => s_testGuid.TryFormat(new Span<char>(), out int charsWritten, format.ToUpperInvariant()));
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat_LengthTooSmall_ReturnsFalse(Guid guid, string format, string expected)
- {
- _ = expected;
- Assert.False(guid.TryFormat(new Span<char>(new char[guid.ToString(format).Length - 1]), out int charsWritten, format));
- Assert.Equal(0, charsWritten);
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat_CharsWritten_EqualsZero_WhenSpanTooSmall(Guid guid, string format, string expected)
- {
- _ = expected;
- Assert.False(guid.TryFormat(new Span<char>(new char[guid.ToString(format).Length - 1]), out int charsWritten, format));
- Assert.Equal(0, charsWritten);
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat_ValidLength_ReturnsTrue(Guid guid, string format, string expected)
- {
- char[] chars = new char[guid.ToString(format).Length];
- Assert.True(guid.TryFormat(new Span<char>(chars), out int charsWritten, format));
- Assert.Equal(chars, expected.ToCharArray());
- }
-
- [Theory]
- [MemberData(nameof(GuidStrings_Valid_TestData))]
- public static void Parse_Span_ValidInput_Success(string input, string format, Guid expected)
- {
- Assert.Equal(expected, Guid.Parse(input.AsSpan()));
- Assert.Equal(expected, Guid.ParseExact(input.AsSpan(), format.ToUpperInvariant()));
- Assert.Equal(expected, Guid.ParseExact(input.AsSpan(), format.ToLowerInvariant())); // Format should be case insensitive
-
- Guid result;
-
- Assert.True(Guid.TryParse(input.AsSpan(), out result));
- Assert.Equal(expected, result);
-
- Assert.True(Guid.TryParseExact(input.AsSpan(), format.ToUpperInvariant(), out result));
- Assert.Equal(expected, result);
-
- Assert.True(Guid.TryParseExact(input.AsSpan(), format.ToLowerInvariant(), out result)); // Format should be case insensitive
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(GuidStrings_Invalid_TestData))]
- public static void Parse_Span_InvalidInput_Fails(string input, Type exceptionType)
- {
- if (input == null)
- {
- return;
- }
-
- // Overflow exceptions throw as format exceptions in Parse
- if (exceptionType.Equals(typeof(OverflowException)))
- {
- exceptionType = typeof(FormatException);
- }
- Assert.Throws(exceptionType, () => Guid.Parse(input.AsSpan()));
-
- Assert.False(Guid.TryParse(input.AsSpan(), out Guid result));
- Assert.Equal(Guid.Empty, result);
-
- foreach (string format in new[] { "N", "D", "B", "P", "X" })
- {
- Assert.Throws(exceptionType, () => Guid.ParseExact(input.AsSpan(), format));
-
- Assert.False(Guid.TryParseExact(input.AsSpan(), format, out result));
- Assert.Equal(Guid.Empty, result);
- }
- }
- }
-}
namespace System.Tests
{
- public partial class Int16Tests
+ public class Int16Tests
{
[Fact]
public static void Ctor_Empty()
AssertExtensions.Throws<ArgumentException>(paramName, () => short.Parse("1", style));
AssertExtensions.Throws<ArgumentException>(paramName, () => short.Parse("1", style, null));
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ yield return new object[] { "-32767", 1, 5, NumberStyles.Integer, null, (short)32767 };
+ yield return new object[] { "-32768", 0, 5, NumberStyles.Integer, null, (short)-3276 };
+ yield return new object[] { "abc", 0, 2, NumberStyles.HexNumber, null, (short)0xab };
+ yield return new object[] { "abc", 1, 2, NumberStyles.HexNumber, null, (short)0xbc };
+ yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, null, (short)123 };
+ yield return new object[] { "123", 0, 1, NumberStyles.Integer, new NumberFormatInfo(), (short)1 };
+ yield return new object[] { "$1,000", 1, 5, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (short)1000 };
+ yield return new object[] { "$1,000", 0, 2, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (short)1 };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, short expected)
+ {
+ short result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.True(short.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+ }
+
+ Assert.Equal(expected, short.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(short.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ short result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.False(short.TryParse(value.AsSpan(), out result));
+ Assert.Equal(0, result);
+ }
+
+ Assert.Throws(exceptionType, () => short.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(short.TryParse(value.AsSpan(), style, provider, out result));
+ Assert.Equal(0, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat(short i, string format, IFormatProvider provider, string expected)
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual));
+
+ // Longer than needed
+ actual = new char[expected.Length + 1];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (expected.Length > 0)
+ {
+ actual = new char[expected.Length - 1];
+ Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(0, charsWritten);
+ }
+
+ if (format != null)
+ {
+ // Upper format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToUpperInvariant(), new string(actual));
+
+ // Lower format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToLowerInvariant(), new string(actual));
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class Int16Tests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- yield return new object[] { "-32767", 1, 5, NumberStyles.Integer, null, (short)32767 };
- yield return new object[] { "-32768", 0, 5, NumberStyles.Integer, null, (short)-3276 };
- yield return new object[] { "abc", 0, 2, NumberStyles.HexNumber, null, (short)0xab };
- yield return new object[] { "abc", 1, 2, NumberStyles.HexNumber, null, (short)0xbc };
- yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, null, (short)123 };
- yield return new object[] { "123", 0, 1, NumberStyles.Integer, new NumberFormatInfo(), (short)1 };
- yield return new object[] { "$1,000", 1, 5, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (short)1000 };
- yield return new object[] { "$1,000", 0, 2, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (short)1 };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, short expected)
- {
- short result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.True(short.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
- }
-
- Assert.Equal(expected, short.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(short.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- short result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.False(short.TryParse(value.AsSpan(), out result));
- Assert.Equal(0, result);
- }
-
- Assert.Throws(exceptionType, () => short.Parse(value.AsSpan(), style, provider));
-
- Assert.False(short.TryParse(value.AsSpan(), style, provider, out result));
- Assert.Equal(0, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat(short i, string format, IFormatProvider provider, string expected)
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual));
-
- // Longer than needed
- actual = new char[expected.Length + 1];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual, 0, charsWritten));
-
- // Too short
- if (expected.Length > 0)
- {
- actual = new char[expected.Length - 1];
- Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(0, charsWritten);
- }
-
- if (format != null)
- {
- // Upper format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToUpperInvariant(), new string(actual));
-
- // Lower format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToLowerInvariant(), new string(actual));
- }
- }
- }
-}
namespace System.Tests
{
- public partial class Int32Tests
+ public class Int32Tests
{
[Fact]
public static void Ctor_Empty()
nfi.CurrencySymbol = "$";
Assert.Equal("$1234", 1234.ToString("C0", nfi));
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ NumberFormatInfo samePositiveNegativeFormat = new NumberFormatInfo()
+ {
+ PositiveSign = "|",
+ NegativeSign = "|"
+ };
+
+ NumberFormatInfo emptyPositiveFormat = new NumberFormatInfo() { PositiveSign = "" };
+ NumberFormatInfo emptyNegativeFormat = new NumberFormatInfo() { NegativeSign = "" };
+
+ // None
+ yield return new object[] { "2147483647", 1, 9, NumberStyles.None, null, 147483647 };
+ yield return new object[] { "2147483647", 1, 1, NumberStyles.None, null, 1 };
+ yield return new object[] { "123\0\0", 2, 2, NumberStyles.None, null, 3 };
+
+ // Hex
+ yield return new object[] { "abc", 0, 1, NumberStyles.HexNumber, null, 0xa };
+ yield return new object[] { "ABC", 1, 1, NumberStyles.HexNumber, null, 0xB };
+ yield return new object[] { "FFFFFFFF", 6, 2, NumberStyles.HexNumber, null, 0xFF };
+ yield return new object[] { "FFFFFFFF", 0, 1, NumberStyles.HexNumber, null, 0xF };
+
+ // Currency
+ yield return new object[] { "-$1000", 1, 5, NumberStyles.Currency, new NumberFormatInfo()
+ {
+ CurrencySymbol = "$",
+ CurrencyGroupSeparator = "|",
+ NumberGroupSeparator = "/"
+ }, 1000 };
+
+ NumberFormatInfo emptyCurrencyFormat = new NumberFormatInfo() { CurrencySymbol = "" };
+ yield return new object[] { "100", 1, 2, NumberStyles.Currency, emptyCurrencyFormat, 0 };
+ yield return new object[] { "100", 0, 1, NumberStyles.Currency, emptyCurrencyFormat, 1 };
+
+ // If CurrencySymbol and Negative are the same, NegativeSign is preferred
+ NumberFormatInfo sameCurrencyNegativeSignFormat = new NumberFormatInfo()
+ {
+ NegativeSign = "|",
+ CurrencySymbol = "|"
+ };
+ yield return new object[] { "1000", 1, 3, NumberStyles.AllowCurrencySymbol | NumberStyles.AllowLeadingSign, sameCurrencyNegativeSignFormat, 0 };
+ yield return new object[] { "|1000", 0, 2, NumberStyles.AllowCurrencySymbol | NumberStyles.AllowLeadingSign, sameCurrencyNegativeSignFormat, -1 };
+
+ // Any
+ yield return new object[] { "123", 0, 2, NumberStyles.Any, null, 12 };
+
+ // AllowLeadingSign
+ yield return new object[] { "-2147483648", 0, 10, NumberStyles.AllowLeadingSign, null, -214748364 };
+
+ // AllowTrailingSign
+ yield return new object[] { "123-", 0, 3, NumberStyles.AllowTrailingSign, null, 123 };
+
+ // AllowExponent
+ yield return new object[] { "1E2", 0, 1, NumberStyles.AllowExponent, null, 1 };
+ yield return new object[] { "1E+2", 3, 1, NumberStyles.AllowExponent, null, 2 };
+ yield return new object[] { "(1E2)", 1, 3, NumberStyles.AllowExponent | NumberStyles.AllowParentheses, null, 1E2 };
+ yield return new object[] { "-1E2", 1, 3, NumberStyles.AllowExponent | NumberStyles.AllowLeadingSign, null, 1E2 };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, int expected)
+ {
+ int result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.True(int.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+ }
+
+ Assert.Equal(expected, int.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(int.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ int result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.False(int.TryParse(value.AsSpan(), out result));
+ Assert.Equal(0, result);
+ }
+
+ Assert.Throws(exceptionType, () => int.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(int.TryParse(value.AsSpan(), style, provider, out result));
+ Assert.Equal(0, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat(int i, string format, IFormatProvider provider, string expected)
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual));
+
+ // Longer than needed
+ actual = new char[expected.Length + 1];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (expected.Length > 0)
+ {
+ actual = new char[expected.Length - 1];
+ Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(0, charsWritten);
+ }
+
+ if (format != null)
+ {
+ // Upper format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToUpperInvariant(), new string(actual));
+
+ // Lower format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToLowerInvariant(), new string(actual));
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class Int32Tests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- NumberFormatInfo samePositiveNegativeFormat = new NumberFormatInfo()
- {
- PositiveSign = "|",
- NegativeSign = "|"
- };
-
- NumberFormatInfo emptyPositiveFormat = new NumberFormatInfo() { PositiveSign = "" };
- NumberFormatInfo emptyNegativeFormat = new NumberFormatInfo() { NegativeSign = "" };
-
- // None
- yield return new object[] { "2147483647", 1, 9, NumberStyles.None, null, 147483647 };
- yield return new object[] { "2147483647", 1, 1, NumberStyles.None, null, 1 };
- yield return new object[] { "123\0\0", 2, 2, NumberStyles.None, null, 3 };
-
- // Hex
- yield return new object[] { "abc", 0, 1, NumberStyles.HexNumber, null, 0xa };
- yield return new object[] { "ABC", 1, 1, NumberStyles.HexNumber, null, 0xB };
- yield return new object[] { "FFFFFFFF", 6, 2, NumberStyles.HexNumber, null, 0xFF };
- yield return new object[] { "FFFFFFFF", 0, 1, NumberStyles.HexNumber, null, 0xF };
-
- // Currency
- yield return new object[] { "-$1000", 1, 5, NumberStyles.Currency, new NumberFormatInfo()
- {
- CurrencySymbol = "$",
- CurrencyGroupSeparator = "|",
- NumberGroupSeparator = "/"
- }, 1000 };
-
- NumberFormatInfo emptyCurrencyFormat = new NumberFormatInfo() { CurrencySymbol = "" };
- yield return new object[] { "100", 1, 2, NumberStyles.Currency, emptyCurrencyFormat, 0 };
- yield return new object[] { "100", 0, 1, NumberStyles.Currency, emptyCurrencyFormat, 1 };
-
- // If CurrencySymbol and Negative are the same, NegativeSign is preferred
- NumberFormatInfo sameCurrencyNegativeSignFormat = new NumberFormatInfo()
- {
- NegativeSign = "|",
- CurrencySymbol = "|"
- };
- yield return new object[] { "1000", 1, 3, NumberStyles.AllowCurrencySymbol | NumberStyles.AllowLeadingSign, sameCurrencyNegativeSignFormat, 0 };
- yield return new object[] { "|1000", 0, 2, NumberStyles.AllowCurrencySymbol | NumberStyles.AllowLeadingSign, sameCurrencyNegativeSignFormat, -1 };
-
- // Any
- yield return new object[] { "123", 0, 2, NumberStyles.Any, null, 12 };
-
- // AllowLeadingSign
- yield return new object[] { "-2147483648", 0, 10, NumberStyles.AllowLeadingSign, null, -214748364 };
-
- // AllowTrailingSign
- yield return new object[] { "123-", 0, 3, NumberStyles.AllowTrailingSign, null, 123 };
-
- // AllowExponent
- yield return new object[] { "1E2", 0, 1, NumberStyles.AllowExponent, null, 1 };
- yield return new object[] { "1E+2", 3, 1, NumberStyles.AllowExponent, null, 2 };
- yield return new object[] { "(1E2)", 1, 3, NumberStyles.AllowExponent | NumberStyles.AllowParentheses, null, 1E2 };
- yield return new object[] { "-1E2", 1, 3, NumberStyles.AllowExponent | NumberStyles.AllowLeadingSign, null, 1E2 };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, int expected)
- {
- int result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.True(int.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
- }
-
- Assert.Equal(expected, int.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(int.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- int result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.False(int.TryParse(value.AsSpan(), out result));
- Assert.Equal(0, result);
- }
-
- Assert.Throws(exceptionType, () => int.Parse(value.AsSpan(), style, provider));
-
- Assert.False(int.TryParse(value.AsSpan(), style, provider, out result));
- Assert.Equal(0, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat(int i, string format, IFormatProvider provider, string expected)
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual));
-
- // Longer than needed
- actual = new char[expected.Length + 1];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual, 0, charsWritten));
-
- // Too short
- if (expected.Length > 0)
- {
- actual = new char[expected.Length - 1];
- Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(0, charsWritten);
- }
-
- if (format != null)
- {
- // Upper format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToUpperInvariant(), new string(actual));
-
- // Lower format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToLowerInvariant(), new string(actual));
- }
- }
- }
-}
namespace System.Tests
{
- public partial class Int64Tests
+ public class Int64Tests
{
[Fact]
public static void Ctor_Empty()
AssertExtensions.Throws<ArgumentException>(paramName, () => long.Parse("1", style));
AssertExtensions.Throws<ArgumentException>(paramName, () => long.Parse("1", style, null));
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ yield return new object[] { "-9223372036854775808", 0, 19, NumberStyles.Integer, null, -922337203685477580 };
+ yield return new object[] { "09223372036854775807", 1, 19, NumberStyles.Integer, null, 9223372036854775807 };
+ yield return new object[] { "9223372036854775807", 0, 1, NumberStyles.Integer, null, 9 };
+ yield return new object[] { "ABC", 0, 2, NumberStyles.HexNumber, null, (long)0xAB };
+ yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, null, (long)123 };
+ yield return new object[] { "$1,000", 0, 2, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (long)1 };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, long expected)
+ {
+ long result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.True(long.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+ }
+
+ Assert.Equal(expected, long.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(long.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ long result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.False(long.TryParse(value.AsSpan(), out result));
+ Assert.Equal(0, result);
+ }
+
+ Assert.Throws(exceptionType, () => long.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(long.TryParse(value.AsSpan(), style, provider, out result));
+ Assert.Equal(0, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat(long i, string format, IFormatProvider provider, string expected)
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual));
+
+ // Longer than needed
+ actual = new char[expected.Length + 1];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (expected.Length > 0)
+ {
+ actual = new char[expected.Length - 1];
+ Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(0, charsWritten);
+ }
+
+ if (format != null)
+ {
+ // Upper format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToUpperInvariant(), new string(actual));
+
+ // Lower format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToLowerInvariant(), new string(actual));
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class Int64Tests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- yield return new object[] { "-9223372036854775808", 0, 19, NumberStyles.Integer, null, -922337203685477580 };
- yield return new object[] { "09223372036854775807", 1, 19, NumberStyles.Integer, null, 9223372036854775807 };
- yield return new object[] { "9223372036854775807", 0, 1, NumberStyles.Integer, null, 9 };
- yield return new object[] { "ABC", 0, 2, NumberStyles.HexNumber, null, (long)0xAB };
- yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, null, (long)123 };
- yield return new object[] { "$1,000", 0, 2, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (long)1 };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, long expected)
- {
- long result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.True(long.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
- }
-
- Assert.Equal(expected, long.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(long.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- long result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.False(long.TryParse(value.AsSpan(), out result));
- Assert.Equal(0, result);
- }
-
- Assert.Throws(exceptionType, () => long.Parse(value.AsSpan(), style, provider));
-
- Assert.False(long.TryParse(value.AsSpan(), style, provider, out result));
- Assert.Equal(0, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat(long i, string format, IFormatProvider provider, string expected)
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual));
-
- // Longer than needed
- actual = new char[expected.Length + 1];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual, 0, charsWritten));
-
- // Too short
- if (expected.Length > 0)
- {
- actual = new char[expected.Length - 1];
- Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(0, charsWritten);
- }
-
- if (format != null)
- {
- // Upper format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToUpperInvariant(), new string(actual));
-
- // Lower format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToLowerInvariant(), new string(actual));
- }
- }
- }
-}
namespace System.Tests
{
- public static partial class IntPtrTests
+ public static class IntPtrTests
{
private static unsafe bool Is64Bit => sizeof(void*) == 8;
Assert.Equal(expected, ptr1 == ptr2);
Assert.Equal(!expected, ptr1 != ptr2);
Assert.Equal(expected, ptr1.GetHashCode().Equals(ptr2.GetHashCode()));
+
+ IEquatable<IntPtr> iEquatable = ptr1;
+ Assert.Equal(expected, iEquatable.Equals((IntPtr)obj));
}
Assert.Equal(expected, ptr1.Equals(obj));
Assert.Equal(ptr1.GetHashCode(), ptr1.GetHashCode());
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections.Generic;
-using Xunit;
-
-namespace System.Tests
-{
- public static partial class IntPtrTests
- {
- [Theory]
- [MemberData(nameof(Equals_TestData))]
- public static void Equals_NetCoreApp11(IntPtr ptr, object obj, bool expected)
- {
- if (!(obj is IntPtr))
- {
- return;
- }
-
- IEquatable<IntPtr> iEquatable = ptr;
- Assert.Equal(expected, iEquatable.Equals((IntPtr)obj));
- }
- }
-}
namespace System.Tests
{
- public static partial class LazyTests
+ public static class LazyTests
{
[Fact]
public static void Ctor()
Assert.Equal(template, d);
}
+ [Fact]
+ public static void Ctor_Value_ReferenceType()
+ {
+ var lazyString = new Lazy<string>("abc");
+ VerifyLazy(lazyString, "abc", hasValue: true, isValueCreated: true);
+ }
+
+ [Fact]
+ public static void Ctor_Value_ValueType()
+ {
+ var lazyObject = new Lazy<int>(123);
+ VerifyLazy(lazyObject, 123, hasValue: true, isValueCreated: true);
+ }
+
+ [Fact]
+ public static void EnsureInitialized_FuncInitializationWithoutTrackingBool_Uninitialized()
+ {
+ string template = "foo";
+ string target = null;
+ object syncLock = null;
+ Assert.Equal(template, LazyInitializer.EnsureInitialized(ref target, ref syncLock, () => template));
+ Assert.Equal(template, target);
+ Assert.NotNull(syncLock);
+ }
+
+ [Fact]
+ public static void EnsureInitialized_FuncInitializationWithoutTrackingBool_Initialized()
+ {
+ string template = "foo";
+ string target = template;
+ object syncLock = null;
+ Assert.Equal(template, LazyInitializer.EnsureInitialized(ref target, ref syncLock, () => template + "bar"));
+ Assert.Equal(template, target);
+ Assert.Null(syncLock);
+ }
+
+ [Fact]
+ public static void EnsureInitializer_FuncInitializationWithoutTrackingBool_Null()
+ {
+ string target = null;
+ object syncLock = null;
+ Assert.Throws<InvalidOperationException>(() => LazyInitializer.EnsureInitialized(ref target, ref syncLock, () => null));
+ }
private static void VerifyLazy<T>(Lazy<T> lazy, T expectedValue, bool hasValue, bool isValueCreated)
{
Assert.Equal(isValueCreated, lazy.IsValueCreated);
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Threading;
-using Xunit;
-
-namespace System.Tests
-{
- public static partial class LazyTests
- {
- [Fact]
- public static void Ctor_Value_ReferenceType()
- {
- var lazyString = new Lazy<string>("abc");
- VerifyLazy(lazyString, "abc", hasValue: true, isValueCreated: true);
- }
-
- [Fact]
- public static void Ctor_Value_ValueType()
- {
- var lazyObject = new Lazy<int>(123);
- VerifyLazy(lazyObject, 123, hasValue: true, isValueCreated: true);
- }
-
- [Fact]
- public static void EnsureInitialized_FuncInitializationWithoutTrackingBool_Uninitialized()
- {
- string template = "foo";
- string target = null;
- object syncLock = null;
- Assert.Equal(template, LazyInitializer.EnsureInitialized(ref target, ref syncLock, () => template));
- Assert.Equal(template, target);
- Assert.NotNull(syncLock);
- }
-
- [Fact]
- public static void EnsureInitialized_FuncInitializationWithoutTrackingBool_Initialized()
- {
- string template = "foo";
- string target = template;
- object syncLock = null;
- Assert.Equal(template, LazyInitializer.EnsureInitialized(ref target, ref syncLock, () => template + "bar"));
- Assert.Equal(template, target);
- Assert.Null(syncLock);
- }
-
- [Fact]
- public static void EnsureInitializer_FuncInitializationWithoutTrackingBool_Null()
- {
- string target = null;
- object syncLock = null;
- Assert.Throws<InvalidOperationException>(() => LazyInitializer.EnsureInitialized(ref target, ref syncLock, () => null));
- }
- }
-}
}
[Fact]
- public static void Test_GetCurrentMethod_GenericMethodDefinition()
- {
- MethodBase m = MyFakeGenericMethod<byte>();
-
- Assert.Equal("MyFakeGenericMethod", m.Name);
- Assert.Equal("MethodBaseTests", m.ReflectedType.Name);
- Assert.True(m.IsGenericMethod);
- Assert.True(m.IsGenericMethodDefinition);
- Assert.Equal(1, m.GetGenericArguments().Length);
- Assert.Equal("T", m.GetGenericArguments()[0].Name);
- }
-
- [Fact]
public static void Test_GetCurrentMethod_Inlineable()
{
// Verify that the result is not affected by inlining optimizations
#endif
}
- public static MethodBase MyFakeGenericMethod<T>()
- {
- MethodBase m = MethodBase.GetCurrentMethod();
- return m;
- }
-
private static int MyAnotherMethod(int x)
{
return x+1;
}
}
#pragma warning restore xUnit1013 // Public method should be marked as test
+
+ [Fact]
+ public static void Test_GetCurrentMethod_ConstructedGenericMethod()
+ {
+ MethodInfo mi = typeof(MethodBaseTests).GetMethod(nameof(MyFakeGenericMethod), BindingFlags.NonPublic | BindingFlags.Static);
+ MethodBase m = mi.MakeGenericMethod(typeof(byte));
+
+ Assert.Equal(nameof(MyFakeGenericMethod), m.Name);
+ Assert.Equal(typeof(MethodBaseTests), m.ReflectedType);
+ Assert.True(m.IsGenericMethod);
+ Assert.False(m.IsGenericMethodDefinition);
+ Assert.True(m.IsConstructedGenericMethod);
+ Assert.Equal(1, m.GetGenericArguments().Length);
+ Assert.Equal(typeof(byte), m.GetGenericArguments()[0]);
+ }
+
+ [Fact]
+ public static void Test_GetCurrentMethod_GenericMethodDefinition()
+ {
+ MethodBase m = typeof(MethodBaseTests).GetMethod(nameof(MyFakeGenericMethod), BindingFlags.NonPublic | BindingFlags.Static);
+
+ Assert.Equal(nameof(MyFakeGenericMethod), m.Name);
+ Assert.Equal(typeof(MethodBaseTests), m.ReflectedType);
+ Assert.True(m.IsGenericMethod);
+ Assert.True(m.IsGenericMethodDefinition);
+ Assert.False(m.IsConstructedGenericMethod);
+ Assert.Equal(1, m.GetGenericArguments().Length);
+ Assert.Equal("T", m.GetGenericArguments()[0].Name);
+ }
+
+ private static void MyFakeGenericMethod<T>()
+ {
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Xunit;
-
-namespace System.Reflection.Tests
-{
- public class MethodBaseNetcoreTests
- {
- [Fact]
- public static void Test_GetCurrentMethod_ConstructedGenericMethod()
- {
- MethodInfo mi = typeof(MethodBaseNetcoreTests).GetMethod(nameof(MyFakeGenericMethod), BindingFlags.NonPublic | BindingFlags.Instance);
- MethodBase m = mi.MakeGenericMethod(typeof(byte));
-
- Assert.Equal(nameof(MyFakeGenericMethod), m.Name);
- Assert.Equal(typeof(MethodBaseNetcoreTests), m.ReflectedType);
- Assert.True(m.IsGenericMethod);
- Assert.False(m.IsGenericMethodDefinition);
- Assert.True(m.IsConstructedGenericMethod);
- Assert.Equal(1, m.GetGenericArguments().Length);
- Assert.Equal(typeof(byte), m.GetGenericArguments()[0]);
- }
-
- [Fact]
- public static void Test_GetCurrentMethod_GenericMethodDefinition()
- {
- MethodBase m = typeof(MethodBaseNetcoreTests).GetMethod(nameof(MyFakeGenericMethod), BindingFlags.NonPublic | BindingFlags.Instance);
-
- Assert.Equal(nameof(MyFakeGenericMethod), m.Name);
- Assert.Equal(typeof(MethodBaseNetcoreTests), m.ReflectedType);
- Assert.True(m.IsGenericMethod);
- Assert.True(m.IsGenericMethodDefinition);
- Assert.False(m.IsConstructedGenericMethod);
- Assert.Equal(1, m.GetGenericArguments().Length);
- Assert.Equal("T", m.GetGenericArguments()[0].Name);
- }
-
- private void MyFakeGenericMethod<T>()
- {
- }
- }
-}
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Collections.Generic;
using Xunit;
namespace System.Reflection.Tests
Assert.True(new TypeDelegator(typeof(TypeCode)).IsValueType);
Assert.True(new TypeDelegator(typeof(TypeCode)).IsEnum);
}
+
+ public static IEnumerable<object[]> SZArrayOrNotTypes()
+ {
+ yield return new object[] { typeof(int[]), true };
+ yield return new object[] { typeof(string[]), true };
+ yield return new object[] { typeof(void), false };
+ yield return new object[] { typeof(int), false };
+ yield return new object[] { typeof(int[]).MakeByRefType(), false };
+ yield return new object[] { typeof(int[,]), false };
+ if (PlatformDetection.IsNonZeroLowerBoundArraySupported)
+ {
+ yield return new object[] { Array.CreateInstance(typeof(int), new[] { 2 }, new[] { -1 }).GetType(), false };
+ yield return new object[] { Array.CreateInstance(typeof(int), new[] { 2 }, new[] { 1 }).GetType(), false };
+ }
+ yield return new object[] { Array.CreateInstance(typeof(int), new[] { 2 }, new[] { 0 }).GetType(), true };
+ yield return new object[] { typeof(int[][]), true };
+ yield return new object[] { Type.GetType("System.Int32[]"), true };
+ yield return new object[] { Type.GetType("System.Int32[*]"), false };
+ yield return new object[] { Type.GetType("System.Int32"), false };
+ yield return new object[] { typeof(int).MakeArrayType(), true };
+ yield return new object[] { typeof(int).MakeArrayType(1), false };
+ yield return new object[] { typeof(int).MakeArrayType().MakeArrayType(), true };
+ yield return new object[] { typeof(int).MakeArrayType(2), false };
+ yield return new object[] { typeof(Outside<int>.Inside<string>), false };
+ yield return new object[] { typeof(Outside<int>.Inside<string>[]), true };
+ yield return new object[] { typeof(Outside<int>.Inside<string>[,]), false };
+ if (PlatformDetection.IsNonZeroLowerBoundArraySupported)
+ {
+ yield return new object[] { Array.CreateInstance(typeof(Outside<int>.Inside<string>), new[] { 2 }, new[] { -1 }).GetType(), false };
+ }
+ }
+
+ [Theory, MemberData(nameof(SZArrayOrNotTypes))]
+ public void IsSZArray(Type type, bool expected)
+ {
+ Assert.Equal(expected, new TypeDelegator(type).IsSZArray);
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using Xunit;
-
-namespace System.Reflection.Tests
-{
- public class TypeDelegatorNetcoreTests
- {
- public static IEnumerable<object[]> SZArrayOrNotTypes()
- {
- yield return new object[] { typeof(int[]), true };
- yield return new object[] { typeof(string[]), true };
- yield return new object[] { typeof(void), false };
- yield return new object[] { typeof(int), false };
- yield return new object[] { typeof(int[]).MakeByRefType(), false };
- yield return new object[] { typeof(int[,]), false };
- if (PlatformDetection.IsNonZeroLowerBoundArraySupported)
- {
- yield return new object[] { Array.CreateInstance(typeof(int), new[] { 2 }, new[] { -1 }).GetType(), false };
- yield return new object[] { Array.CreateInstance(typeof(int), new[] { 2 }, new[] { 1 }).GetType(), false };
- }
- yield return new object[] { Array.CreateInstance(typeof(int), new[] { 2 }, new[] { 0 }).GetType(), true };
- yield return new object[] { typeof(int[][]), true };
- yield return new object[] { Type.GetType("System.Int32[]"), true };
- yield return new object[] { Type.GetType("System.Int32[*]"), false };
- yield return new object[] { Type.GetType("System.Int32"), false };
- yield return new object[] { typeof(int).MakeArrayType(), true };
- yield return new object[] { typeof(int).MakeArrayType(1), false };
- yield return new object[] { typeof(int).MakeArrayType().MakeArrayType(), true };
- yield return new object[] { typeof(int).MakeArrayType(2), false };
- yield return new object[] { typeof(Outside<int>.Inside<string>), false };
- yield return new object[] { typeof(Outside<int>.Inside<string>[]), true };
- yield return new object[] { typeof(Outside<int>.Inside<string>[,]), false };
- if (PlatformDetection.IsNonZeroLowerBoundArraySupported)
- {
- yield return new object[] { Array.CreateInstance(typeof(Outside<int>.Inside<string>), new[] { 2 }, new[] { -1 }).GetType(), false };
- }
- }
-
- [Theory, MemberData(nameof(SZArrayOrNotTypes))]
- public void IsSZArray(Type type, bool expected)
- {
- Assert.Equal(expected, new TypeDelegator(type).IsSZArray);
- }
- }
-}
namespace System.Runtime.CompilerServices.Tests
{
- public static partial class AttributesTests
+ public static class AttributesTests
{
[Fact]
public static void AccessedThroughPropertyAttributeTests()
{
new UnsafeValueTypeAttribute();
}
+
+ [Fact]
+ public static void AsyncMethodBuilderAttributeTests()
+ {
+ var attr1 = new AsyncMethodBuilderAttribute(null);
+ Assert.Null(attr1.BuilderType);
+
+ var attr2 = new AsyncMethodBuilderAttribute(typeof(AttributesTests));
+ Assert.Equal(typeof(AttributesTests), attr2.BuilderType);
+ }
+
+ [Fact]
+ public static void IsByRefLikeAttributeTests()
+ {
+ new IsByRefLikeAttribute();
+ }
+
+ [Fact]
+ public static void IsReadOnlyAttributeTests()
+ {
+ new IsReadOnlyAttribute();
+ }
+
+ [Fact]
+ public static void EnumeratorCancellationAttributeTests()
+ {
+ new EnumeratorCancellationAttribute();
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Xunit;
-
-namespace System.Runtime.CompilerServices.Tests
-{
- public static partial class AttributesTests
- {
- [Fact]
- public static void AsyncMethodBuilderAttributeTests()
- {
- var attr1 = new AsyncMethodBuilderAttribute(null);
- Assert.Null(attr1.BuilderType);
-
- var attr2 = new AsyncMethodBuilderAttribute(typeof(AttributesTests));
- Assert.Equal(typeof(AttributesTests), attr2.BuilderType);
- }
-
- [Fact]
- public static void IsByRefLikeAttributeTests()
- {
- new IsByRefLikeAttribute();
- }
-
- [Fact]
- public static void IsReadOnlyAttributeTests()
- {
- new IsReadOnlyAttribute();
- }
-
- [Fact]
- public static void EnumeratorCancellationAttributeTests()
- {
- new EnumeratorCancellationAttribute();
- }
- }
-}
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Linq;
+using System;
+using System.Collections.Generic;
using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace System.Runtime.CompilerServices.Tests
{
- public partial class ConditionalWeakTableTests
+ public class ConditionalWeakTableTests
{
[Fact]
public static void InvalidArgs_Throws()
// Do it a couple of times, to make sure the table is still usable after a clear.
}
}
+
+ [Fact]
+ public static void AddOrUpdateDataTest()
+ {
+ var cwt = new ConditionalWeakTable<string, string>();
+ string key = "key1";
+ cwt.AddOrUpdate(key, "value1");
+
+ string value;
+ Assert.True(cwt.TryGetValue(key, out value));
+ Assert.Equal("value1", value);
+ Assert.Equal(value, cwt.GetOrCreateValue(key));
+ Assert.Equal(value, cwt.GetValue(key, k => "value1"));
+
+ Assert.Throws<ArgumentNullException>(() => cwt.AddOrUpdate(null, "value2"));
+
+ cwt.AddOrUpdate(key, "value2");
+ Assert.True(cwt.TryGetValue(key, out value));
+ Assert.Equal("value2", value);
+ Assert.Equal(value, cwt.GetOrCreateValue(key));
+ Assert.Equal(value, cwt.GetValue(key, k => "value1"));
+ }
+
+ [Fact]
+ public static void Clear_EmptyTable()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ cwt.Clear(); // no exception
+ cwt.Clear();
+ }
+
+ [Fact]
+ public static void Clear_AddThenEmptyRepeatedly_ItemsRemoved()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ object key = new object(), value = new object();
+ object result;
+ for (int i = 0; i < 3; i++)
+ {
+ cwt.Add(key, value);
+
+ Assert.True(cwt.TryGetValue(key, out result));
+ Assert.Same(value, result);
+
+ cwt.Clear();
+
+ Assert.False(cwt.TryGetValue(key, out result));
+ Assert.Null(result);
+ }
+ }
+
+ [Fact]
+ public static void Clear_AddMany_Clear_AllItemsRemoved()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+
+ object[] keys = Enumerable.Range(0, 33).Select(_ => new object()).ToArray();
+ object[] values = Enumerable.Range(0, keys.Length).Select(_ => new object()).ToArray();
+ for (int i = 0; i < keys.Length; i++)
+ {
+ cwt.Add(keys[i], values[i]);
+ }
+
+ Assert.Equal(keys.Length, ((IEnumerable<KeyValuePair<object, object>>)cwt).Count());
+
+ cwt.Clear();
+
+ Assert.Equal(0, ((IEnumerable<KeyValuePair<object, object>>)cwt).Count());
+
+ GC.KeepAlive(keys);
+ GC.KeepAlive(values);
+ }
+
+ [Fact]
+ public static void GetEnumerator_Empty_ReturnsEmptyEnumerator()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
+ Assert.Equal(0, enumerable.Count());
+ }
+
+ [Fact]
+ public static void GetEnumerator_AddedAndRemovedItems_AppropriatelyShowUpInEnumeration()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
+
+ object key1 = new object(), value1 = new object();
+
+ for (int i = 0; i < 20; i++) // adding and removing multiple times, across internal container boundary
+ {
+ cwt.Add(key1, value1);
+ Assert.Equal(1, enumerable.Count());
+ Assert.Equal(new KeyValuePair<object, object>(key1, value1), enumerable.First());
+
+ Assert.True(cwt.Remove(key1));
+ Assert.Equal(0, enumerable.Count());
+ }
+
+ GC.KeepAlive(key1);
+ GC.KeepAlive(value1);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsPreciseGcSupported))]
+ public static void GetEnumerator_CollectedItemsNotEnumerated()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
+
+ // Delegate to add collectible items to the table, separated out
+ // to avoid the JIT extending the lifetimes of the temporaries
+ Action<ConditionalWeakTable<object, object>> addItem =
+ t => t.Add(new object(), new object());
+
+ for (int i = 0; i < 10; i++) addItem(cwt);
+ GC.Collect();
+ Assert.Equal(0, enumerable.Count());
+ }
+
+ [Fact]
+ public static void GetEnumerator_MultipleEnumeratorsReturnSameResults()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
+
+ object[] keys = Enumerable.Range(0, 33).Select(_ => new object()).ToArray();
+ object[] values = Enumerable.Range(0, keys.Length).Select(_ => new object()).ToArray();
+ for (int i = 0; i < keys.Length; i++)
+ {
+ cwt.Add(keys[i], values[i]);
+ }
+
+ using (IEnumerator<KeyValuePair<object, object>> enumerator1 = enumerable.GetEnumerator())
+ using (IEnumerator<KeyValuePair<object, object>> enumerator2 = enumerable.GetEnumerator())
+ {
+ while (enumerator1.MoveNext())
+ {
+ Assert.True(enumerator2.MoveNext());
+ Assert.Equal(enumerator1.Current, enumerator2.Current);
+ }
+ Assert.False(enumerator2.MoveNext());
+ }
+
+ GC.KeepAlive(keys);
+ GC.KeepAlive(values);
+ }
+
+ [Fact]
+ public static void GetEnumerator_RemovedItems_RemovedFromResults()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
+
+ object[] keys = Enumerable.Range(0, 33).Select(_ => new object()).ToArray();
+ object[] values = Enumerable.Range(0, keys.Length).Select(_ => new object()).ToArray();
+ for (int i = 0; i < keys.Length; i++)
+ {
+ cwt.Add(keys[i], values[i]);
+ }
+
+ for (int i = 0; i < keys.Length; i++)
+ {
+ Assert.Equal(keys.Length - i, enumerable.Count());
+ Assert.Equal(
+ Enumerable.Range(i, keys.Length - i).Select(j => new KeyValuePair<object, object>(keys[j], values[j])),
+ enumerable);
+ cwt.Remove(keys[i]);
+ }
+ Assert.Equal(0, enumerable.Count());
+
+ GC.KeepAlive(keys);
+ GC.KeepAlive(values);
+ }
+
+ [Fact]
+ public static void GetEnumerator_ItemsAddedAfterGetEnumeratorNotIncluded()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
+
+ object key1 = new object(), key2 = new object(), value1 = new object(), value2 = new object();
+
+ cwt.Add(key1, value1);
+ IEnumerator<KeyValuePair<object, object>> enumerator1 = enumerable.GetEnumerator();
+ cwt.Add(key2, value2);
+ IEnumerator<KeyValuePair<object, object>> enumerator2 = enumerable.GetEnumerator();
+
+ Assert.True(enumerator1.MoveNext());
+ Assert.Equal(new KeyValuePair<object, object>(key1, value1), enumerator1.Current);
+ Assert.False(enumerator1.MoveNext());
+
+ Assert.True(enumerator2.MoveNext());
+ Assert.Equal(new KeyValuePair<object, object>(key1, value1), enumerator2.Current);
+ Assert.True(enumerator2.MoveNext());
+ Assert.Equal(new KeyValuePair<object, object>(key2, value2), enumerator2.Current);
+ Assert.False(enumerator2.MoveNext());
+
+ enumerator1.Dispose();
+ enumerator2.Dispose();
+
+ GC.KeepAlive(key1);
+ GC.KeepAlive(key2);
+ GC.KeepAlive(value1);
+ GC.KeepAlive(value2);
+ }
+
+ [Fact]
+ public static void GetEnumerator_ItemsRemovedAfterGetEnumeratorNotIncluded()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
+
+ object key1 = new object(), key2 = new object(), value1 = new object(), value2 = new object();
+
+ cwt.Add(key1, value1);
+ cwt.Add(key2, value2);
+ IEnumerator<KeyValuePair<object, object>> enumerator1 = enumerable.GetEnumerator();
+ cwt.Remove(key1);
+ IEnumerator<KeyValuePair<object, object>> enumerator2 = enumerable.GetEnumerator();
+
+ Assert.True(enumerator1.MoveNext());
+ Assert.Equal(new KeyValuePair<object, object>(key2, value2), enumerator1.Current);
+ Assert.False(enumerator1.MoveNext());
+
+ Assert.True(enumerator2.MoveNext());
+ Assert.Equal(new KeyValuePair<object, object>(key2, value2), enumerator2.Current);
+ Assert.False(enumerator2.MoveNext());
+
+ enumerator1.Dispose();
+ enumerator2.Dispose();
+
+ GC.KeepAlive(key1);
+ GC.KeepAlive(key2);
+ GC.KeepAlive(value1);
+ GC.KeepAlive(value2);
+ }
+
+ [Fact]
+ public static void GetEnumerator_ItemsClearedAfterGetEnumeratorNotIncluded()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
+
+ object key1 = new object(), key2 = new object(), value1 = new object(), value2 = new object();
+
+ cwt.Add(key1, value1);
+ cwt.Add(key2, value2);
+ IEnumerator<KeyValuePair<object, object>> enumerator1 = enumerable.GetEnumerator();
+ cwt.Clear();
+ IEnumerator<KeyValuePair<object, object>> enumerator2 = enumerable.GetEnumerator();
+
+ Assert.False(enumerator1.MoveNext());
+ Assert.False(enumerator2.MoveNext());
+
+ enumerator1.Dispose();
+ enumerator2.Dispose();
+
+ GC.KeepAlive(key1);
+ GC.KeepAlive(key2);
+ GC.KeepAlive(value1);
+ GC.KeepAlive(value2);
+ }
+
+ [Fact]
+ public static void GetEnumerator_Current_ThrowsOnInvalidUse()
+ {
+ var cwt = new ConditionalWeakTable<object, object>();
+ var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
+
+ object key1 = new object(), value1 = new object();
+ cwt.Add(key1, value1);
+
+ using (IEnumerator<KeyValuePair<object, object>> enumerator = enumerable.GetEnumerator())
+ {
+ Assert.Throws<InvalidOperationException>(() => enumerator.Current); // before first MoveNext
+ }
+
+ GC.KeepAlive(key1);
+ GC.KeepAlive(value1);
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Linq;
-using Xunit;
-
-namespace System.Runtime.CompilerServices.Tests
-{
- public partial class ConditionalWeakTableTests
- {
- [Fact]
- public static void AddOrUpdateDataTest()
- {
- var cwt = new ConditionalWeakTable<string, string>();
- string key = "key1";
- cwt.AddOrUpdate(key, "value1");
-
- string value;
- Assert.True(cwt.TryGetValue(key, out value));
- Assert.Equal("value1", value);
- Assert.Equal(value, cwt.GetOrCreateValue(key));
- Assert.Equal(value, cwt.GetValue(key, k => "value1"));
-
- Assert.Throws<ArgumentNullException>(() => cwt.AddOrUpdate(null, "value2"));
-
- cwt.AddOrUpdate(key, "value2");
- Assert.True(cwt.TryGetValue(key, out value));
- Assert.Equal("value2", value);
- Assert.Equal(value, cwt.GetOrCreateValue(key));
- Assert.Equal(value, cwt.GetValue(key, k => "value1"));
- }
-
- [Fact]
- public static void Clear_EmptyTable()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- cwt.Clear(); // no exception
- cwt.Clear();
- }
-
- [Fact]
- public static void Clear_AddThenEmptyRepeatedly_ItemsRemoved()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- object key = new object(), value = new object();
- object result;
- for (int i = 0; i < 3; i++)
- {
- cwt.Add(key, value);
-
- Assert.True(cwt.TryGetValue(key, out result));
- Assert.Same(value, result);
-
- cwt.Clear();
-
- Assert.False(cwt.TryGetValue(key, out result));
- Assert.Null(result);
- }
- }
-
- [Fact]
- public static void Clear_AddMany_Clear_AllItemsRemoved()
- {
- var cwt = new ConditionalWeakTable<object, object>();
-
- object[] keys = Enumerable.Range(0, 33).Select(_ => new object()).ToArray();
- object[] values = Enumerable.Range(0, keys.Length).Select(_ => new object()).ToArray();
- for (int i = 0; i < keys.Length; i++)
- {
- cwt.Add(keys[i], values[i]);
- }
-
- Assert.Equal(keys.Length, ((IEnumerable<KeyValuePair<object, object>>)cwt).Count());
-
- cwt.Clear();
-
- Assert.Equal(0, ((IEnumerable<KeyValuePair<object, object>>)cwt).Count());
-
- GC.KeepAlive(keys);
- GC.KeepAlive(values);
- }
-
- [Fact]
- public static void GetEnumerator_Empty_ReturnsEmptyEnumerator()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
- Assert.Equal(0, enumerable.Count());
- }
-
- [Fact]
- public static void GetEnumerator_AddedAndRemovedItems_AppropriatelyShowUpInEnumeration()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
-
- object key1 = new object(), value1 = new object();
-
- for (int i = 0; i < 20; i++) // adding and removing multiple times, across internal container boundary
- {
- cwt.Add(key1, value1);
- Assert.Equal(1, enumerable.Count());
- Assert.Equal(new KeyValuePair<object, object>(key1, value1), enumerable.First());
-
- Assert.True(cwt.Remove(key1));
- Assert.Equal(0, enumerable.Count());
- }
-
- GC.KeepAlive(key1);
- GC.KeepAlive(value1);
- }
-
- [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsPreciseGcSupported))]
- public static void GetEnumerator_CollectedItemsNotEnumerated()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
-
- // Delegate to add collectible items to the table, separated out
- // to avoid the JIT extending the lifetimes of the temporaries
- Action<ConditionalWeakTable<object, object>> addItem =
- t => t.Add(new object(), new object());
-
- for (int i = 0; i < 10; i++) addItem(cwt);
- GC.Collect();
- Assert.Equal(0, enumerable.Count());
- }
-
- [Fact]
- public static void GetEnumerator_MultipleEnumeratorsReturnSameResults()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
-
- object[] keys = Enumerable.Range(0, 33).Select(_ => new object()).ToArray();
- object[] values = Enumerable.Range(0, keys.Length).Select(_ => new object()).ToArray();
- for (int i = 0; i < keys.Length; i++)
- {
- cwt.Add(keys[i], values[i]);
- }
-
- using (IEnumerator<KeyValuePair<object, object>> enumerator1 = enumerable.GetEnumerator())
- using (IEnumerator<KeyValuePair<object, object>> enumerator2 = enumerable.GetEnumerator())
- {
- while (enumerator1.MoveNext())
- {
- Assert.True(enumerator2.MoveNext());
- Assert.Equal(enumerator1.Current, enumerator2.Current);
- }
- Assert.False(enumerator2.MoveNext());
- }
-
- GC.KeepAlive(keys);
- GC.KeepAlive(values);
- }
-
- [Fact]
- public static void GetEnumerator_RemovedItems_RemovedFromResults()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
-
- object[] keys = Enumerable.Range(0, 33).Select(_ => new object()).ToArray();
- object[] values = Enumerable.Range(0, keys.Length).Select(_ => new object()).ToArray();
- for (int i = 0; i < keys.Length; i++)
- {
- cwt.Add(keys[i], values[i]);
- }
-
- for (int i = 0; i < keys.Length; i++)
- {
- Assert.Equal(keys.Length - i, enumerable.Count());
- Assert.Equal(
- Enumerable.Range(i, keys.Length - i).Select(j => new KeyValuePair<object, object>(keys[j], values[j])),
- enumerable);
- cwt.Remove(keys[i]);
- }
- Assert.Equal(0, enumerable.Count());
-
- GC.KeepAlive(keys);
- GC.KeepAlive(values);
- }
-
- [Fact]
- public static void GetEnumerator_ItemsAddedAfterGetEnumeratorNotIncluded()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
-
- object key1 = new object(), key2 = new object(), value1 = new object(), value2 = new object();
-
- cwt.Add(key1, value1);
- IEnumerator<KeyValuePair<object, object>> enumerator1 = enumerable.GetEnumerator();
- cwt.Add(key2, value2);
- IEnumerator<KeyValuePair<object, object>> enumerator2 = enumerable.GetEnumerator();
-
- Assert.True(enumerator1.MoveNext());
- Assert.Equal(new KeyValuePair<object, object>(key1, value1), enumerator1.Current);
- Assert.False(enumerator1.MoveNext());
-
- Assert.True(enumerator2.MoveNext());
- Assert.Equal(new KeyValuePair<object, object>(key1, value1), enumerator2.Current);
- Assert.True(enumerator2.MoveNext());
- Assert.Equal(new KeyValuePair<object, object>(key2, value2), enumerator2.Current);
- Assert.False(enumerator2.MoveNext());
-
- enumerator1.Dispose();
- enumerator2.Dispose();
-
- GC.KeepAlive(key1);
- GC.KeepAlive(key2);
- GC.KeepAlive(value1);
- GC.KeepAlive(value2);
- }
-
- [Fact]
- public static void GetEnumerator_ItemsRemovedAfterGetEnumeratorNotIncluded()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
-
- object key1 = new object(), key2 = new object(), value1 = new object(), value2 = new object();
-
- cwt.Add(key1, value1);
- cwt.Add(key2, value2);
- IEnumerator<KeyValuePair<object, object>> enumerator1 = enumerable.GetEnumerator();
- cwt.Remove(key1);
- IEnumerator<KeyValuePair<object, object>> enumerator2 = enumerable.GetEnumerator();
-
- Assert.True(enumerator1.MoveNext());
- Assert.Equal(new KeyValuePair<object, object>(key2, value2), enumerator1.Current);
- Assert.False(enumerator1.MoveNext());
-
- Assert.True(enumerator2.MoveNext());
- Assert.Equal(new KeyValuePair<object, object>(key2, value2), enumerator2.Current);
- Assert.False(enumerator2.MoveNext());
-
- enumerator1.Dispose();
- enumerator2.Dispose();
-
- GC.KeepAlive(key1);
- GC.KeepAlive(key2);
- GC.KeepAlive(value1);
- GC.KeepAlive(value2);
- }
-
- [Fact]
- public static void GetEnumerator_ItemsClearedAfterGetEnumeratorNotIncluded()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
-
- object key1 = new object(), key2 = new object(), value1 = new object(), value2 = new object();
-
- cwt.Add(key1, value1);
- cwt.Add(key2, value2);
- IEnumerator<KeyValuePair<object, object>> enumerator1 = enumerable.GetEnumerator();
- cwt.Clear();
- IEnumerator<KeyValuePair<object, object>> enumerator2 = enumerable.GetEnumerator();
-
- Assert.False(enumerator1.MoveNext());
- Assert.False(enumerator2.MoveNext());
-
- enumerator1.Dispose();
- enumerator2.Dispose();
-
- GC.KeepAlive(key1);
- GC.KeepAlive(key2);
- GC.KeepAlive(value1);
- GC.KeepAlive(value2);
- }
-
- [Fact]
- public static void GetEnumerator_Current_ThrowsOnInvalidUse()
- {
- var cwt = new ConditionalWeakTable<object, object>();
- var enumerable = (IEnumerable<KeyValuePair<object, object>>)cwt;
-
- object key1 = new object(), value1 = new object();
- cwt.Add(key1, value1);
-
- using (IEnumerator<KeyValuePair<object, object>> enumerator = enumerable.GetEnumerator())
- {
- Assert.Throws<InvalidOperationException>(() => enumerator.Current); // before first MoveNext
- }
-
- GC.KeepAlive(key1);
- GC.KeepAlive(value1);
- }
- }
-}
namespace System.Runtime.CompilerServices.Tests
{
- public static partial class RuntimeFeatureTests
+ public static class RuntimeFeatureTests
{
[Fact]
public static void PortablePdb()
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using Xunit;
namespace System.Runtime.CompilerServices.Tests
{
- public static partial class RuntimeHelpersTests
+ public static class RuntimeHelpersTests
{
[Fact]
public static void GetHashCodeTest()
RuntimeHelpers.PrepareDelegate((Func<int>)(() => 1) + (Func<int>)(() => 2));
RuntimeHelpers.PrepareDelegate(null);
}
- }
- public struct Age
- {
- public int years;
- public int months;
- }
+ [Fact]
+ public static void TryEnsureSufficientExecutionStack_SpaceAvailable_ReturnsTrue()
+ {
+ Assert.True(RuntimeHelpers.TryEnsureSufficientExecutionStack());
+ }
- public class FixedClass
- {
- [FixedAddressValueType]
- public static Age FixedAge;
+ [Fact]
+ public static void TryEnsureSufficientExecutionStack_NoSpaceAvailable_ReturnsFalse()
+ {
+ FillStack(depth: 0);
+ }
- public static unsafe IntPtr AddressOfFixedAge()
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void FillStack(int depth)
{
- fixed (Age* pointer = &FixedAge)
+ // This test will fail with a StackOverflowException if TryEnsureSufficientExecutionStack() doesn't
+ // return false. No exception is thrown and the test finishes when TryEnsureSufficientExecutionStack()
+ // returns true.
+ if (!RuntimeHelpers.TryEnsureSufficientExecutionStack())
{
- return (IntPtr)pointer;
+ Assert.Throws<InsufficientExecutionStackException>(() => RuntimeHelpers.EnsureSufficientExecutionStack());
+ return;
+ }
+ else if (depth < 2048)
+ {
+ FillStack(depth + 1);
}
}
- }
- public static partial class RuntimeHelpersTests
- {
+ [Fact]
+ public static void GetUninitializedObject_InvalidArguments_ThrowsException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("type", () => RuntimeHelpers.GetUninitializedObject(null));
+
+ AssertExtensions.Throws<ArgumentException>(null, () => RuntimeHelpers.GetUninitializedObject(typeof(string))); // special type
+ Assert.Throws<MemberAccessException>(() => RuntimeHelpers.GetUninitializedObject(typeof(System.IO.Stream))); // abstract type
+ Assert.Throws<MemberAccessException>(() => RuntimeHelpers.GetUninitializedObject(typeof(System.Collections.IEnumerable))); // interface
+ Assert.Throws<MemberAccessException>(() => RuntimeHelpers.GetUninitializedObject(typeof(System.Collections.Generic.List<>))); // generic definition
+ Assert.Throws<NotSupportedException>(() => RuntimeHelpers.GetUninitializedObject(typeof(TypedReference))); // byref-like type
+ }
+
+ [Fact]
+ public static void GetUninitializedObject_DoesNotRunConstructor()
+ {
+ Assert.Equal(42, new ObjectWithDefaultCtor().Value);
+ Assert.Equal(0, ((ObjectWithDefaultCtor)RuntimeHelpers.GetUninitializedObject(typeof(ObjectWithDefaultCtor))).Value);
+ }
+
+ [Fact]
+ public static void GetUninitializedObject_Nullable()
+ {
+ // Nullable returns the underlying type instead
+ Assert.Equal(typeof(int), RuntimeHelpers.GetUninitializedObject(typeof(Nullable<int>)).GetType());
+ }
+
+ private class ObjectWithDefaultCtor
+ {
+ public int Value = 42;
+ }
+
+ [Fact]
+ public static void IsReferenceOrContainsReferences()
+ {
+ Assert.False(RuntimeHelpers.IsReferenceOrContainsReferences<int>());
+ Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences<string>());
+ Assert.False(RuntimeHelpers.IsReferenceOrContainsReferences<Guid>());
+ Assert.False(RuntimeHelpers.IsReferenceOrContainsReferences<StructWithoutReferences>());
+ Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences<StructWithReferences>());
+ }
+
+ [Fact]
+ public static void ArrayRangeHelperTest()
+ {
+ int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ Range range = Range.All;
+ Assert.Equal(a, RuntimeHelpers.GetSubArray(a, range));
+
+ range = new Range(Index.FromStart(1), Index.FromEnd(5));
+ Assert.Equal(new int [] { 2, 3, 4, 5}, RuntimeHelpers.GetSubArray(a, range));
+
+ range = new Range(Index.FromStart(0), Index.FromStart(a.Length + 1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => { int [] array = RuntimeHelpers.GetSubArray(a, range); });
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ private struct StructWithoutReferences
+ {
+ public int a, b, c;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ private struct StructWithReferences
+ {
+ public int a, b, c;
+ public object d;
+ }
+
[Fact]
public static void FixedAddressValueTypeTest()
{
Assert.Equal(fixedPtr1, fixedPtr2);
}
}
+
+ public struct Age
+ {
+ public int years;
+ public int months;
+ }
+
+ public class FixedClass
+ {
+ [FixedAddressValueType]
+ public static Age FixedAge;
+
+ public static unsafe IntPtr AddressOfFixedAge()
+ {
+ fixed (Age* pointer = &FixedAge)
+ {
+ return (IntPtr)pointer;
+ }
+ }
+ }
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Runtime.InteropServices;
-
-using Xunit;
-
-namespace System.Runtime.CompilerServices.Tests
-{
- public static partial class RuntimeHelpersTests
- {
- [Fact]
- public static void TryEnsureSufficientExecutionStack_SpaceAvailable_ReturnsTrue()
- {
- Assert.True(RuntimeHelpers.TryEnsureSufficientExecutionStack());
- }
-
- [Fact]
- public static void TryEnsureSufficientExecutionStack_NoSpaceAvailable_ReturnsFalse()
- {
- FillStack(depth: 0);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- private static void FillStack(int depth)
- {
- // This test will fail with a StackOverflowException if TryEnsureSufficientExecutionStack() doesn't
- // return false. No exception is thrown and the test finishes when TryEnsureSufficientExecutionStack()
- // returns true.
- if (!RuntimeHelpers.TryEnsureSufficientExecutionStack())
- {
- Assert.Throws<InsufficientExecutionStackException>(() => RuntimeHelpers.EnsureSufficientExecutionStack());
- return;
- }
- else if (depth < 2048)
- {
- FillStack(depth + 1);
- }
- }
-
- [Fact]
- public static void GetUninitializedObject_InvalidArguments_ThrowsException()
- {
- AssertExtensions.Throws<ArgumentNullException>("type", () => RuntimeHelpers.GetUninitializedObject(null));
-
- AssertExtensions.Throws<ArgumentException>(null, () => RuntimeHelpers.GetUninitializedObject(typeof(string))); // special type
- Assert.Throws<MemberAccessException>(() => RuntimeHelpers.GetUninitializedObject(typeof(System.IO.Stream))); // abstract type
- Assert.Throws<MemberAccessException>(() => RuntimeHelpers.GetUninitializedObject(typeof(System.Collections.IEnumerable))); // interface
- Assert.Throws<MemberAccessException>(() => RuntimeHelpers.GetUninitializedObject(typeof(System.Collections.Generic.List<>))); // generic definition
- Assert.Throws<NotSupportedException>(() => RuntimeHelpers.GetUninitializedObject(typeof(TypedReference))); // byref-like type
- }
-
- [Fact]
- public static void GetUninitializedObject_DoesNotRunConstructor()
- {
- Assert.Equal(42, new ObjectWithDefaultCtor().Value);
- Assert.Equal(0, ((ObjectWithDefaultCtor)RuntimeHelpers.GetUninitializedObject(typeof(ObjectWithDefaultCtor))).Value);
- }
-
- [Fact]
- public static void GetUninitializedObject_Nullable()
- {
- // Nullable returns the underlying type instead
- Assert.Equal(typeof(int), RuntimeHelpers.GetUninitializedObject(typeof(Nullable<int>)).GetType());
- }
-
- private class ObjectWithDefaultCtor
- {
- public int Value = 42;
- }
-
- [Fact]
- public static void IsReferenceOrContainsReferences()
- {
- Assert.False(RuntimeHelpers.IsReferenceOrContainsReferences<int>());
- Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences<string>());
- Assert.False(RuntimeHelpers.IsReferenceOrContainsReferences<Guid>());
- Assert.False(RuntimeHelpers.IsReferenceOrContainsReferences<StructWithoutReferences>());
- Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences<StructWithReferences>());
- }
-
- [Fact]
- public static void ArrayRangeHelperTest()
- {
- int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- Range range = Range.All;
- Assert.Equal(a, RuntimeHelpers.GetSubArray(a, range));
-
- range = new Range(Index.FromStart(1), Index.FromEnd(5));
- Assert.Equal(new int [] { 2, 3, 4, 5}, RuntimeHelpers.GetSubArray(a, range));
-
- range = new Range(Index.FromStart(0), Index.FromStart(a.Length + 1));
- Assert.Throws<ArgumentOutOfRangeException>(() => { int [] array = RuntimeHelpers.GetSubArray(a, range); });
- }
-
- [StructLayoutAttribute(LayoutKind.Sequential)]
- private struct StructWithoutReferences
- {
- public int a, b, c;
- }
-
- [StructLayoutAttribute(LayoutKind.Sequential)]
- private struct StructWithReferences
- {
- public int a, b, c;
- public object d;
- }
- }
-}
namespace System.Runtime.ExceptionServices.Tests
{
- public partial class ExceptionDispatchInfoTests
+ public class ExceptionDispatchInfoTests
{
[Fact]
public static void StaticThrow_NullArgument_ThrowArgumentNullException()
AssertExtensions.Throws<ArgumentException>(paramName, () => sbyte.Parse("1", style));
AssertExtensions.Throws<ArgumentException>(paramName, () => sbyte.Parse("1", style, null));
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ yield return new object[] { "-123", 0, 2, NumberStyles.Integer, null, (sbyte)-1 };
+ yield return new object[] { "-123", 1, 3, NumberStyles.Integer, null, (sbyte)123 };
+ yield return new object[] { "12", 0, 1, NumberStyles.HexNumber, null, (sbyte)0x1 };
+ yield return new object[] { "12", 1, 1, NumberStyles.HexNumber, null, (sbyte)0x2 };
+ yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, null, (sbyte)123 };
+ yield return new object[] { "$100", 1, 1, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (sbyte)1 };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, sbyte expected)
+ {
+ sbyte result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.True(sbyte.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+ }
+
+ Assert.Equal(expected, sbyte.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(sbyte.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ sbyte result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.False(sbyte.TryParse(value.AsSpan(), out result));
+ Assert.Equal(0, result);
+ }
+
+ Assert.Throws(exceptionType, () => sbyte.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(sbyte.TryParse(value.AsSpan(), style, provider, out result));
+ Assert.Equal(0, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat(sbyte i, string format, IFormatProvider provider, string expected)
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual));
+
+ // Longer than needed
+ actual = new char[expected.Length + 1];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (expected.Length > 0)
+ {
+ actual = new char[expected.Length - 1];
+ Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(0, charsWritten);
+ }
+
+ if (format != null)
+ {
+ // Upper format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToUpperInvariant(), new string(actual));
+
+ // Lower format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToLowerInvariant(), new string(actual));
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class SByteTests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- yield return new object[] { "-123", 0, 2, NumberStyles.Integer, null, (sbyte)-1 };
- yield return new object[] { "-123", 1, 3, NumberStyles.Integer, null, (sbyte)123 };
- yield return new object[] { "12", 0, 1, NumberStyles.HexNumber, null, (sbyte)0x1 };
- yield return new object[] { "12", 1, 1, NumberStyles.HexNumber, null, (sbyte)0x2 };
- yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, null, (sbyte)123 };
- yield return new object[] { "$100", 1, 1, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (sbyte)1 };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, sbyte expected)
- {
- sbyte result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.True(sbyte.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
- }
-
- Assert.Equal(expected, sbyte.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(sbyte.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- sbyte result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.False(sbyte.TryParse(value.AsSpan(), out result));
- Assert.Equal(0, result);
- }
-
- Assert.Throws(exceptionType, () => sbyte.Parse(value.AsSpan(), style, provider));
-
- Assert.False(sbyte.TryParse(value.AsSpan(), style, provider, out result));
- Assert.Equal(0, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat(sbyte i, string format, IFormatProvider provider, string expected)
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual));
-
- // Longer than needed
- actual = new char[expected.Length + 1];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual, 0, charsWritten));
-
- // Too short
- if (expected.Length > 0)
- {
- actual = new char[expected.Length - 1];
- Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(0, charsWritten);
- }
-
- if (format != null)
- {
- // Upper format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToUpperInvariant(), new string(actual));
-
- // Lower format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToLowerInvariant(), new string(actual));
- }
- }
- }
-}
Assert.Throws<FormatException>(() => f.ToString("Y")); // Invalid format
Assert.Throws<FormatException>(() => f.ToString("Y", null)); // Invalid format
}
+
+ [Theory]
+ [InlineData(float.NegativeInfinity, false)] // Negative Infinity
+ [InlineData(float.MinValue, true)] // Min Negative Normal
+ [InlineData(-1.17549435E-38f, true)] // Max Negative Normal
+ [InlineData(-1.17549421E-38f, true)] // Min Negative Subnormal
+ [InlineData(-1.401298E-45, true)] // Max Negative Subnormal
+ [InlineData(-0.0f, true)] // Negative Zero
+ [InlineData(float.NaN, false)] // NaN
+ [InlineData(0.0f, true)] // Positive Zero
+ [InlineData(1.401298E-45, true)] // Min Positive Subnormal
+ [InlineData(1.17549421E-38f, true)] // Max Positive Subnormal
+ [InlineData(1.17549435E-38f, true)] // Min Positive Normal
+ [InlineData(float.MaxValue, true)] // Max Positive Normal
+ [InlineData(float.PositiveInfinity, false)] // Positive Infinity
+ public static void IsFinite(float d, bool expected)
+ {
+ Assert.Equal(expected, float.IsFinite(d));
+ }
+
+ [Theory]
+ [InlineData(float.NegativeInfinity, true)] // Negative Infinity
+ [InlineData(float.MinValue, true)] // Min Negative Normal
+ [InlineData(-1.17549435E-38f, true)] // Max Negative Normal
+ [InlineData(-1.17549421E-38f, true)] // Min Negative Subnormal
+ [InlineData(-1.401298E-45, true)] // Max Negative Subnormal
+ [InlineData(-0.0f, true)] // Negative Zero
+ [InlineData(float.NaN, true)] // NaN
+ [InlineData(0.0f, false)] // Positive Zero
+ [InlineData(1.401298E-45, false)] // Min Positive Subnormal
+ [InlineData(1.17549421E-38f, false)] // Max Positive Subnormal
+ [InlineData(1.17549435E-38f, false)] // Min Positive Normal
+ [InlineData(float.MaxValue, false)] // Max Positive Normal
+ [InlineData(float.PositiveInfinity, false)] // Positive Infinity
+ public static void IsNegative(float d, bool expected)
+ {
+ Assert.Equal(expected, float.IsNegative(d));
+ }
+
+ [Theory]
+ [InlineData(float.NegativeInfinity, false)] // Negative Infinity
+ [InlineData(float.MinValue, true)] // Min Negative Normal
+ [InlineData(-1.17549435E-38f, true)] // Max Negative Normal
+ [InlineData(-1.17549421E-38f, false)] // Min Negative Subnormal
+ [InlineData(-1.401298E-45, false)] // Max Negative Subnormal
+ [InlineData(-0.0f, false)] // Negative Zero
+ [InlineData(float.NaN, false)] // NaN
+ [InlineData(0.0f, false)] // Positive Zero
+ [InlineData(1.401298E-45, false)] // Min Positive Subnormal
+ [InlineData(1.17549421E-38f, false)] // Max Positive Subnormal
+ [InlineData(1.17549435E-38f, true)] // Min Positive Normal
+ [InlineData(float.MaxValue, true)] // Max Positive Normal
+ [InlineData(float.PositiveInfinity, false)] // Positive Infinity
+ public static void IsNormal(float d, bool expected)
+ {
+ Assert.Equal(expected, float.IsNormal(d));
+ }
+
+ [Theory]
+ [InlineData(float.NegativeInfinity, false)] // Negative Infinity
+ [InlineData(float.MinValue, false)] // Min Negative Normal
+ [InlineData(-1.17549435E-38f, false)] // Max Negative Normal
+ [InlineData(-1.17549421E-38f, true)] // Min Negative Subnormal
+ [InlineData(-1.401298E-45, true)] // Max Negative Subnormal
+ [InlineData(-0.0f, false)] // Negative Zero
+ [InlineData(float.NaN, false)] // NaN
+ [InlineData(0.0f, false)] // Positive Zero
+ [InlineData(1.401298E-45, true)] // Min Positive Subnormal
+ [InlineData(1.17549421E-38f, true)] // Max Positive Subnormal
+ [InlineData(1.17549435E-38f, false)] // Min Positive Normal
+ [InlineData(float.MaxValue, false)] // Max Positive Normal
+ [InlineData(float.PositiveInfinity, false)] // Positive Infinity
+ public static void IsSubnormal(float d, bool expected)
+ {
+ Assert.Equal(expected, float.IsSubnormal(d));
+ }
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ const NumberStyles DefaultStyle = NumberStyles.Float | NumberStyles.AllowThousands;
+
+ yield return new object[] { "-123", 1, 3, DefaultStyle, null, (float)123 };
+ yield return new object[] { "-123", 0, 3, DefaultStyle, null, (float)-12 };
+ yield return new object[] { "1E23", 0, 3, DefaultStyle, null, (float)1E2 };
+ yield return new object[] { "123", 0, 2, NumberStyles.Float, new NumberFormatInfo(), (float)12 };
+ yield return new object[] { "$1,000", 1, 3, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$", CurrencyGroupSeparator = "," }, (float)10 };
+ yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, new NumberFormatInfo() { NumberDecimalSeparator = "." }, (float)123 };
+ yield return new object[] { "-Infinity", 1, 8, NumberStyles.Any, NumberFormatInfo.InvariantInfo, float.PositiveInfinity };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, float expected)
+ {
+ bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo;
+ float result;
+ if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None)
+ {
+ // Use Parse(string) or Parse(string, IFormatProvider)
+ if (isDefaultProvider)
+ {
+ Assert.True(float.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+
+ Assert.Equal(expected, float.Parse(value.AsSpan(offset, count)));
+ }
+
+ Assert.Equal(expected, float.Parse(value.AsSpan(offset, count), provider: provider));
+ }
+
+ Assert.Equal(expected, float.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(float.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ Assert.Throws(exceptionType, () => float.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(float.TryParse(value.AsSpan(), style, provider, out float result));
+ Assert.Equal(0, result);
+ }
+ }
+
+ [Fact]
+ public static void TryFormat()
+ {
+ using (new ThreadCultureChange(CultureInfo.InvariantCulture))
+ {
+ foreach (object[] testdata in ToString_TestData())
+ {
+ float localI = (float)testdata[0];
+ string localFormat = (string)testdata[1];
+ IFormatProvider localProvider = (IFormatProvider)testdata[2];
+ string localExpected = (string)testdata[3];
+
+ try
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[localExpected.Length];
+ Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
+ Assert.Equal(localExpected.Length, charsWritten);
+ Assert.Equal(localExpected, new string(actual));
+
+ // Longer than needed
+ actual = new char[localExpected.Length + 1];
+ Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
+ Assert.Equal(localExpected.Length, charsWritten);
+ Assert.Equal(localExpected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (localExpected.Length > 0)
+ {
+ actual = new char[localExpected.Length - 1];
+ Assert.False(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
+ Assert.Equal(0, charsWritten);
+ }
+ }
+ catch (Exception exc)
+ {
+ throw new Exception($"Failed on `{localI}`, `{localFormat}`, `{localProvider}`, `{localExpected}`. {exc}");
+ }
+ }
+ }
+ }
+
+ public static IEnumerable<object[]> ToStringRoundtrip_TestData()
+ {
+ yield return new object[] { float.NegativeInfinity };
+ yield return new object[] { float.MinValue };
+ yield return new object[] { -MathF.PI };
+ yield return new object[] { -MathF.E };
+ yield return new object[] { -float.Epsilon };
+ yield return new object[] { -0.845512408f };
+ yield return new object[] { -0.0f };
+ yield return new object[] { float.NaN };
+ yield return new object[] { 0.0f };
+ yield return new object[] { 0.845512408f };
+ yield return new object[] { float.Epsilon };
+ yield return new object[] { MathF.E };
+ yield return new object[] { MathF.PI };
+ yield return new object[] { float.MaxValue };
+ yield return new object[] { float.PositiveInfinity };
+ }
+
+ [Theory]
+ [MemberData(nameof(ToStringRoundtrip_TestData))]
+ public static void ToStringRoundtrip(float value)
+ {
+ float result = float.Parse(value.ToString());
+ Assert.Equal(BitConverter.SingleToInt32Bits(value), BitConverter.SingleToInt32Bits(result));
+ }
+
+ [Theory]
+ [MemberData(nameof(ToStringRoundtrip_TestData))]
+ public static void ToStringRoundtrip_R(float value)
+ {
+ float result = float.Parse(value.ToString("R"));
+ Assert.Equal(BitConverter.SingleToInt32Bits(value), BitConverter.SingleToInt32Bits(result));
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Microsoft.DotNet.RemoteExecutor;
-using Xunit;
-
-#pragma warning disable xUnit1025 // reporting duplicate test cases due to not distinguishing 0.0 from -0.0, NaN from -NaN
-
-namespace System.Tests
-{
- public partial class SingleTests
- {
- [Theory]
- [InlineData(float.NegativeInfinity, false)] // Negative Infinity
- [InlineData(float.MinValue, true)] // Min Negative Normal
- [InlineData(-1.17549435E-38f, true)] // Max Negative Normal
- [InlineData(-1.17549421E-38f, true)] // Min Negative Subnormal
- [InlineData(-1.401298E-45, true)] // Max Negative Subnormal
- [InlineData(-0.0f, true)] // Negative Zero
- [InlineData(float.NaN, false)] // NaN
- [InlineData(0.0f, true)] // Positive Zero
- [InlineData(1.401298E-45, true)] // Min Positive Subnormal
- [InlineData(1.17549421E-38f, true)] // Max Positive Subnormal
- [InlineData(1.17549435E-38f, true)] // Min Positive Normal
- [InlineData(float.MaxValue, true)] // Max Positive Normal
- [InlineData(float.PositiveInfinity, false)] // Positive Infinity
- public static void IsFinite(float d, bool expected)
- {
- Assert.Equal(expected, float.IsFinite(d));
- }
-
- [Theory]
- [InlineData(float.NegativeInfinity, true)] // Negative Infinity
- [InlineData(float.MinValue, true)] // Min Negative Normal
- [InlineData(-1.17549435E-38f, true)] // Max Negative Normal
- [InlineData(-1.17549421E-38f, true)] // Min Negative Subnormal
- [InlineData(-1.401298E-45, true)] // Max Negative Subnormal
- [InlineData(-0.0f, true)] // Negative Zero
- [InlineData(float.NaN, true)] // NaN
- [InlineData(0.0f, false)] // Positive Zero
- [InlineData(1.401298E-45, false)] // Min Positive Subnormal
- [InlineData(1.17549421E-38f, false)] // Max Positive Subnormal
- [InlineData(1.17549435E-38f, false)] // Min Positive Normal
- [InlineData(float.MaxValue, false)] // Max Positive Normal
- [InlineData(float.PositiveInfinity, false)] // Positive Infinity
- public static void IsNegative(float d, bool expected)
- {
- Assert.Equal(expected, float.IsNegative(d));
- }
-
- [Theory]
- [InlineData(float.NegativeInfinity, false)] // Negative Infinity
- [InlineData(float.MinValue, true)] // Min Negative Normal
- [InlineData(-1.17549435E-38f, true)] // Max Negative Normal
- [InlineData(-1.17549421E-38f, false)] // Min Negative Subnormal
- [InlineData(-1.401298E-45, false)] // Max Negative Subnormal
- [InlineData(-0.0f, false)] // Negative Zero
- [InlineData(float.NaN, false)] // NaN
- [InlineData(0.0f, false)] // Positive Zero
- [InlineData(1.401298E-45, false)] // Min Positive Subnormal
- [InlineData(1.17549421E-38f, false)] // Max Positive Subnormal
- [InlineData(1.17549435E-38f, true)] // Min Positive Normal
- [InlineData(float.MaxValue, true)] // Max Positive Normal
- [InlineData(float.PositiveInfinity, false)] // Positive Infinity
- public static void IsNormal(float d, bool expected)
- {
- Assert.Equal(expected, float.IsNormal(d));
- }
-
- [Theory]
- [InlineData(float.NegativeInfinity, false)] // Negative Infinity
- [InlineData(float.MinValue, false)] // Min Negative Normal
- [InlineData(-1.17549435E-38f, false)] // Max Negative Normal
- [InlineData(-1.17549421E-38f, true)] // Min Negative Subnormal
- [InlineData(-1.401298E-45, true)] // Max Negative Subnormal
- [InlineData(-0.0f, false)] // Negative Zero
- [InlineData(float.NaN, false)] // NaN
- [InlineData(0.0f, false)] // Positive Zero
- [InlineData(1.401298E-45, true)] // Min Positive Subnormal
- [InlineData(1.17549421E-38f, true)] // Max Positive Subnormal
- [InlineData(1.17549435E-38f, false)] // Min Positive Normal
- [InlineData(float.MaxValue, false)] // Max Positive Normal
- [InlineData(float.PositiveInfinity, false)] // Positive Infinity
- public static void IsSubnormal(float d, bool expected)
- {
- Assert.Equal(expected, float.IsSubnormal(d));
- }
-
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- const NumberStyles DefaultStyle = NumberStyles.Float | NumberStyles.AllowThousands;
-
- yield return new object[] { "-123", 1, 3, DefaultStyle, null, (float)123 };
- yield return new object[] { "-123", 0, 3, DefaultStyle, null, (float)-12 };
- yield return new object[] { "1E23", 0, 3, DefaultStyle, null, (float)1E2 };
- yield return new object[] { "123", 0, 2, NumberStyles.Float, new NumberFormatInfo(), (float)12 };
- yield return new object[] { "$1,000", 1, 3, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$", CurrencyGroupSeparator = "," }, (float)10 };
- yield return new object[] { "(123)", 1, 3, NumberStyles.AllowParentheses, new NumberFormatInfo() { NumberDecimalSeparator = "." }, (float)123 };
- yield return new object[] { "-Infinity", 1, 8, NumberStyles.Any, NumberFormatInfo.InvariantInfo, float.PositiveInfinity };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, float expected)
- {
- bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo;
- float result;
- if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None)
- {
- // Use Parse(string) or Parse(string, IFormatProvider)
- if (isDefaultProvider)
- {
- Assert.True(float.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
-
- Assert.Equal(expected, float.Parse(value.AsSpan(offset, count)));
- }
-
- Assert.Equal(expected, float.Parse(value.AsSpan(offset, count), provider: provider));
- }
-
- Assert.Equal(expected, float.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(float.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- Assert.Throws(exceptionType, () => float.Parse(value.AsSpan(), style, provider));
-
- Assert.False(float.TryParse(value.AsSpan(), style, provider, out float result));
- Assert.Equal(0, result);
- }
- }
-
- [Fact]
- public static void TryFormat()
- {
- using (new ThreadCultureChange(CultureInfo.InvariantCulture))
- {
- foreach (object[] testdata in ToString_TestData())
- {
- float localI = (float)testdata[0];
- string localFormat = (string)testdata[1];
- IFormatProvider localProvider = (IFormatProvider)testdata[2];
- string localExpected = (string)testdata[3];
-
- try
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[localExpected.Length];
- Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
- Assert.Equal(localExpected.Length, charsWritten);
- Assert.Equal(localExpected, new string(actual));
-
- // Longer than needed
- actual = new char[localExpected.Length + 1];
- Assert.True(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
- Assert.Equal(localExpected.Length, charsWritten);
- Assert.Equal(localExpected, new string(actual, 0, charsWritten));
-
- // Too short
- if (localExpected.Length > 0)
- {
- actual = new char[localExpected.Length - 1];
- Assert.False(localI.TryFormat(actual.AsSpan(), out charsWritten, localFormat, localProvider));
- Assert.Equal(0, charsWritten);
- }
- }
- catch (Exception exc)
- {
- throw new Exception($"Failed on `{localI}`, `{localFormat}`, `{localProvider}`, `{localExpected}`. {exc}");
- }
- }
- }
- }
-
- public static IEnumerable<object[]> ToStringRoundtrip_TestData()
- {
- yield return new object[] { float.NegativeInfinity };
- yield return new object[] { float.MinValue };
- yield return new object[] { -MathF.PI };
- yield return new object[] { -MathF.E };
- yield return new object[] { -float.Epsilon };
- yield return new object[] { -0.845512408f };
- yield return new object[] { -0.0f };
- yield return new object[] { float.NaN };
- yield return new object[] { 0.0f };
- yield return new object[] { 0.845512408f };
- yield return new object[] { float.Epsilon };
- yield return new object[] { MathF.E };
- yield return new object[] { MathF.PI };
- yield return new object[] { float.MaxValue };
- yield return new object[] { float.PositiveInfinity };
- }
-
- [Theory]
- [MemberData(nameof(ToStringRoundtrip_TestData))]
- public static void ToStringRoundtrip(float value)
- {
- float result = float.Parse(value.ToString());
- Assert.Equal(BitConverter.SingleToInt32Bits(value), BitConverter.SingleToInt32Bits(result));
- }
-
- [Theory]
- [MemberData(nameof(ToStringRoundtrip_TestData))]
- public static void ToStringRoundtrip_R(float value)
- {
- float result = float.Parse(value.ToString("R"));
- Assert.Equal(BitConverter.SingleToInt32Bits(value), BitConverter.SingleToInt32Bits(result));
- }
- }
-}
namespace System.Tests
{
- public partial class StringComparerTests
+ public class StringComparerTests
{
[Fact]
public void Create_InvalidArguments_Throws()
Assert.False(c.Equals("42", 84));
Assert.False(c.Equals(42, "84"));
}
+
+ [Fact]
+ public void CreateCultureOptions_InvalidArguments_Throws()
+ {
+ Assert.Throws<ArgumentNullException>(() => StringComparer.Create(null, CompareOptions.None));
+ }
+
+ [Fact]
+ public void CreateCultureOptions_CreatesValidComparer()
+ {
+ StringComparer c = StringComparer.Create(CultureInfo.InvariantCulture, CompareOptions.IgnoreCase);
+ Assert.NotNull(c);
+ Assert.True(c.Equals((object)"hello", (object)"HEllO"));
+ Assert.True(c.Equals("hello", "HEllO"));
+ Assert.False(c.Equals((object)"bello", (object)"HEllO"));
+ Assert.False(c.Equals("bello", "HEllO"));
+
+ object obj = new object();
+ Assert.Equal(c.GetHashCode((object)"hello"), c.GetHashCode((object)"hello"));
+ Assert.Equal(c.GetHashCode("hello"), c.GetHashCode("hello"));
+ Assert.Equal(c.GetHashCode("hello"), c.GetHashCode((object)"hello"));
+ Assert.Equal(obj.GetHashCode(), c.GetHashCode(obj));
+ Assert.Equal(42.CompareTo(84), c.Compare(42, 84));
+ Assert.Throws<ArgumentException>(() => c.Compare("42", 84));
+ Assert.Equal(1, c.Compare("42", null));
+ Assert.Throws<ArgumentException>(() => c.Compare(42, "84"));
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class StringComparerTests
- {
- [Fact]
- public void CreateCultureOptions_InvalidArguments_Throws()
- {
- Assert.Throws<ArgumentNullException>(() => StringComparer.Create(null, CompareOptions.None));
- }
-
- [Fact]
- public void CreateCultureOptions_CreatesValidComparer()
- {
- StringComparer c = StringComparer.Create(CultureInfo.InvariantCulture, CompareOptions.IgnoreCase);
- Assert.NotNull(c);
- Assert.True(c.Equals((object)"hello", (object)"HEllO"));
- Assert.True(c.Equals("hello", "HEllO"));
- Assert.False(c.Equals((object)"bello", (object)"HEllO"));
- Assert.False(c.Equals("bello", "HEllO"));
-
- object obj = new object();
- Assert.Equal(c.GetHashCode((object)"hello"), c.GetHashCode((object)"hello"));
- Assert.Equal(c.GetHashCode("hello"), c.GetHashCode("hello"));
- Assert.Equal(c.GetHashCode("hello"), c.GetHashCode((object)"hello"));
- Assert.Equal(obj.GetHashCode(), c.GetHashCode(obj));
- Assert.Equal(42.CompareTo(84), c.Compare(42, 84));
- Assert.Throws<ArgumentException>(() => c.Compare("42", 84));
- Assert.Equal(1, c.Compare("42", null));
- Assert.Throws<ArgumentException>(() => c.Compare(42, "84"));
- }
- }
-}
namespace System.Tests
{
- public partial class StringGetHashCodeTests
+ public class StringGetHashCodeTests
{
/// <summary>
/// Ensure that hash codes are randomized by getting the hash in two processes
() => { return CultureInfo.CurrentCulture.CompareInfo.GetHashCode("abc", CompareOptions.Ordinal); },
() => { return CultureInfo.CurrentCulture.CompareInfo.GetHashCode("abc", CompareOptions.OrdinalIgnoreCase); }
};
+
+ [Theory]
+ [MemberData(nameof(GetHashCodeOrdinalIgnoreCase_TestData))]
+ public void GetHashCode_OrdinalIgnoreCase_ReturnsSameHashCodeAsUpperCaseOrdinal(string input)
+ {
+ // As an implementation detail, the OrdinalIgnoreCase hash code calculation is simply the hash code
+ // of the upper-invariant version of the input string.
+
+ Assert.Equal(input.ToUpperInvariant().GetHashCode(), input.GetHashCode(StringComparison.OrdinalIgnoreCase));
+ }
+
+ public static IEnumerable<object[]> GetHashCodeOrdinalIgnoreCase_TestData()
+ {
+ // 0 through 8 char lowercase & uppercase ASCII strings
+ // tests the various branches within the hash code calculation routines
+
+ for (int i = 0; i <= 8; i++)
+ {
+ yield return new object[] { "abcdefgh".Substring(0, i) };
+ yield return new object[] { "ABCDEFGH".Substring(0, i) };
+ }
+
+ // 16 char mixed case mostly-ASCII string plus one non-ASCII character inserted at various locations
+ // tests fallback logic for OrdinalIgnoreCase hash
+
+ for (int i = 0; i <= 16; i++)
+ {
+ yield return new object[] { "AaBbCcDdEeFfGgHh".Insert(i, "\u00E9" /* LATIN SMALL LETTER E WITH ACUTE */) };
+ yield return new object[] { "AaBbCcDdEeFfGgHh".Insert(i, "\u044D" /* CYRILLIC SMALL LETTER E */) };
+ yield return new object[] { "AaBbCcDdEeFfGgHh".Insert(i, "\u0131" /* LATIN SMALL LETTER DOTLESS I */) };
+ }
+
+ // Various texts copied from Microsoft's non-U.S. home pages, for further localization tests
+
+ yield return new object[] { "\u0418\u0433\u0440\u044B \u0438 \u0440\u0430\u0437\u0432\u043B\u0435\u0447\u0435\u043D\u0438\u044F \u0431\u0435\u0437 \u0433\u0440\u0430\u043D\u0438\u0446 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0435 4K." }; // ru-RU
+ yield return new object[] { "Poder port\u00E1til." }; // es-ES
+ yield return new object[] { "\u60F3\u50CF\u3092\u8D85\u3048\u305F\u3001\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u3092\u3002" }; // ja-JP
+ yield return new object[] { "\u00C9l\u00E9gant et performant." }; // fr-FR
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class StringGetHashCodeTests
- {
- [Theory]
- [MemberData(nameof(GetHashCodeOrdinalIgnoreCase_TestData))]
- public void GetHashCode_OrdinalIgnoreCase_ReturnsSameHashCodeAsUpperCaseOrdinal(string input)
- {
- // As an implementation detail, the OrdinalIgnoreCase hash code calculation is simply the hash code
- // of the upper-invariant version of the input string.
-
- Assert.Equal(input.ToUpperInvariant().GetHashCode(), input.GetHashCode(StringComparison.OrdinalIgnoreCase));
- }
-
- public static IEnumerable<object[]> GetHashCodeOrdinalIgnoreCase_TestData()
- {
- // 0 through 8 char lowercase & uppercase ASCII strings
- // tests the various branches within the hash code calculation routines
-
- for (int i = 0; i <= 8; i++)
- {
- yield return new object[] { "abcdefgh".Substring(0, i) };
- yield return new object[] { "ABCDEFGH".Substring(0, i) };
- }
-
- // 16 char mixed case mostly-ASCII string plus one non-ASCII character inserted at various locations
- // tests fallback logic for OrdinalIgnoreCase hash
-
- for (int i = 0; i <= 16; i++)
- {
- yield return new object[] { "AaBbCcDdEeFfGgHh".Insert(i, "\u00E9" /* LATIN SMALL LETTER E WITH ACUTE */) };
- yield return new object[] { "AaBbCcDdEeFfGgHh".Insert(i, "\u044D" /* CYRILLIC SMALL LETTER E */) };
- yield return new object[] { "AaBbCcDdEeFfGgHh".Insert(i, "\u0131" /* LATIN SMALL LETTER DOTLESS I */) };
- }
-
- // Various texts copied from Microsoft's non-U.S. home pages, for further localization tests
-
- yield return new object[] { "\u0418\u0433\u0440\u044B \u0438 \u0440\u0430\u0437\u0432\u043B\u0435\u0447\u0435\u043D\u0438\u044F \u0431\u0435\u0437 \u0433\u0440\u0430\u043D\u0438\u0446 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0435 4K." }; // ru-RU
- yield return new object[] { "Poder port\u00E1til." }; // es-ES
- yield return new object[] { "\u60F3\u50CF\u3092\u8D85\u3048\u305F\u3001\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u3092\u3002" }; // ja-JP
- yield return new object[] { "\u00C9l\u00E9gant et performant." }; // fr-FR
- }
- }
-}
{
// Since many of the methods we'll be testing are internal, we'll need to invoke
// them via reflection.
- public static unsafe partial class AsciiUtilityTests
+ public static unsafe class AsciiUtilityTests
{
private const int SizeOfVector128 = 128 / 8;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
+using System.Linq;
using System.Tests;
using Microsoft.DotNet.RemoteExecutor;
using Xunit;
public string Format(string format, object arg, IFormatProvider formatProvider) => "abc";
public object GetFormat(Type formatType) => this;
}
+
+ [Fact]
+ public static void AppendJoin_NullValues_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin('|', (object[])null));
+ AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin('|', (IEnumerable<object>)null));
+ AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin('|', (string[])null));
+ AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin("|", (object[])null));
+ AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin("|", (IEnumerable<object>)null));
+ AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin("|", (string[])null));
+ }
+
+ [Theory]
+ [InlineData(new object[0], "")]
+ [InlineData(new object[] { null }, "")]
+ [InlineData(new object[] { 10 }, "10")]
+ [InlineData(new object[] { null, null }, "|")]
+ [InlineData(new object[] { null, 20 }, "|20")]
+ [InlineData(new object[] { 10, null }, "10|")]
+ [InlineData(new object[] { 10, 20 }, "10|20")]
+ [InlineData(new object[] { null, null, null }, "||")]
+ [InlineData(new object[] { null, null, 30 }, "||30")]
+ [InlineData(new object[] { null, 20, null }, "|20|")]
+ [InlineData(new object[] { null, 20, 30 }, "|20|30")]
+ [InlineData(new object[] { 10, null, null }, "10||")]
+ [InlineData(new object[] { 10, null, 30 }, "10||30")]
+ [InlineData(new object[] { 10, 20, null }, "10|20|")]
+ [InlineData(new object[] { 10, 20, 30 }, "10|20|30")]
+ [InlineData(new object[] { "" }, "")]
+ [InlineData(new object[] { "", "" }, "|")]
+ public static void AppendJoin_TestValues(object[] values, string expected)
+ {
+ var stringValues = Array.ConvertAll(values, _ => _?.ToString());
+ var enumerable = values.Select(_ => _);
+
+ Assert.Equal(expected, new StringBuilder().AppendJoin('|', values).ToString());
+ Assert.Equal(expected, new StringBuilder().AppendJoin('|', enumerable).ToString());
+ Assert.Equal(expected, new StringBuilder().AppendJoin('|', stringValues).ToString());
+ Assert.Equal(expected, new StringBuilder().AppendJoin("|", values).ToString());
+ Assert.Equal(expected, new StringBuilder().AppendJoin("|", enumerable).ToString());
+ Assert.Equal(expected, new StringBuilder().AppendJoin("|", stringValues).ToString());
+ }
+
+ [Fact]
+ public static void AppendJoin_NullToStringValues()
+ {
+ AppendJoin_TestValues(new object[] { new NullToStringObject() }, "");
+ AppendJoin_TestValues(new object[] { new NullToStringObject(), new NullToStringObject() }, "|");
+ }
+
+ private sealed class NullToStringObject
+ {
+ public override string ToString() => null;
+ }
+
+ [Theory]
+ [InlineData(null, "123")]
+ [InlineData("", "123")]
+ [InlineData(" ", "1 2 3")]
+ [InlineData(", ", "1, 2, 3")]
+ public static void AppendJoin_TestStringSeparators(string separator, string expected)
+ {
+ Assert.Equal(expected, new StringBuilder().AppendJoin(separator, new object[] { 1, 2, 3 }).ToString());
+ Assert.Equal(expected, new StringBuilder().AppendJoin(separator, Enumerable.Range(1, 3)).ToString());
+ Assert.Equal(expected, new StringBuilder().AppendJoin(separator, new string[] { "1", "2", "3" }).ToString());
+ }
+
+
+ private static StringBuilder CreateBuilderWithNoSpareCapacity()
+ {
+ return new StringBuilder(0, 5).Append("Hello");
+ }
+
+ [Theory]
+ [InlineData(null, new object[] { null, null })]
+ [InlineData("", new object[] { "", "" })]
+ [InlineData(" ", new object[] { })]
+ [InlineData(", ", new object[] { "" })]
+ public static void AppendJoin_NoValues_NoSpareCapacity_DoesNotThrow(string separator, object[] values)
+ {
+ var stringValues = Array.ConvertAll(values, _ => _?.ToString());
+ var enumerable = values.Select(_ => _);
+
+ if (separator?.Length == 1)
+ {
+ CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], values);
+ CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], enumerable);
+ CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], stringValues);
+ }
+ CreateBuilderWithNoSpareCapacity().AppendJoin(separator, values);
+ CreateBuilderWithNoSpareCapacity().AppendJoin(separator, enumerable);
+ CreateBuilderWithNoSpareCapacity().AppendJoin(separator, stringValues);
+ }
+
+ [Theory]
+ [InlineData(null, new object[] { " " })]
+ [InlineData(" ", new object[] { " " })]
+ [InlineData(" ", new object[] { null, null })]
+ [InlineData(" ", new object[] { "", "" })]
+ public static void AppendJoin_NoSpareCapacity_ThrowsArgumentOutOfRangeException(string separator, object[] values)
+ {
+ var builder = new StringBuilder(0, 5);
+ builder.Append("Hello");
+
+ var stringValues = Array.ConvertAll(values, _ => _?.ToString());
+ var enumerable = values.Select(_ => _);
+
+ if (separator?.Length == 1)
+ {
+ AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], values));
+ AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], enumerable));
+ AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], stringValues));
+ }
+ AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, values));
+ AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, enumerable));
+ AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, stringValues));
+ }
+
+ [Theory]
+ [InlineData("Hello", new char[] { 'a' }, "Helloa")]
+ [InlineData("Hello", new char[] { 'b', 'c', 'd' }, "Hellobcd")]
+ [InlineData("Hello", new char[] { 'b', '\0', 'd' }, "Hellob\0d")]
+ [InlineData("", new char[] { 'e', 'f', 'g' }, "efg")]
+ [InlineData("Hello", new char[0], "Hello")]
+ public static void Append_CharSpan(string original, char[] value, string expected)
+ {
+ var builder = new StringBuilder(original);
+ builder.Append(new ReadOnlySpan<char>(value));
+ Assert.Equal(expected, builder.ToString());
+ }
+
+ [Theory]
+ [InlineData("Hello", new char[] { 'a' }, "Helloa")]
+ [InlineData("Hello", new char[] { 'b', 'c', 'd' }, "Hellobcd")]
+ [InlineData("Hello", new char[] { 'b', '\0', 'd' }, "Hellob\0d")]
+ [InlineData("", new char[] { 'e', 'f', 'g' }, "efg")]
+ [InlineData("Hello", new char[0], "Hello")]
+ public static void Append_CharMemory(string original, char[] value, string expected)
+ {
+ var builder = new StringBuilder(original);
+ builder.Append(value.AsMemory());
+ Assert.Equal(expected, builder.ToString());
+ }
+
+ [Theory]
+ [InlineData(1)]
+ [InlineData(10000)]
+ public static void Clear_AppendAndInsertBeforeClearManyTimes_CapacityStaysWithinRange(int times)
+ {
+ var builder = new StringBuilder();
+ var originalCapacity = builder.Capacity;
+ var s = new string(' ', 10);
+ int oldLength = 0;
+ for (int i = 0; i < times; i++)
+ {
+ builder.Append(s);
+ builder.Append(s);
+ builder.Append(s);
+ builder.Insert(0, s);
+ builder.Insert(0, s);
+ oldLength = builder.Length;
+
+ builder.Clear();
+ }
+ Assert.InRange(builder.Capacity, 1, oldLength * 1.2);
+ }
+
+ [Fact]
+ public static void Clear_InitialCapacityMuchLargerThanLength_CapacityReducedToInitialCapacity()
+ {
+ var builder = new StringBuilder(100);
+ var initialCapacity = builder.Capacity;
+ builder.Append(new string('a', 40));
+ builder.Insert(0, new string('a', 10));
+ builder.Insert(0, new string('a', 10));
+ builder.Insert(0, new string('a', 10));
+ var oldCapacity = builder.Capacity;
+ var oldLength = builder.Length;
+ builder.Clear();
+ Assert.NotEqual(oldCapacity, builder.Capacity);
+ Assert.Equal(initialCapacity, builder.Capacity);
+ Assert.NotInRange(builder.Capacity, 1, oldLength * 1.2);
+ Assert.InRange(builder.Capacity, 1, Math.Max(initialCapacity, oldLength * 1.2));
+ }
+
+ [Fact]
+ public static void Clear_StringBuilderHasTwoChunks_OneChunkIsEmpty_ClearReducesCapacity()
+ {
+ var sb = new StringBuilder(string.Empty);
+ int initialCapacity = sb.Capacity;
+ for (int i = 0; i < initialCapacity; i++)
+ {
+ sb.Append('a');
+ }
+ sb.Insert(0, 'a');
+ while (sb.Length > 1)
+ {
+ sb.Remove(1, 1);
+ }
+ int oldCapacity = sb.Capacity;
+ sb.Clear();
+ Assert.Equal(oldCapacity - 1, sb.Capacity);
+ Assert.Equal(initialCapacity, sb.Capacity);
+ }
+
+ [Theory]
+ [InlineData("Hello", 0, new char[] { '\0', '\0', '\0', '\0', '\0' }, 5, new char[] { 'H', 'e', 'l', 'l', 'o' })]
+ [InlineData("Hello", 0, new char[] { '\0', '\0', '\0', '\0' }, 4, new char[] { 'H', 'e', 'l', 'l' })]
+ [InlineData("Hello", 1, new char[] { '\0', '\0', '\0', '\0', '\0' }, 4, new char[] { 'e', 'l', 'l', 'o', '\0' })]
+ public static void CopyTo_CharSpan(string value, int sourceIndex, char[] destination, int count, char[] expected)
+ {
+ var builder = new StringBuilder(value);
+ builder.CopyTo(sourceIndex, new Span<char>(destination), count);
+ Assert.Equal(expected, destination);
+ }
+
+ [Fact]
+ public static void CopyTo_CharSpan_StringBuilderWithMultipleChunks()
+ {
+ StringBuilder builder = StringBuilderWithMultipleChunks();
+ char[] destination = new char[builder.Length];
+ builder.CopyTo(0, new Span<char>(destination), destination.Length);
+ Assert.Equal(s_chunkSplitSource.ToCharArray(), destination);
+ }
+
+ [Fact]
+ public static void CopyTo_CharSpan_Invalid()
+ {
+ var builder = new StringBuilder("Hello");
+
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("sourceIndex", () => builder.CopyTo(-1, new Span<char>(new char[10]), 0)); // Source index < 0
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("sourceIndex", () => builder.CopyTo(6, new Span<char>(new char[10]), 0)); // Source index > builder.Length
+
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => builder.CopyTo(0, new Span<char>(new char[10]), -1)); // Count < 0
+
+ AssertExtensions.Throws<ArgumentException>(null, () => builder.CopyTo(5, new Span<char>(new char[10]), 1)); // Source index + count > builder.Length
+ AssertExtensions.Throws<ArgumentException>(null, () => builder.CopyTo(4, new Span<char>(new char[10]), 2)); // Source index + count > builder.Length
+
+ AssertExtensions.Throws<ArgumentException>(null, () => builder.CopyTo(0, new Span<char>(new char[10]), 11)); // count > destinationArray.Length
+ }
+
+ [Theory]
+ [InlineData("Hello", 0, new char[] { '\0' }, "\0Hello")]
+ [InlineData("Hello", 3, new char[] { 'a', 'b', 'c' }, "Helabclo")]
+ [InlineData("Hello", 5, new char[] { 'd', 'e', 'f' }, "Hellodef")]
+ [InlineData("Hello", 0, new char[0], "Hello")]
+ public static void Insert_CharSpan(string original, int index, char[] value, string expected)
+ {
+ var builder = new StringBuilder(original);
+ builder.Insert(index, new ReadOnlySpan<char>(value));
+ Assert.Equal(expected, builder.ToString());
+ }
+
+ [Fact]
+ public static void Insert_CharSpan_Invalid()
+ {
+ var builder = new StringBuilder(0, 5);
+ builder.Append("Hello");
+
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => builder.Insert(-1, new ReadOnlySpan<char>(new char[0]))); // Index < 0
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => builder.Insert(builder.Length + 1, new ReadOnlySpan<char>(new char[0]))); // Index > builder.Length
+ AssertExtensions.Throws<ArgumentOutOfRangeException>("requiredLength", () => builder.Insert(builder.Length, new ReadOnlySpan<char>(new char[1]))); // New length > builder.MaxCapacity
+ }
+
+ public static IEnumerable<object[]> Append_StringBuilder_TestData()
+ {
+ string mediumString = new string('a', 30);
+ string largeString = new string('b', 1000);
+
+ var sb1 = new StringBuilder("Hello");
+ var sb2 = new StringBuilder("one");
+ var sb3 = new StringBuilder(20).Append(mediumString);
+
+ yield return new object[] { new StringBuilder("Hello"), sb1, "HelloHello" };
+ yield return new object[] { new StringBuilder("Hello"), sb2, "Helloone" };
+ yield return new object[] { new StringBuilder("Hello"), new StringBuilder(), "Hello" };
+
+ yield return new object[] { new StringBuilder("one"), sb3, "one" + mediumString };
+
+ yield return new object[] { new StringBuilder(20).Append(mediumString), sb3, mediumString + mediumString };
+ yield return new object[] { new StringBuilder(10).Append(mediumString), sb3, mediumString + mediumString };
+
+ yield return new object[] { new StringBuilder(20).Append(largeString), sb3, largeString + mediumString };
+ yield return new object[] { new StringBuilder(10).Append(largeString), sb3, largeString + mediumString };
+
+ yield return new object[] { new StringBuilder(10), sb3, mediumString };
+ yield return new object[] { new StringBuilder(30), sb3, mediumString };
+ yield return new object[] { new StringBuilder(10), new StringBuilder(20), string.Empty};
+
+ yield return new object[] { sb1, null, "Hello" };
+ yield return new object[] { sb1, sb1, "HelloHello" };
+ }
+
+ [Theory]
+ [MemberData(nameof(Append_StringBuilder_TestData))]
+ public static void Append_StringBuilder(StringBuilder s1, StringBuilder s2, string s)
+ {
+ Assert.Equal(s, s1.Append(s2).ToString());
+ }
+
+ public static IEnumerable<object[]> Append_StringBuilder_Substring_TestData()
+ {
+ string mediumString = new string('a', 30);
+ string largeString = new string('b', 1000);
+
+ var sb1 = new StringBuilder("Hello");
+ var sb2 = new StringBuilder("one");
+ var sb3 = new StringBuilder(20).Append(mediumString);
+
+ yield return new object[] { new StringBuilder("Hello"), sb1, 0, 5, "HelloHello" };
+ yield return new object[] { new StringBuilder("Hello"), sb1, 0, 0, "Hello" };
+ yield return new object[] { new StringBuilder("Hello"), sb1, 2, 3, "Hellollo" };
+ yield return new object[] { new StringBuilder("Hello"), sb1, 2, 2, "Helloll" };
+ yield return new object[] { new StringBuilder("Hello"), sb1, 2, 0, "Hello" };
+ yield return new object[] { new StringBuilder("Hello"), new StringBuilder(), 0, 0, "Hello" };
+ yield return new object[] { new StringBuilder("Hello"), null, 0, 0, "Hello" };
+ yield return new object[] { new StringBuilder(), new StringBuilder("Hello"), 2, 3, "llo" };
+ yield return new object[] { new StringBuilder("Hello"), sb2, 0, 3, "Helloone" };
+
+ yield return new object[] { new StringBuilder("one"), sb3, 5, 25, "one" + new string('a', 25) };
+ yield return new object[] { new StringBuilder("one"), sb3, 5, 20, "one" + new string('a', 20) };
+ yield return new object[] { new StringBuilder("one"), sb3, 10, 10, "one" + new string('a', 10) };
+
+ yield return new object[] { new StringBuilder(20).Append(mediumString), sb3, 20, 10, new string('a', 40) };
+ yield return new object[] { new StringBuilder(10).Append(mediumString), sb3, 10, 10, new string('a', 40) };
+
+ yield return new object[] { new StringBuilder(20).Append(largeString), new StringBuilder(20).Append(largeString), 100, 50, largeString + new string('b', 50) };
+ yield return new object[] { new StringBuilder(10).Append(mediumString), new StringBuilder(20).Append(largeString), 20, 10, mediumString + new string('b', 10) };
+ yield return new object[] { new StringBuilder(10).Append(mediumString), new StringBuilder(20).Append(largeString), 100, 50, mediumString + new string('b', 50) };
+
+ yield return new object[] { sb1, sb1, 2, 3, "Hellollo" };
+ yield return new object[] { sb2, sb2, 2, 0, "one" };
+ }
+
+ [Theory]
+ [MemberData(nameof(Append_StringBuilder_Substring_TestData))]
+ public static void Append_StringBuilder_Substring(StringBuilder s1, StringBuilder s2, int startIndex, int count, string s)
+ {
+ Assert.Equal(s, s1.Append(s2, startIndex, count).ToString());
+ }
+
+ [Fact]
+ public static void Append_StringBuilder_InvalidInput()
+ {
+ StringBuilder sb = new StringBuilder(5, 5).Append("Hello");
+
+ Assert.Throws<ArgumentOutOfRangeException>(() => sb.Append(sb, -1, 0));
+ Assert.Throws<ArgumentOutOfRangeException>(() => sb.Append(sb, 0, -1));
+ Assert.Throws<ArgumentOutOfRangeException>(() => sb.Append(sb, 4, 5));
+
+ Assert.Throws<ArgumentNullException>(() => sb.Append( (StringBuilder)null, 2, 2));
+ Assert.Throws<ArgumentNullException>(() => sb.Append((StringBuilder)null, 2, 3));
+ Assert.Throws<ArgumentOutOfRangeException>(() => new StringBuilder(3, 6).Append("Hello").Append(sb));
+ Assert.Throws<ArgumentOutOfRangeException>(() => new StringBuilder(3, 6).Append("Hello").Append("Hello"));
+
+ Assert.Throws<ArgumentOutOfRangeException>(() => sb.Append(sb));
+ }
+
+ public static IEnumerable<object[]> Equals_String_TestData()
+ {
+ string mediumString = new string('a', 30);
+ string largeString = new string('a', 1000);
+ string extraLargeString = new string('a', 41000); // 8000 is the maximum chunk size
+
+ var sb1 = new StringBuilder("Hello");
+ var sb2 = new StringBuilder(20).Append(mediumString);
+ var sb3 = new StringBuilder(20).Append(largeString);
+ var sb4 = new StringBuilder(20).Append(extraLargeString);
+
+ yield return new object[] { sb1, "Hello", true };
+ yield return new object[] { sb1, "Hel", false };
+ yield return new object[] { sb1, "Hellz", false };
+ yield return new object[] { sb1, "Helloz", false };
+ yield return new object[] { sb1, "", false };
+ yield return new object[] { new StringBuilder(), "", true };
+ yield return new object[] { new StringBuilder(), "Hello", false };
+ yield return new object[] { sb2, mediumString, true };
+ yield return new object[] { sb2, "H", false };
+ yield return new object[] { sb3, largeString, true };
+ yield return new object[] { sb3, "H", false };
+ yield return new object[] { sb3, new string('a', 999) + 'b', false };
+ yield return new object[] { sb4, extraLargeString, true };
+ yield return new object[] { sb4, "H", false };
+ }
+
+ [Theory]
+ [MemberData(nameof(Equals_String_TestData))]
+ public static void Equals(StringBuilder sb1, string value, bool expected)
+ {
+ Assert.Equal(expected, sb1.Equals(value.AsSpan()));
+ }
+
+ [Fact]
+ public static void ForEach()
+ {
+ // Test on a variety of lengths, at least up to the point of 9 8K chunks = 72K because this is where
+ // we start using a different technique for creating the ChunkEnumerator. 200 * 500 = 100K which hits this.
+ for (int i = 0; i < 200; i++)
+ {
+ StringBuilder inBuilder = new StringBuilder();
+ for (int j = 0; j < i; j++)
+ {
+ // Make some unique strings that are at least 500 bytes long.
+ inBuilder.Append(j);
+ inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz01_");
+ inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz0123_");
+ inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz012345_");
+ inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz012345678_");
+ inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz01234567890_");
+ }
+
+ // Copy the string out (not using StringBuilder).
+ string outStr = "";
+ foreach (ReadOnlyMemory<char> chunk in inBuilder.GetChunks())
+ outStr += new string(chunk.Span);
+
+ // The strings formed by concatenating the chunks should be the same as the value in the StringBuilder.
+ Assert.Equal(outStr, inBuilder.ToString());
+ }
+ }
+
+ [Fact]
+ public static void EqualsIgnoresCapacity()
+ {
+ var sb1 = new StringBuilder(5);
+ var sb2 = new StringBuilder(10);
+
+ Assert.True(sb1.Equals(sb2));
+
+ sb1.Append("12345");
+ sb2.Append("12345");
+
+ Assert.True(sb1.Equals(sb2));
+ }
+
+ [Fact]
+ public static void EqualsIgnoresMaxCapacity()
+ {
+ var sb1 = new StringBuilder(5, 5);
+ var sb2 = new StringBuilder(5, 10);
+
+ Assert.True(sb1.Equals(sb2));
+
+ sb1.Append("12345");
+ sb2.Append("12345");
+
+ Assert.True(sb1.Equals(sb2));
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using Xunit;
-
-namespace System.Text.Tests
-{
- public partial class StringBuilderTests
- {
- [Fact]
- public static void AppendJoin_NullValues_ThrowsArgumentNullException()
- {
- AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin('|', (object[])null));
- AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin('|', (IEnumerable<object>)null));
- AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin('|', (string[])null));
- AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin("|", (object[])null));
- AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin("|", (IEnumerable<object>)null));
- AssertExtensions.Throws<ArgumentNullException>("values", () => new StringBuilder().AppendJoin("|", (string[])null));
- }
-
- [Theory]
- [InlineData(new object[0], "")]
- [InlineData(new object[] { null }, "")]
- [InlineData(new object[] { 10 }, "10")]
- [InlineData(new object[] { null, null }, "|")]
- [InlineData(new object[] { null, 20 }, "|20")]
- [InlineData(new object[] { 10, null }, "10|")]
- [InlineData(new object[] { 10, 20 }, "10|20")]
- [InlineData(new object[] { null, null, null }, "||")]
- [InlineData(new object[] { null, null, 30 }, "||30")]
- [InlineData(new object[] { null, 20, null }, "|20|")]
- [InlineData(new object[] { null, 20, 30 }, "|20|30")]
- [InlineData(new object[] { 10, null, null }, "10||")]
- [InlineData(new object[] { 10, null, 30 }, "10||30")]
- [InlineData(new object[] { 10, 20, null }, "10|20|")]
- [InlineData(new object[] { 10, 20, 30 }, "10|20|30")]
- [InlineData(new object[] { "" }, "")]
- [InlineData(new object[] { "", "" }, "|")]
- public static void AppendJoin_TestValues(object[] values, string expected)
- {
- var stringValues = Array.ConvertAll(values, _ => _?.ToString());
- var enumerable = values.Select(_ => _);
-
- Assert.Equal(expected, new StringBuilder().AppendJoin('|', values).ToString());
- Assert.Equal(expected, new StringBuilder().AppendJoin('|', enumerable).ToString());
- Assert.Equal(expected, new StringBuilder().AppendJoin('|', stringValues).ToString());
- Assert.Equal(expected, new StringBuilder().AppendJoin("|", values).ToString());
- Assert.Equal(expected, new StringBuilder().AppendJoin("|", enumerable).ToString());
- Assert.Equal(expected, new StringBuilder().AppendJoin("|", stringValues).ToString());
- }
-
- [Fact]
- public static void AppendJoin_NullToStringValues()
- {
- AppendJoin_TestValues(new object[] { new NullToStringObject() }, "");
- AppendJoin_TestValues(new object[] { new NullToStringObject(), new NullToStringObject() }, "|");
- }
-
- private sealed class NullToStringObject
- {
- public override string ToString() => null;
- }
-
- [Theory]
- [InlineData(null, "123")]
- [InlineData("", "123")]
- [InlineData(" ", "1 2 3")]
- [InlineData(", ", "1, 2, 3")]
- public static void AppendJoin_TestStringSeparators(string separator, string expected)
- {
- Assert.Equal(expected, new StringBuilder().AppendJoin(separator, new object[] { 1, 2, 3 }).ToString());
- Assert.Equal(expected, new StringBuilder().AppendJoin(separator, Enumerable.Range(1, 3)).ToString());
- Assert.Equal(expected, new StringBuilder().AppendJoin(separator, new string[] { "1", "2", "3" }).ToString());
- }
-
-
- private static StringBuilder CreateBuilderWithNoSpareCapacity()
- {
- return new StringBuilder(0, 5).Append("Hello");
- }
-
- [Theory]
- [InlineData(null, new object[] { null, null })]
- [InlineData("", new object[] { "", "" })]
- [InlineData(" ", new object[] { })]
- [InlineData(", ", new object[] { "" })]
- public static void AppendJoin_NoValues_NoSpareCapacity_DoesNotThrow(string separator, object[] values)
- {
- var stringValues = Array.ConvertAll(values, _ => _?.ToString());
- var enumerable = values.Select(_ => _);
-
- if (separator?.Length == 1)
- {
- CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], values);
- CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], enumerable);
- CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], stringValues);
- }
- CreateBuilderWithNoSpareCapacity().AppendJoin(separator, values);
- CreateBuilderWithNoSpareCapacity().AppendJoin(separator, enumerable);
- CreateBuilderWithNoSpareCapacity().AppendJoin(separator, stringValues);
- }
-
- [Theory]
- [InlineData(null, new object[] { " " })]
- [InlineData(" ", new object[] { " " })]
- [InlineData(" ", new object[] { null, null })]
- [InlineData(" ", new object[] { "", "" })]
- public static void AppendJoin_NoSpareCapacity_ThrowsArgumentOutOfRangeException(string separator, object[] values)
- {
- var builder = new StringBuilder(0, 5);
- builder.Append("Hello");
-
- var stringValues = Array.ConvertAll(values, _ => _?.ToString());
- var enumerable = values.Select(_ => _);
-
- if (separator?.Length == 1)
- {
- AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], values));
- AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], enumerable));
- AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator[0], stringValues));
- }
- AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, values));
- AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, enumerable));
- AssertExtensions.Throws<ArgumentOutOfRangeException>(s_noCapacityParamName, () => CreateBuilderWithNoSpareCapacity().AppendJoin(separator, stringValues));
- }
-
- [Theory]
- [InlineData("Hello", new char[] { 'a' }, "Helloa")]
- [InlineData("Hello", new char[] { 'b', 'c', 'd' }, "Hellobcd")]
- [InlineData("Hello", new char[] { 'b', '\0', 'd' }, "Hellob\0d")]
- [InlineData("", new char[] { 'e', 'f', 'g' }, "efg")]
- [InlineData("Hello", new char[0], "Hello")]
- public static void Append_CharSpan(string original, char[] value, string expected)
- {
- var builder = new StringBuilder(original);
- builder.Append(new ReadOnlySpan<char>(value));
- Assert.Equal(expected, builder.ToString());
- }
-
- [Theory]
- [InlineData("Hello", new char[] { 'a' }, "Helloa")]
- [InlineData("Hello", new char[] { 'b', 'c', 'd' }, "Hellobcd")]
- [InlineData("Hello", new char[] { 'b', '\0', 'd' }, "Hellob\0d")]
- [InlineData("", new char[] { 'e', 'f', 'g' }, "efg")]
- [InlineData("Hello", new char[0], "Hello")]
- public static void Append_CharMemory(string original, char[] value, string expected)
- {
- var builder = new StringBuilder(original);
- builder.Append(value.AsMemory());
- Assert.Equal(expected, builder.ToString());
- }
-
- [Theory]
- [InlineData(1)]
- [InlineData(10000)]
- public static void Clear_AppendAndInsertBeforeClearManyTimes_CapacityStaysWithinRange(int times)
- {
- var builder = new StringBuilder();
- var originalCapacity = builder.Capacity;
- var s = new string(' ', 10);
- int oldLength = 0;
- for (int i = 0; i < times; i++)
- {
- builder.Append(s);
- builder.Append(s);
- builder.Append(s);
- builder.Insert(0, s);
- builder.Insert(0, s);
- oldLength = builder.Length;
-
- builder.Clear();
- }
- Assert.InRange(builder.Capacity, 1, oldLength * 1.2);
- }
-
- [Fact]
- public static void Clear_InitialCapacityMuchLargerThanLength_CapacityReducedToInitialCapacity()
- {
- var builder = new StringBuilder(100);
- var initialCapacity = builder.Capacity;
- builder.Append(new string('a', 40));
- builder.Insert(0, new string('a', 10));
- builder.Insert(0, new string('a', 10));
- builder.Insert(0, new string('a', 10));
- var oldCapacity = builder.Capacity;
- var oldLength = builder.Length;
- builder.Clear();
- Assert.NotEqual(oldCapacity, builder.Capacity);
- Assert.Equal(initialCapacity, builder.Capacity);
- Assert.NotInRange(builder.Capacity, 1, oldLength * 1.2);
- Assert.InRange(builder.Capacity, 1, Math.Max(initialCapacity, oldLength * 1.2));
- }
-
- [Fact]
- public static void Clear_StringBuilderHasTwoChunks_OneChunkIsEmpty_ClearReducesCapacity()
- {
- var sb = new StringBuilder(string.Empty);
- int initialCapacity = sb.Capacity;
- for (int i = 0; i < initialCapacity; i++)
- {
- sb.Append('a');
- }
- sb.Insert(0, 'a');
- while (sb.Length > 1)
- {
- sb.Remove(1, 1);
- }
- int oldCapacity = sb.Capacity;
- sb.Clear();
- Assert.Equal(oldCapacity - 1, sb.Capacity);
- Assert.Equal(initialCapacity, sb.Capacity);
- }
-
- [Theory]
- [InlineData("Hello", 0, new char[] { '\0', '\0', '\0', '\0', '\0' }, 5, new char[] { 'H', 'e', 'l', 'l', 'o' })]
- [InlineData("Hello", 0, new char[] { '\0', '\0', '\0', '\0' }, 4, new char[] { 'H', 'e', 'l', 'l' })]
- [InlineData("Hello", 1, new char[] { '\0', '\0', '\0', '\0', '\0' }, 4, new char[] { 'e', 'l', 'l', 'o', '\0' })]
- public static void CopyTo_CharSpan(string value, int sourceIndex, char[] destination, int count, char[] expected)
- {
- var builder = new StringBuilder(value);
- builder.CopyTo(sourceIndex, new Span<char>(destination), count);
- Assert.Equal(expected, destination);
- }
-
- [Fact]
- public static void CopyTo_CharSpan_StringBuilderWithMultipleChunks()
- {
- StringBuilder builder = StringBuilderWithMultipleChunks();
- char[] destination = new char[builder.Length];
- builder.CopyTo(0, new Span<char>(destination), destination.Length);
- Assert.Equal(s_chunkSplitSource.ToCharArray(), destination);
- }
-
- [Fact]
- public static void CopyTo_CharSpan_Invalid()
- {
- var builder = new StringBuilder("Hello");
-
- AssertExtensions.Throws<ArgumentOutOfRangeException>("sourceIndex", () => builder.CopyTo(-1, new Span<char>(new char[10]), 0)); // Source index < 0
- AssertExtensions.Throws<ArgumentOutOfRangeException>("sourceIndex", () => builder.CopyTo(6, new Span<char>(new char[10]), 0)); // Source index > builder.Length
-
- AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => builder.CopyTo(0, new Span<char>(new char[10]), -1)); // Count < 0
-
- AssertExtensions.Throws<ArgumentException>(null, () => builder.CopyTo(5, new Span<char>(new char[10]), 1)); // Source index + count > builder.Length
- AssertExtensions.Throws<ArgumentException>(null, () => builder.CopyTo(4, new Span<char>(new char[10]), 2)); // Source index + count > builder.Length
-
- AssertExtensions.Throws<ArgumentException>(null, () => builder.CopyTo(0, new Span<char>(new char[10]), 11)); // count > destinationArray.Length
- }
-
- [Theory]
- [InlineData("Hello", 0, new char[] { '\0' }, "\0Hello")]
- [InlineData("Hello", 3, new char[] { 'a', 'b', 'c' }, "Helabclo")]
- [InlineData("Hello", 5, new char[] { 'd', 'e', 'f' }, "Hellodef")]
- [InlineData("Hello", 0, new char[0], "Hello")]
- public static void Insert_CharSpan(string original, int index, char[] value, string expected)
- {
- var builder = new StringBuilder(original);
- builder.Insert(index, new ReadOnlySpan<char>(value));
- Assert.Equal(expected, builder.ToString());
- }
-
- [Fact]
- public static void Insert_CharSpan_Invalid()
- {
- var builder = new StringBuilder(0, 5);
- builder.Append("Hello");
-
- AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => builder.Insert(-1, new ReadOnlySpan<char>(new char[0]))); // Index < 0
- AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => builder.Insert(builder.Length + 1, new ReadOnlySpan<char>(new char[0]))); // Index > builder.Length
- AssertExtensions.Throws<ArgumentOutOfRangeException>("requiredLength", () => builder.Insert(builder.Length, new ReadOnlySpan<char>(new char[1]))); // New length > builder.MaxCapacity
- }
-
- public static IEnumerable<object[]> Append_StringBuilder_TestData()
- {
- string mediumString = new string('a', 30);
- string largeString = new string('b', 1000);
-
- var sb1 = new StringBuilder("Hello");
- var sb2 = new StringBuilder("one");
- var sb3 = new StringBuilder(20).Append(mediumString);
-
- yield return new object[] { new StringBuilder("Hello"), sb1, "HelloHello" };
- yield return new object[] { new StringBuilder("Hello"), sb2, "Helloone" };
- yield return new object[] { new StringBuilder("Hello"), new StringBuilder(), "Hello" };
-
- yield return new object[] { new StringBuilder("one"), sb3, "one" + mediumString };
-
- yield return new object[] { new StringBuilder(20).Append(mediumString), sb3, mediumString + mediumString };
- yield return new object[] { new StringBuilder(10).Append(mediumString), sb3, mediumString + mediumString };
-
- yield return new object[] { new StringBuilder(20).Append(largeString), sb3, largeString + mediumString };
- yield return new object[] { new StringBuilder(10).Append(largeString), sb3, largeString + mediumString };
-
- yield return new object[] { new StringBuilder(10), sb3, mediumString };
- yield return new object[] { new StringBuilder(30), sb3, mediumString };
- yield return new object[] { new StringBuilder(10), new StringBuilder(20), string.Empty};
-
- yield return new object[] { sb1, null, "Hello" };
- yield return new object[] { sb1, sb1, "HelloHello" };
- }
-
- [Theory]
- [MemberData(nameof(Append_StringBuilder_TestData))]
- public static void Append_StringBuilder(StringBuilder s1, StringBuilder s2, string s)
- {
- Assert.Equal(s, s1.Append(s2).ToString());
- }
-
- public static IEnumerable<object[]> Append_StringBuilder_Substring_TestData()
- {
- string mediumString = new string('a', 30);
- string largeString = new string('b', 1000);
-
- var sb1 = new StringBuilder("Hello");
- var sb2 = new StringBuilder("one");
- var sb3 = new StringBuilder(20).Append(mediumString);
-
- yield return new object[] { new StringBuilder("Hello"), sb1, 0, 5, "HelloHello" };
- yield return new object[] { new StringBuilder("Hello"), sb1, 0, 0, "Hello" };
- yield return new object[] { new StringBuilder("Hello"), sb1, 2, 3, "Hellollo" };
- yield return new object[] { new StringBuilder("Hello"), sb1, 2, 2, "Helloll" };
- yield return new object[] { new StringBuilder("Hello"), sb1, 2, 0, "Hello" };
- yield return new object[] { new StringBuilder("Hello"), new StringBuilder(), 0, 0, "Hello" };
- yield return new object[] { new StringBuilder("Hello"), null, 0, 0, "Hello" };
- yield return new object[] { new StringBuilder(), new StringBuilder("Hello"), 2, 3, "llo" };
- yield return new object[] { new StringBuilder("Hello"), sb2, 0, 3, "Helloone" };
-
- yield return new object[] { new StringBuilder("one"), sb3, 5, 25, "one" + new string('a', 25) };
- yield return new object[] { new StringBuilder("one"), sb3, 5, 20, "one" + new string('a', 20) };
- yield return new object[] { new StringBuilder("one"), sb3, 10, 10, "one" + new string('a', 10) };
-
- yield return new object[] { new StringBuilder(20).Append(mediumString), sb3, 20, 10, new string('a', 40) };
- yield return new object[] { new StringBuilder(10).Append(mediumString), sb3, 10, 10, new string('a', 40) };
-
- yield return new object[] { new StringBuilder(20).Append(largeString), new StringBuilder(20).Append(largeString), 100, 50, largeString + new string('b', 50) };
- yield return new object[] { new StringBuilder(10).Append(mediumString), new StringBuilder(20).Append(largeString), 20, 10, mediumString + new string('b', 10) };
- yield return new object[] { new StringBuilder(10).Append(mediumString), new StringBuilder(20).Append(largeString), 100, 50, mediumString + new string('b', 50) };
-
- yield return new object[] { sb1, sb1, 2, 3, "Hellollo" };
- yield return new object[] { sb2, sb2, 2, 0, "one" };
- }
-
- [Theory]
- [MemberData(nameof(Append_StringBuilder_Substring_TestData))]
- public static void Append_StringBuilder_Substring(StringBuilder s1, StringBuilder s2, int startIndex, int count, string s)
- {
- Assert.Equal(s, s1.Append(s2, startIndex, count).ToString());
- }
-
- [Fact]
- public static void Append_StringBuilder_InvalidInput()
- {
- StringBuilder sb = new StringBuilder(5, 5).Append("Hello");
-
- Assert.Throws<ArgumentOutOfRangeException>(() => sb.Append(sb, -1, 0));
- Assert.Throws<ArgumentOutOfRangeException>(() => sb.Append(sb, 0, -1));
- Assert.Throws<ArgumentOutOfRangeException>(() => sb.Append(sb, 4, 5));
-
- Assert.Throws<ArgumentNullException>(() => sb.Append( (StringBuilder)null, 2, 2));
- Assert.Throws<ArgumentNullException>(() => sb.Append((StringBuilder)null, 2, 3));
- Assert.Throws<ArgumentOutOfRangeException>(() => new StringBuilder(3, 6).Append("Hello").Append(sb));
- Assert.Throws<ArgumentOutOfRangeException>(() => new StringBuilder(3, 6).Append("Hello").Append("Hello"));
-
- Assert.Throws<ArgumentOutOfRangeException>(() => sb.Append(sb));
- }
-
- public static IEnumerable<object[]> Equals_String_TestData()
- {
- string mediumString = new string('a', 30);
- string largeString = new string('a', 1000);
- string extraLargeString = new string('a', 41000); // 8000 is the maximum chunk size
-
- var sb1 = new StringBuilder("Hello");
- var sb2 = new StringBuilder(20).Append(mediumString);
- var sb3 = new StringBuilder(20).Append(largeString);
- var sb4 = new StringBuilder(20).Append(extraLargeString);
-
- yield return new object[] { sb1, "Hello", true };
- yield return new object[] { sb1, "Hel", false };
- yield return new object[] { sb1, "Hellz", false };
- yield return new object[] { sb1, "Helloz", false };
- yield return new object[] { sb1, "", false };
- yield return new object[] { new StringBuilder(), "", true };
- yield return new object[] { new StringBuilder(), "Hello", false };
- yield return new object[] { sb2, mediumString, true };
- yield return new object[] { sb2, "H", false };
- yield return new object[] { sb3, largeString, true };
- yield return new object[] { sb3, "H", false };
- yield return new object[] { sb3, new string('a', 999) + 'b', false };
- yield return new object[] { sb4, extraLargeString, true };
- yield return new object[] { sb4, "H", false };
- }
-
- [Theory]
- [MemberData(nameof(Equals_String_TestData))]
- public static void Equals(StringBuilder sb1, string value, bool expected)
- {
- Assert.Equal(expected, sb1.Equals(value.AsSpan()));
- }
-
- [Fact]
- public static void ForEach()
- {
- // Test on a variety of lengths, at least up to the point of 9 8K chunks = 72K because this is where
- // we start using a different technique for creating the ChunkEnumerator. 200 * 500 = 100K which hits this.
- for (int i = 0; i < 200; i++)
- {
- StringBuilder inBuilder = new StringBuilder();
- for (int j = 0; j < i; j++)
- {
- // Make some unique strings that are at least 500 bytes long.
- inBuilder.Append(j);
- inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz01_");
- inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz0123_");
- inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz012345_");
- inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz012345678_");
- inBuilder.Append("_abcdefghijklmnopqrstuvwxyz01234567890__Abcdefghijklmnopqrstuvwxyz01234567890__ABcdefghijklmnopqrstuvwxyz01234567890_");
- }
-
- // Copy the string out (not using StringBuilder).
- string outStr = "";
- foreach (ReadOnlyMemory<char> chunk in inBuilder.GetChunks())
- outStr += new string(chunk.Span);
-
- // The strings formed by concatenating the chunks should be the same as the value in the StringBuilder.
- Assert.Equal(outStr, inBuilder.ToString());
- }
- }
-
- [Fact]
- public static void EqualsIgnoresCapacity()
- {
- var sb1 = new StringBuilder(5);
- var sb2 = new StringBuilder(10);
-
- Assert.True(sb1.Equals(sb2));
-
- sb1.Append("12345");
- sb2.Append("12345");
-
- Assert.True(sb1.Equals(sb2));
- }
-
- [Fact]
- public static void EqualsIgnoresMaxCapacity()
- {
- var sb1 = new StringBuilder(5, 5);
- var sb2 = new StringBuilder(5, 10);
-
- Assert.True(sb1.Equals(sb2));
-
- sb1.Append("12345");
- sb2.Append("12345");
-
- Assert.True(sb1.Equals(sb2));
- }
- }
-}
namespace System.Text.Unicode.Tests
{
- public partial class Utf16UtilityTests
+ public class Utf16UtilityTests
{
private unsafe delegate char* GetPointerToFirstInvalidCharDel(char* pInputBuffer, int inputLength, out long utf8CodeUnitCountAdjustment, out int scalarCountAdjustment);
private static readonly Lazy<GetPointerToFirstInvalidCharDel> _getPointerToFirstInvalidCharFn = CreateGetPointerToFirstInvalidCharFn();
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Buffers;
-using System.Linq;
-using Xunit;
-
-namespace System.Text.Unicode.Tests
-{
- public partial class Utf8Tests
- {
- [Theory]
- [InlineData("", "")] // empty string is OK
- [InlineData(X_UTF16, X_UTF8)]
- [InlineData(E_ACUTE_UTF16, E_ACUTE_UTF8)]
- [InlineData(EURO_SYMBOL_UTF16, EURO_SYMBOL_UTF8)]
- public void ToBytes_WithSmallValidBuffers(string utf16Input, string expectedUtf8TranscodingHex)
- {
- // These test cases are for the "slow processing" code path at the end of TranscodeToUtf8,
- // so inputs should be less than 2 chars.
-
- Assert.InRange(utf16Input.Length, 0, 1);
-
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: expectedUtf8TranscodingHex.Length / 2,
- replaceInvalidSequences: false,
- isFinalChunk: false,
- expectedOperationStatus: OperationStatus.Done,
- expectedNumCharsRead: utf16Input.Length,
- expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
- }
-
- [Theory]
- [InlineData("AB")] // 2 ASCII chars, hits fast inner loop
- [InlineData("ABCD")] // 4 ASCII chars, hits fast inner loop
- [InlineData("ABCDEF")] // 6 ASCII chars, hits fast inner loop
- [InlineData("ABCDEFGH")] // 8 ASCII chars, hits fast inner loop
- [InlineData("ABCDEFGHIJ")] // 10 ASCII chars, hits fast inner loop
- [InlineData("ABCDEF" + E_ACUTE_UTF16 + "HIJ")] // interrupts inner loop due to non-ASCII char in first char of first DWORD
- [InlineData("ABCDEFG" + EURO_SYMBOL_UTF16 + "IJ")] // interrupts inner loop due to non-ASCII char in second char of first DWORD
- [InlineData("ABCDEFGH" + E_ACUTE_UTF16 + "J")] // interrupts inner loop due to non-ASCII char in first char of second DWORD
- [InlineData("ABCDEFGHI" + EURO_SYMBOL_UTF16)] // interrupts inner loop due to non-ASCII char in second char of second DWORD
- [InlineData(X_UTF16 + E_ACUTE_UTF16)] // drains first ASCII char then falls down to slow path
- [InlineData(X_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16)] // drains first ASCII char then consumes 2x 2-byte sequences at once
- [InlineData(E_ACUTE_UTF16 + X_UTF16)] // no first ASCII char to drain, consumes 2-byte seq followed by ASCII char
- [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16)] // stay within 2x 2-byte sequence processing loop
- [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + X_UTF16)] // break out of 2x 2-byte seq loop due to ASCII data in second char of DWORD
- [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + X_UTF16 + X_UTF16)] // break out of 2x 2-byte seq loop due to ASCII data in first char of DWORD
- [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + EURO_SYMBOL_UTF16)] // break out of 2x 2-byte seq loop due to 3-byte data
- [InlineData(E_ACUTE_UTF16 + EURO_SYMBOL_UTF16)] // 2-byte logic sees next char isn't ASCII, cannot read full DWORD from remaining input buffer, falls down to slow drain loop
- [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + X_UTF16)] // 2x 3-byte logic can't read a full DWORD from next part of buffer, falls down to slow drain loop
- [InlineData(EURO_SYMBOL_UTF16 + X_UTF16)] // 3-byte processing loop consumes trailing ASCII char, but can't read next DWORD, falls down to slow drain loop
- [InlineData(EURO_SYMBOL_UTF16 + X_UTF16 + X_UTF16)] // 3-byte processing loop consumes trailing ASCII char, but can't read next DWORD, falls down to slow drain loop
- [InlineData(EURO_SYMBOL_UTF16 + E_ACUTE_UTF16)] // 3-byte processing loop can't consume next ASCII char, can't read DWORD, falls down to slow drain loop
- [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // stay within 2x 3-byte sequence processing loop
- [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + X_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // consume stray ASCII char at beginning of DWORD after 2x 3-byte sequence
- [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + X_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // consume stray ASCII char at end of DWORD after 2x 3-byte sequence
- [InlineData(EURO_SYMBOL_UTF16 + E_ACUTE_UTF16 + X_UTF16)] // consume 2-byte sequence as second char in DWORD which begins with 3-byte encoded char
- [InlineData(EURO_SYMBOL_UTF16 + GRINNING_FACE_UTF16)] // 3-byte sequence followed by 4-byte sequence
- [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + GRINNING_FACE_UTF16)] // 2x 3-byte sequence followed by 4-byte sequence
- [InlineData(GRINNING_FACE_UTF16)] // single 4-byte surrogate char pair
- [InlineData(GRINNING_FACE_UTF16 + EURO_SYMBOL_UTF16)] // 4-byte surrogate char pair, cannot read next DWORD, falls down to slow drain loop
- public void ToBytes_WithLargeValidBuffers(string utf16Input)
- {
- // These test cases are for the "fast processing" code which is the main loop of TranscodeToUtf8,
- // so inputs should be at least 2 chars.
-
- Assert.True(utf16Input.Length >= 2);
-
- // We're going to run the tests with destination buffer lengths ranging from 0 all the way
- // to buffers large enough to hold the full output. This allows us to test logic that
- // detects whether we're about to overrun our destination buffer and instead returns DestinationTooSmall.
-
- Rune[] enumeratedScalars = utf16Input.EnumerateRunes().ToArray();
-
- // 0-length buffer test
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: 0,
- replaceInvalidSequences: false,
- isFinalChunk: false,
- expectedOperationStatus: OperationStatus.DestinationTooSmall,
- expectedNumCharsRead: 0,
- expectedUtf8Transcoding: ReadOnlySpan<byte>.Empty);
-
- int expectedNumCharsConsumed = 0;
- byte[] concatenatedUtf8 = Array.Empty<byte>();
-
- for (int i = 0; i < enumeratedScalars.Length; i++)
- {
- Rune thisScalar = enumeratedScalars[i];
-
- // provide partial destination buffers all the way up to (but not including) enough to hold the next full scalar encoding
- for (int j = 1; j < thisScalar.Utf8SequenceLength; j++)
- {
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: concatenatedUtf8.Length + j,
- replaceInvalidSequences: false,
- isFinalChunk: false,
- expectedOperationStatus: OperationStatus.DestinationTooSmall,
- expectedNumCharsRead: expectedNumCharsConsumed,
- expectedUtf8Transcoding: concatenatedUtf8);
- }
-
- // now provide a destination buffer large enough to hold the next full scalar encoding
-
- expectedNumCharsConsumed += thisScalar.Utf16SequenceLength;
- concatenatedUtf8 = concatenatedUtf8.Concat(ToUtf8(thisScalar)).ToArray();
-
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: concatenatedUtf8.Length,
- replaceInvalidSequences: false,
- isFinalChunk: false,
- expectedOperationStatus: (i == enumeratedScalars.Length - 1) ? OperationStatus.Done : OperationStatus.DestinationTooSmall,
- expectedNumCharsRead: expectedNumCharsConsumed,
- expectedUtf8Transcoding: concatenatedUtf8);
- }
-
- // now throw lots of ASCII data at the beginning so that we exercise the vectorized code paths
-
- utf16Input = new string('x', 64) + utf16Input;
- concatenatedUtf8 = utf16Input.EnumerateRunes().SelectMany(ToUtf8).ToArray();
-
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: concatenatedUtf8.Length,
- replaceInvalidSequences: false,
- isFinalChunk: true,
- expectedOperationStatus: OperationStatus.Done,
- expectedNumCharsRead: utf16Input.Length,
- expectedUtf8Transcoding: concatenatedUtf8);
-
- // now throw some non-ASCII data at the beginning so that we *don't* exercise the vectorized code paths
-
- utf16Input = WOMAN_CARTWHEELING_MEDSKIN_UTF16 + utf16Input[64..];
- concatenatedUtf8 = utf16Input.EnumerateRunes().SelectMany(ToUtf8).ToArray();
-
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: concatenatedUtf8.Length,
- replaceInvalidSequences: false,
- isFinalChunk: true,
- expectedOperationStatus: OperationStatus.Done,
- expectedNumCharsRead: utf16Input.Length,
- expectedUtf8Transcoding: concatenatedUtf8);
- }
-
- [Theory]
- [InlineData('\uD800', OperationStatus.NeedMoreData)] // standalone high surrogate
- [InlineData('\uDFFF', OperationStatus.InvalidData)] // standalone low surrogate
- public void ToBytes_WithOnlyStandaloneSurrogates(char charValue, OperationStatus expectedOperationStatus)
- {
- ToBytes_Test_Core(
- utf16Input: new[] { charValue },
- destinationSize: 0,
- replaceInvalidSequences: false,
- isFinalChunk: false,
- expectedOperationStatus: expectedOperationStatus,
- expectedNumCharsRead: 0,
- expectedUtf8Transcoding: Span<byte>.Empty);
- }
-
- [Theory]
- [InlineData("<LOW><HIGH>", 0, "")] // swapped surrogate pair characters
- [InlineData("A<LOW><HIGH>", 1, "41")] // consume standalone ASCII char, then swapped surrogate pair characters
- [InlineData("A<HIGH>B", 1, "41")] // consume standalone ASCII char, then standalone high surrogate char
- [InlineData("A<LOW>B", 1, "41")] // consume standalone ASCII char, then standalone low surrogate char
- [InlineData("AB<HIGH><HIGH>", 2, "4142")] // consume two ASCII chars, then standalone high surrogate char
- [InlineData("AB<LOW><LOW>", 2, "4142")] // consume two ASCII chars, then standalone low surrogate char
- public void ToBytes_WithInvalidSurrogates(string utf16Input, int expectedNumCharsConsumed, string expectedUtf8TranscodingHex)
- {
- // xUnit can't handle ill-formed strings in [InlineData], so we replace here.
-
- utf16Input = utf16Input.Replace("<HIGH>", "\uD800").Replace("<LOW>", "\uDFFF");
-
- // These test cases are for the "fast processing" code which is the main loop of TranscodeToUtf8,
- // so inputs should be at least 2 chars.
-
- Assert.True(utf16Input.Length >= 2);
-
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: expectedUtf8TranscodingHex.Length / 2,
- replaceInvalidSequences: false,
- isFinalChunk: false,
- expectedOperationStatus: OperationStatus.InvalidData,
- expectedNumCharsRead: expectedNumCharsConsumed,
- expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
-
- // Now try the tests again with a larger buffer.
- // This ensures that running out of destination space wasn't the reason we failed.
-
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: (expectedUtf8TranscodingHex.Length) / 2 + 16,
- replaceInvalidSequences: false,
- isFinalChunk: false,
- expectedOperationStatus: OperationStatus.InvalidData,
- expectedNumCharsRead: expectedNumCharsConsumed,
- expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
- }
-
- [Theory]
- [InlineData("<LOW><HIGH>", REPLACEMENT_CHAR_UTF8)] // standalone low surr. and incomplete high surr.
- [InlineData("<HIGH><HIGH>", REPLACEMENT_CHAR_UTF8)] // standalone high surr. and incomplete high surr.
- [InlineData("<LOW><LOW>", REPLACEMENT_CHAR_UTF8 + REPLACEMENT_CHAR_UTF8)] // standalone low surr. and incomplete low surr.
- [InlineData("A<LOW>B<LOW>C<HIGH>D", "41" + REPLACEMENT_CHAR_UTF8 + "42" + REPLACEMENT_CHAR_UTF8 + "43" + REPLACEMENT_CHAR_UTF8 + "44")] // standalone low, low, high surrounded by other data
- public void ToBytes_WithReplacements(string utf16Input, string expectedUtf8TranscodingHex)
- {
- // xUnit can't handle ill-formed strings in [InlineData], so we replace here.
-
- utf16Input = utf16Input.Replace("<HIGH>", "\uD800").Replace("<LOW>", "\uDFFF");
-
- bool isFinalCharHighSurrogate = char.IsHighSurrogate(utf16Input.Last());
-
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: expectedUtf8TranscodingHex.Length / 2,
- replaceInvalidSequences: true,
- isFinalChunk: false,
- expectedOperationStatus: (isFinalCharHighSurrogate) ? OperationStatus.NeedMoreData : OperationStatus.Done,
- expectedNumCharsRead: (isFinalCharHighSurrogate) ? (utf16Input.Length - 1) : utf16Input.Length,
- expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
-
- if (isFinalCharHighSurrogate)
- {
- // Also test with isFinalChunk = true
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: expectedUtf8TranscodingHex.Length / 2 + Rune.ReplacementChar.Utf8SequenceLength /* for replacement char */,
- replaceInvalidSequences: true,
- isFinalChunk: true,
- expectedOperationStatus: OperationStatus.Done,
- expectedNumCharsRead: utf16Input.Length,
- expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex + REPLACEMENT_CHAR_UTF8));
- }
- }
-
- [Theory]
- [InlineData(E_ACUTE_UTF16 + "<LOW>", true, 1, OperationStatus.DestinationTooSmall, E_ACUTE_UTF8)] // not enough output buffer to hold U+FFFD
- [InlineData(E_ACUTE_UTF16 + "<LOW>", true, 2, OperationStatus.Done, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8)] // replace standalone low surr. at end
- [InlineData(E_ACUTE_UTF16 + "<HIGH>", true, 1, OperationStatus.DestinationTooSmall, E_ACUTE_UTF8)] // not enough output buffer to hold U+FFFD
- [InlineData(E_ACUTE_UTF16 + "<HIGH>", true, 2, OperationStatus.Done, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8)] // replace standalone high surr. at end
- [InlineData(E_ACUTE_UTF16 + "<HIGH>", false, 1, OperationStatus.NeedMoreData, E_ACUTE_UTF8)] // don't replace standalone high surr. at end
- [InlineData(E_ACUTE_UTF16 + "<HIGH>" + X_UTF16, true, 2, OperationStatus.DestinationTooSmall, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8)] // not enough output buffer to hold 'X'
- [InlineData(E_ACUTE_UTF16 + "<HIGH>" + X_UTF16, false, 2, OperationStatus.DestinationTooSmall, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8)] // not enough output buffer to hold 'X'
- [InlineData(E_ACUTE_UTF16 + "<HIGH>" + X_UTF16, true, 3, OperationStatus.Done, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8 + X_UTF8)] // replacement followed by 'X'
- [InlineData(E_ACUTE_UTF16 + "<HIGH>" + X_UTF16, false, 3, OperationStatus.Done, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8 + X_UTF8)] // replacement followed by 'X'
- public void ToBytes_WithReplacements_AndCustomBufferSizes(string utf16Input, bool isFinalChunk, int expectedNumCharsConsumed, OperationStatus expectedOperationStatus, string expectedUtf8TranscodingHex)
- {
- // xUnit can't handle ill-formed strings in [InlineData], so we replace here.
-
- utf16Input = utf16Input.Replace("<HIGH>", "\uD800").Replace("<LOW>", "\uDFFF");
-
- ToBytes_Test_Core(
- utf16Input: utf16Input,
- destinationSize: expectedUtf8TranscodingHex.Length / 2,
- replaceInvalidSequences: true,
- isFinalChunk: isFinalChunk,
- expectedOperationStatus: expectedOperationStatus,
- expectedNumCharsRead: expectedNumCharsConsumed,
- expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
- }
-
- [Fact]
- public void ToBytes_AllPossibleScalarValues()
- {
- ToBytes_Test_Core(
- utf16Input: s_allScalarsAsUtf16.Span,
- destinationSize: s_allScalarsAsUtf8.Length,
- replaceInvalidSequences: false,
- isFinalChunk: false,
- expectedOperationStatus: OperationStatus.Done,
- expectedNumCharsRead: s_allScalarsAsUtf16.Length,
- expectedUtf8Transcoding: s_allScalarsAsUtf8.Span);
- }
-
- private static void ToBytes_Test_Core(ReadOnlySpan<char> utf16Input, int destinationSize, bool replaceInvalidSequences, bool isFinalChunk, OperationStatus expectedOperationStatus, int expectedNumCharsRead, ReadOnlySpan<byte> expectedUtf8Transcoding)
- {
- // Arrange
-
- using (BoundedMemory<char> boundedSource = BoundedMemory.AllocateFromExistingData(utf16Input))
- using (BoundedMemory<byte> boundedDestination = BoundedMemory.Allocate<byte>(destinationSize))
- {
- boundedSource.MakeReadonly();
-
- // Act
-
- OperationStatus actualOperationStatus = Utf8.FromUtf16(boundedSource.Span, boundedDestination.Span, out int actualNumCharsRead, out int actualNumBytesWritten, replaceInvalidSequences, isFinalChunk);
-
- // Assert
-
- Assert.Equal(expectedOperationStatus, actualOperationStatus);
- Assert.Equal(expectedNumCharsRead, actualNumCharsRead);
- Assert.Equal(expectedUtf8Transcoding.Length, actualNumBytesWritten);
- Assert.Equal(expectedUtf8Transcoding.ToArray(), boundedDestination.Span.Slice(0, actualNumBytesWritten).ToArray());
- }
- }
- }
-}
// See the LICENSE file in the project root for more information.
using System.Buffers;
+using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
+using System.Text.RegularExpressions;
using Xunit;
namespace System.Text.Unicode.Tests
{
- public partial class Utf8Tests
+ public class Utf8Tests
{
+ private const string X_UTF8 = "58"; // U+0058 LATIN CAPITAL LETTER X, 1 byte
+ private const string X_UTF16 = "X";
+
+ private const string Y_UTF8 = "59"; // U+0058 LATIN CAPITAL LETTER Y, 1 byte
+ private const string Y_UTF16 = "Y";
+
+ private const string Z_UTF8 = "5A"; // U+0058 LATIN CAPITAL LETTER Z, 1 byte
+ private const string Z_UTF16 = "Z";
+
+ private const string E_ACUTE_UTF8 = "C3A9"; // U+00E9 LATIN SMALL LETTER E WITH ACUTE, 2 bytes
+ private const string E_ACUTE_UTF16 = "\u00E9";
+
+ private const string EURO_SYMBOL_UTF8 = "E282AC"; // U+20AC EURO SIGN, 3 bytes
+ private const string EURO_SYMBOL_UTF16 = "\u20AC";
+
+ private const string REPLACEMENT_CHAR_UTF8 = "EFBFBD"; // U+FFFD REPLACEMENT CHAR, 3 bytes
+ private const string REPLACEMENT_CHAR_UTF16 = "\uFFFD";
+
+ private const string GRINNING_FACE_UTF8 = "F09F9880"; // U+1F600 GRINNING FACE, 4 bytes
+ private const string GRINNING_FACE_UTF16 = "\U0001F600";
+
+ private const string WOMAN_CARTWHEELING_MEDSKIN_UTF16 = "\U0001F938\U0001F3FD\u200D\u2640\uFE0F"; // U+1F938 U+1F3FD U+200D U+2640 U+FE0F WOMAN CARTWHEELING: MEDIUM SKIN TONE
+
+ // All valid scalars [ U+0000 .. U+D7FF ] and [ U+E000 .. U+10FFFF ].
+ private static readonly IEnumerable<Rune> s_allValidScalars = Enumerable.Range(0x0000, 0xD800).Concat(Enumerable.Range(0xE000, 0x110000 - 0xE000)).Select(value => new Rune(value));
+
+ private static readonly ReadOnlyMemory<char> s_allScalarsAsUtf16;
+ private static readonly ReadOnlyMemory<byte> s_allScalarsAsUtf8;
+
+ static Utf8Tests()
+ {
+ List<char> allScalarsAsUtf16 = new List<char>();
+ List<byte> allScalarsAsUtf8 = new List<byte>();
+
+ foreach (Rune rune in s_allValidScalars)
+ {
+ allScalarsAsUtf16.AddRange(ToUtf16(rune));
+ allScalarsAsUtf8.AddRange(ToUtf8(rune));
+ }
+
+ s_allScalarsAsUtf16 = allScalarsAsUtf16.ToArray().AsMemory();
+ s_allScalarsAsUtf8 = allScalarsAsUtf8.ToArray().AsMemory();
+ }
+
+ /*
+ * COMMON UTILITIES FOR UNIT TESTS
+ */
+
+ public static byte[] DecodeHex(ReadOnlySpan<char> inputHex)
+ {
+ Assert.True(Regex.IsMatch(inputHex.ToString(), "^([0-9a-fA-F]{2})*$"), "Input must be an even number of hex characters.");
+
+ byte[] retVal = new byte[inputHex.Length / 2];
+ for (int i = 0; i < retVal.Length; i++)
+ {
+ retVal[i] = byte.Parse(inputHex.Slice(i * 2, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
+ }
+ return retVal;
+ }
+
+ // !! IMPORTANT !!
+ // Don't delete this implementation, as we use it as a reference to make sure the framework's
+ // transcoding logic is correct.
+ public static byte[] ToUtf8(Rune rune)
+ {
+ Assert.True(Rune.IsValid(rune.Value), $"Rune with value U+{(uint)rune.Value:X4} is not well-formed.");
+
+ if (rune.Value < 0x80)
+ {
+ return new[]
+ {
+ (byte)rune.Value
+ };
+ }
+ else if (rune.Value < 0x0800)
+ {
+ return new[]
+ {
+ (byte)((rune.Value >> 6) | 0xC0),
+ (byte)((rune.Value & 0x3F) | 0x80)
+ };
+ }
+ else if (rune.Value < 0x10000)
+ {
+ return new[]
+ {
+ (byte)((rune.Value >> 12) | 0xE0),
+ (byte)(((rune.Value >> 6) & 0x3F) | 0x80),
+ (byte)((rune.Value & 0x3F) | 0x80)
+ };
+ }
+ else
+ {
+ return new[]
+ {
+ (byte)((rune.Value >> 18) | 0xF0),
+ (byte)(((rune.Value >> 12) & 0x3F) | 0x80),
+ (byte)(((rune.Value >> 6) & 0x3F) | 0x80),
+ (byte)((rune.Value & 0x3F) | 0x80)
+ };
+ }
+ }
+
+ // !! IMPORTANT !!
+ // Don't delete this implementation, as we use it as a reference to make sure the framework's
+ // transcoding logic is correct.
+ private static char[] ToUtf16(Rune rune)
+ {
+ Assert.True(Rune.IsValid(rune.Value), $"Rune with value U+{(uint)rune.Value:X4} is not well-formed.");
+
+ if (rune.IsBmp)
+ {
+ return new[]
+ {
+ (char)rune.Value
+ };
+ }
+ else
+ {
+ return new[]
+ {
+ (char)((rune.Value >> 10) + 0xD800 - 0x40),
+ (char)((rune.Value & 0x03FF) + 0xDC00)
+ };
+ }
+ }
+
+ [Theory]
+ [InlineData("", "")] // empty string is OK
+ [InlineData(X_UTF16, X_UTF8)]
+ [InlineData(E_ACUTE_UTF16, E_ACUTE_UTF8)]
+ [InlineData(EURO_SYMBOL_UTF16, EURO_SYMBOL_UTF8)]
+ public void ToBytes_WithSmallValidBuffers(string utf16Input, string expectedUtf8TranscodingHex)
+ {
+ // These test cases are for the "slow processing" code path at the end of TranscodeToUtf8,
+ // so inputs should be less than 2 chars.
+
+ Assert.InRange(utf16Input.Length, 0, 1);
+
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: expectedUtf8TranscodingHex.Length / 2,
+ replaceInvalidSequences: false,
+ isFinalChunk: false,
+ expectedOperationStatus: OperationStatus.Done,
+ expectedNumCharsRead: utf16Input.Length,
+ expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
+ }
+
+ [Theory]
+ [InlineData("AB")] // 2 ASCII chars, hits fast inner loop
+ [InlineData("ABCD")] // 4 ASCII chars, hits fast inner loop
+ [InlineData("ABCDEF")] // 6 ASCII chars, hits fast inner loop
+ [InlineData("ABCDEFGH")] // 8 ASCII chars, hits fast inner loop
+ [InlineData("ABCDEFGHIJ")] // 10 ASCII chars, hits fast inner loop
+ [InlineData("ABCDEF" + E_ACUTE_UTF16 + "HIJ")] // interrupts inner loop due to non-ASCII char in first char of first DWORD
+ [InlineData("ABCDEFG" + EURO_SYMBOL_UTF16 + "IJ")] // interrupts inner loop due to non-ASCII char in second char of first DWORD
+ [InlineData("ABCDEFGH" + E_ACUTE_UTF16 + "J")] // interrupts inner loop due to non-ASCII char in first char of second DWORD
+ [InlineData("ABCDEFGHI" + EURO_SYMBOL_UTF16)] // interrupts inner loop due to non-ASCII char in second char of second DWORD
+ [InlineData(X_UTF16 + E_ACUTE_UTF16)] // drains first ASCII char then falls down to slow path
+ [InlineData(X_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16)] // drains first ASCII char then consumes 2x 2-byte sequences at once
+ [InlineData(E_ACUTE_UTF16 + X_UTF16)] // no first ASCII char to drain, consumes 2-byte seq followed by ASCII char
+ [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16)] // stay within 2x 2-byte sequence processing loop
+ [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + X_UTF16)] // break out of 2x 2-byte seq loop due to ASCII data in second char of DWORD
+ [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + X_UTF16 + X_UTF16)] // break out of 2x 2-byte seq loop due to ASCII data in first char of DWORD
+ [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + EURO_SYMBOL_UTF16)] // break out of 2x 2-byte seq loop due to 3-byte data
+ [InlineData(E_ACUTE_UTF16 + EURO_SYMBOL_UTF16)] // 2-byte logic sees next char isn't ASCII, cannot read full DWORD from remaining input buffer, falls down to slow drain loop
+ [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + X_UTF16)] // 2x 3-byte logic can't read a full DWORD from next part of buffer, falls down to slow drain loop
+ [InlineData(EURO_SYMBOL_UTF16 + X_UTF16)] // 3-byte processing loop consumes trailing ASCII char, but can't read next DWORD, falls down to slow drain loop
+ [InlineData(EURO_SYMBOL_UTF16 + X_UTF16 + X_UTF16)] // 3-byte processing loop consumes trailing ASCII char, but can't read next DWORD, falls down to slow drain loop
+ [InlineData(EURO_SYMBOL_UTF16 + E_ACUTE_UTF16)] // 3-byte processing loop can't consume next ASCII char, can't read DWORD, falls down to slow drain loop
+ [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // stay within 2x 3-byte sequence processing loop
+ [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + X_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // consume stray ASCII char at beginning of DWORD after 2x 3-byte sequence
+ [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + X_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // consume stray ASCII char at end of DWORD after 2x 3-byte sequence
+ [InlineData(EURO_SYMBOL_UTF16 + E_ACUTE_UTF16 + X_UTF16)] // consume 2-byte sequence as second char in DWORD which begins with 3-byte encoded char
+ [InlineData(EURO_SYMBOL_UTF16 + GRINNING_FACE_UTF16)] // 3-byte sequence followed by 4-byte sequence
+ [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + GRINNING_FACE_UTF16)] // 2x 3-byte sequence followed by 4-byte sequence
+ [InlineData(GRINNING_FACE_UTF16)] // single 4-byte surrogate char pair
+ [InlineData(GRINNING_FACE_UTF16 + EURO_SYMBOL_UTF16)] // 4-byte surrogate char pair, cannot read next DWORD, falls down to slow drain loop
+ public void ToBytes_WithLargeValidBuffers(string utf16Input)
+ {
+ // These test cases are for the "fast processing" code which is the main loop of TranscodeToUtf8,
+ // so inputs should be at least 2 chars.
+
+ Assert.True(utf16Input.Length >= 2);
+
+ // We're going to run the tests with destination buffer lengths ranging from 0 all the way
+ // to buffers large enough to hold the full output. This allows us to test logic that
+ // detects whether we're about to overrun our destination buffer and instead returns DestinationTooSmall.
+
+ Rune[] enumeratedScalars = utf16Input.EnumerateRunes().ToArray();
+
+ // 0-length buffer test
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: 0,
+ replaceInvalidSequences: false,
+ isFinalChunk: false,
+ expectedOperationStatus: OperationStatus.DestinationTooSmall,
+ expectedNumCharsRead: 0,
+ expectedUtf8Transcoding: ReadOnlySpan<byte>.Empty);
+
+ int expectedNumCharsConsumed = 0;
+ byte[] concatenatedUtf8 = Array.Empty<byte>();
+
+ for (int i = 0; i < enumeratedScalars.Length; i++)
+ {
+ Rune thisScalar = enumeratedScalars[i];
+
+ // provide partial destination buffers all the way up to (but not including) enough to hold the next full scalar encoding
+ for (int j = 1; j < thisScalar.Utf8SequenceLength; j++)
+ {
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: concatenatedUtf8.Length + j,
+ replaceInvalidSequences: false,
+ isFinalChunk: false,
+ expectedOperationStatus: OperationStatus.DestinationTooSmall,
+ expectedNumCharsRead: expectedNumCharsConsumed,
+ expectedUtf8Transcoding: concatenatedUtf8);
+ }
+
+ // now provide a destination buffer large enough to hold the next full scalar encoding
+
+ expectedNumCharsConsumed += thisScalar.Utf16SequenceLength;
+ concatenatedUtf8 = concatenatedUtf8.Concat(ToUtf8(thisScalar)).ToArray();
+
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: concatenatedUtf8.Length,
+ replaceInvalidSequences: false,
+ isFinalChunk: false,
+ expectedOperationStatus: (i == enumeratedScalars.Length - 1) ? OperationStatus.Done : OperationStatus.DestinationTooSmall,
+ expectedNumCharsRead: expectedNumCharsConsumed,
+ expectedUtf8Transcoding: concatenatedUtf8);
+ }
+
+ // now throw lots of ASCII data at the beginning so that we exercise the vectorized code paths
+
+ utf16Input = new string('x', 64) + utf16Input;
+ concatenatedUtf8 = utf16Input.EnumerateRunes().SelectMany(ToUtf8).ToArray();
+
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: concatenatedUtf8.Length,
+ replaceInvalidSequences: false,
+ isFinalChunk: true,
+ expectedOperationStatus: OperationStatus.Done,
+ expectedNumCharsRead: utf16Input.Length,
+ expectedUtf8Transcoding: concatenatedUtf8);
+
+ // now throw some non-ASCII data at the beginning so that we *don't* exercise the vectorized code paths
+
+ utf16Input = WOMAN_CARTWHEELING_MEDSKIN_UTF16 + utf16Input[64..];
+ concatenatedUtf8 = utf16Input.EnumerateRunes().SelectMany(ToUtf8).ToArray();
+
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: concatenatedUtf8.Length,
+ replaceInvalidSequences: false,
+ isFinalChunk: true,
+ expectedOperationStatus: OperationStatus.Done,
+ expectedNumCharsRead: utf16Input.Length,
+ expectedUtf8Transcoding: concatenatedUtf8);
+ }
+
+ [Theory]
+ [InlineData('\uD800', OperationStatus.NeedMoreData)] // standalone high surrogate
+ [InlineData('\uDFFF', OperationStatus.InvalidData)] // standalone low surrogate
+ public void ToBytes_WithOnlyStandaloneSurrogates(char charValue, OperationStatus expectedOperationStatus)
+ {
+ ToBytes_Test_Core(
+ utf16Input: new[] { charValue },
+ destinationSize: 0,
+ replaceInvalidSequences: false,
+ isFinalChunk: false,
+ expectedOperationStatus: expectedOperationStatus,
+ expectedNumCharsRead: 0,
+ expectedUtf8Transcoding: Span<byte>.Empty);
+ }
+
+ [Theory]
+ [InlineData("<LOW><HIGH>", 0, "")] // swapped surrogate pair characters
+ [InlineData("A<LOW><HIGH>", 1, "41")] // consume standalone ASCII char, then swapped surrogate pair characters
+ [InlineData("A<HIGH>B", 1, "41")] // consume standalone ASCII char, then standalone high surrogate char
+ [InlineData("A<LOW>B", 1, "41")] // consume standalone ASCII char, then standalone low surrogate char
+ [InlineData("AB<HIGH><HIGH>", 2, "4142")] // consume two ASCII chars, then standalone high surrogate char
+ [InlineData("AB<LOW><LOW>", 2, "4142")] // consume two ASCII chars, then standalone low surrogate char
+ public void ToBytes_WithInvalidSurrogates(string utf16Input, int expectedNumCharsConsumed, string expectedUtf8TranscodingHex)
+ {
+ // xUnit can't handle ill-formed strings in [InlineData], so we replace here.
+
+ utf16Input = utf16Input.Replace("<HIGH>", "\uD800").Replace("<LOW>", "\uDFFF");
+
+ // These test cases are for the "fast processing" code which is the main loop of TranscodeToUtf8,
+ // so inputs should be at least 2 chars.
+
+ Assert.True(utf16Input.Length >= 2);
+
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: expectedUtf8TranscodingHex.Length / 2,
+ replaceInvalidSequences: false,
+ isFinalChunk: false,
+ expectedOperationStatus: OperationStatus.InvalidData,
+ expectedNumCharsRead: expectedNumCharsConsumed,
+ expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
+
+ // Now try the tests again with a larger buffer.
+ // This ensures that running out of destination space wasn't the reason we failed.
+
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: (expectedUtf8TranscodingHex.Length) / 2 + 16,
+ replaceInvalidSequences: false,
+ isFinalChunk: false,
+ expectedOperationStatus: OperationStatus.InvalidData,
+ expectedNumCharsRead: expectedNumCharsConsumed,
+ expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
+ }
+
+ [Theory]
+ [InlineData("<LOW><HIGH>", REPLACEMENT_CHAR_UTF8)] // standalone low surr. and incomplete high surr.
+ [InlineData("<HIGH><HIGH>", REPLACEMENT_CHAR_UTF8)] // standalone high surr. and incomplete high surr.
+ [InlineData("<LOW><LOW>", REPLACEMENT_CHAR_UTF8 + REPLACEMENT_CHAR_UTF8)] // standalone low surr. and incomplete low surr.
+ [InlineData("A<LOW>B<LOW>C<HIGH>D", "41" + REPLACEMENT_CHAR_UTF8 + "42" + REPLACEMENT_CHAR_UTF8 + "43" + REPLACEMENT_CHAR_UTF8 + "44")] // standalone low, low, high surrounded by other data
+ public void ToBytes_WithReplacements(string utf16Input, string expectedUtf8TranscodingHex)
+ {
+ // xUnit can't handle ill-formed strings in [InlineData], so we replace here.
+
+ utf16Input = utf16Input.Replace("<HIGH>", "\uD800").Replace("<LOW>", "\uDFFF");
+
+ bool isFinalCharHighSurrogate = char.IsHighSurrogate(utf16Input.Last());
+
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: expectedUtf8TranscodingHex.Length / 2,
+ replaceInvalidSequences: true,
+ isFinalChunk: false,
+ expectedOperationStatus: (isFinalCharHighSurrogate) ? OperationStatus.NeedMoreData : OperationStatus.Done,
+ expectedNumCharsRead: (isFinalCharHighSurrogate) ? (utf16Input.Length - 1) : utf16Input.Length,
+ expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
+
+ if (isFinalCharHighSurrogate)
+ {
+ // Also test with isFinalChunk = true
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: expectedUtf8TranscodingHex.Length / 2 + Rune.ReplacementChar.Utf8SequenceLength /* for replacement char */,
+ replaceInvalidSequences: true,
+ isFinalChunk: true,
+ expectedOperationStatus: OperationStatus.Done,
+ expectedNumCharsRead: utf16Input.Length,
+ expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex + REPLACEMENT_CHAR_UTF8));
+ }
+ }
+
+ [Theory]
+ [InlineData(E_ACUTE_UTF16 + "<LOW>", true, 1, OperationStatus.DestinationTooSmall, E_ACUTE_UTF8)] // not enough output buffer to hold U+FFFD
+ [InlineData(E_ACUTE_UTF16 + "<LOW>", true, 2, OperationStatus.Done, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8)] // replace standalone low surr. at end
+ [InlineData(E_ACUTE_UTF16 + "<HIGH>", true, 1, OperationStatus.DestinationTooSmall, E_ACUTE_UTF8)] // not enough output buffer to hold U+FFFD
+ [InlineData(E_ACUTE_UTF16 + "<HIGH>", true, 2, OperationStatus.Done, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8)] // replace standalone high surr. at end
+ [InlineData(E_ACUTE_UTF16 + "<HIGH>", false, 1, OperationStatus.NeedMoreData, E_ACUTE_UTF8)] // don't replace standalone high surr. at end
+ [InlineData(E_ACUTE_UTF16 + "<HIGH>" + X_UTF16, true, 2, OperationStatus.DestinationTooSmall, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8)] // not enough output buffer to hold 'X'
+ [InlineData(E_ACUTE_UTF16 + "<HIGH>" + X_UTF16, false, 2, OperationStatus.DestinationTooSmall, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8)] // not enough output buffer to hold 'X'
+ [InlineData(E_ACUTE_UTF16 + "<HIGH>" + X_UTF16, true, 3, OperationStatus.Done, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8 + X_UTF8)] // replacement followed by 'X'
+ [InlineData(E_ACUTE_UTF16 + "<HIGH>" + X_UTF16, false, 3, OperationStatus.Done, E_ACUTE_UTF8 + REPLACEMENT_CHAR_UTF8 + X_UTF8)] // replacement followed by 'X'
+ public void ToBytes_WithReplacements_AndCustomBufferSizes(string utf16Input, bool isFinalChunk, int expectedNumCharsConsumed, OperationStatus expectedOperationStatus, string expectedUtf8TranscodingHex)
+ {
+ // xUnit can't handle ill-formed strings in [InlineData], so we replace here.
+
+ utf16Input = utf16Input.Replace("<HIGH>", "\uD800").Replace("<LOW>", "\uDFFF");
+
+ ToBytes_Test_Core(
+ utf16Input: utf16Input,
+ destinationSize: expectedUtf8TranscodingHex.Length / 2,
+ replaceInvalidSequences: true,
+ isFinalChunk: isFinalChunk,
+ expectedOperationStatus: expectedOperationStatus,
+ expectedNumCharsRead: expectedNumCharsConsumed,
+ expectedUtf8Transcoding: DecodeHex(expectedUtf8TranscodingHex));
+ }
+
+ [Fact]
+ public void ToBytes_AllPossibleScalarValues()
+ {
+ ToBytes_Test_Core(
+ utf16Input: s_allScalarsAsUtf16.Span,
+ destinationSize: s_allScalarsAsUtf8.Length,
+ replaceInvalidSequences: false,
+ isFinalChunk: false,
+ expectedOperationStatus: OperationStatus.Done,
+ expectedNumCharsRead: s_allScalarsAsUtf16.Length,
+ expectedUtf8Transcoding: s_allScalarsAsUtf8.Span);
+ }
+
+ private static void ToBytes_Test_Core(ReadOnlySpan<char> utf16Input, int destinationSize, bool replaceInvalidSequences, bool isFinalChunk, OperationStatus expectedOperationStatus, int expectedNumCharsRead, ReadOnlySpan<byte> expectedUtf8Transcoding)
+ {
+ // Arrange
+
+ using (BoundedMemory<char> boundedSource = BoundedMemory.AllocateFromExistingData(utf16Input))
+ using (BoundedMemory<byte> boundedDestination = BoundedMemory.Allocate<byte>(destinationSize))
+ {
+ boundedSource.MakeReadonly();
+
+ // Act
+
+ OperationStatus actualOperationStatus = Utf8.FromUtf16(boundedSource.Span, boundedDestination.Span, out int actualNumCharsRead, out int actualNumBytesWritten, replaceInvalidSequences, isFinalChunk);
+
+ // Assert
+
+ Assert.Equal(expectedOperationStatus, actualOperationStatus);
+ Assert.Equal(expectedNumCharsRead, actualNumCharsRead);
+ Assert.Equal(expectedUtf8Transcoding.Length, actualNumBytesWritten);
+ Assert.Equal(expectedUtf8Transcoding.ToArray(), boundedDestination.Span.Slice(0, actualNumBytesWritten).ToArray());
+ }
+ }
+
[Theory]
[InlineData("80", 0, "")] // sequence cannot begin with continuation character
[InlineData("8182", 0, "")] // sequence cannot begin with continuation character
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Buffers;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Text.RegularExpressions;
-using Xunit;
-
-namespace System.Text.Unicode.Tests
-{
- public partial class Utf8Tests
- {
- private const string X_UTF8 = "58"; // U+0058 LATIN CAPITAL LETTER X, 1 byte
- private const string X_UTF16 = "X";
-
- private const string Y_UTF8 = "59"; // U+0058 LATIN CAPITAL LETTER Y, 1 byte
- private const string Y_UTF16 = "Y";
-
- private const string Z_UTF8 = "5A"; // U+0058 LATIN CAPITAL LETTER Z, 1 byte
- private const string Z_UTF16 = "Z";
-
- private const string E_ACUTE_UTF8 = "C3A9"; // U+00E9 LATIN SMALL LETTER E WITH ACUTE, 2 bytes
- private const string E_ACUTE_UTF16 = "\u00E9";
-
- private const string EURO_SYMBOL_UTF8 = "E282AC"; // U+20AC EURO SIGN, 3 bytes
- private const string EURO_SYMBOL_UTF16 = "\u20AC";
-
- private const string REPLACEMENT_CHAR_UTF8 = "EFBFBD"; // U+FFFD REPLACEMENT CHAR, 3 bytes
- private const string REPLACEMENT_CHAR_UTF16 = "\uFFFD";
-
- private const string GRINNING_FACE_UTF8 = "F09F9880"; // U+1F600 GRINNING FACE, 4 bytes
- private const string GRINNING_FACE_UTF16 = "\U0001F600";
-
- private const string WOMAN_CARTWHEELING_MEDSKIN_UTF16 = "\U0001F938\U0001F3FD\u200D\u2640\uFE0F"; // U+1F938 U+1F3FD U+200D U+2640 U+FE0F WOMAN CARTWHEELING: MEDIUM SKIN TONE
-
- // All valid scalars [ U+0000 .. U+D7FF ] and [ U+E000 .. U+10FFFF ].
- private static readonly IEnumerable<Rune> s_allValidScalars = Enumerable.Range(0x0000, 0xD800).Concat(Enumerable.Range(0xE000, 0x110000 - 0xE000)).Select(value => new Rune(value));
-
- private static readonly ReadOnlyMemory<char> s_allScalarsAsUtf16;
- private static readonly ReadOnlyMemory<byte> s_allScalarsAsUtf8;
-
- static Utf8Tests()
- {
- List<char> allScalarsAsUtf16 = new List<char>();
- List<byte> allScalarsAsUtf8 = new List<byte>();
-
- foreach (Rune rune in s_allValidScalars)
- {
- allScalarsAsUtf16.AddRange(ToUtf16(rune));
- allScalarsAsUtf8.AddRange(ToUtf8(rune));
- }
-
- s_allScalarsAsUtf16 = allScalarsAsUtf16.ToArray().AsMemory();
- s_allScalarsAsUtf8 = allScalarsAsUtf8.ToArray().AsMemory();
- }
-
- /*
- * COMMON UTILITIES FOR UNIT TESTS
- */
-
- public static byte[] DecodeHex(ReadOnlySpan<char> inputHex)
- {
- Assert.True(Regex.IsMatch(inputHex.ToString(), "^([0-9a-fA-F]{2})*$"), "Input must be an even number of hex characters.");
-
- byte[] retVal = new byte[inputHex.Length / 2];
- for (int i = 0; i < retVal.Length; i++)
- {
- retVal[i] = byte.Parse(inputHex.Slice(i * 2, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
- }
- return retVal;
- }
-
- // !! IMPORTANT !!
- // Don't delete this implementation, as we use it as a reference to make sure the framework's
- // transcoding logic is correct.
- public static byte[] ToUtf8(Rune rune)
- {
- Assert.True(Rune.IsValid(rune.Value), $"Rune with value U+{(uint)rune.Value:X4} is not well-formed.");
-
- if (rune.Value < 0x80)
- {
- return new[]
- {
- (byte)rune.Value
- };
- }
- else if (rune.Value < 0x0800)
- {
- return new[]
- {
- (byte)((rune.Value >> 6) | 0xC0),
- (byte)((rune.Value & 0x3F) | 0x80)
- };
- }
- else if (rune.Value < 0x10000)
- {
- return new[]
- {
- (byte)((rune.Value >> 12) | 0xE0),
- (byte)(((rune.Value >> 6) & 0x3F) | 0x80),
- (byte)((rune.Value & 0x3F) | 0x80)
- };
- }
- else
- {
- return new[]
- {
- (byte)((rune.Value >> 18) | 0xF0),
- (byte)(((rune.Value >> 12) & 0x3F) | 0x80),
- (byte)(((rune.Value >> 6) & 0x3F) | 0x80),
- (byte)((rune.Value & 0x3F) | 0x80)
- };
- }
- }
-
- // !! IMPORTANT !!
- // Don't delete this implementation, as we use it as a reference to make sure the framework's
- // transcoding logic is correct.
- private static char[] ToUtf16(Rune rune)
- {
- Assert.True(Rune.IsValid(rune.Value), $"Rune with value U+{(uint)rune.Value:X4} is not well-formed.");
-
- if (rune.IsBmp)
- {
- return new[]
- {
- (char)rune.Value
- };
- }
- else
- {
- return new[]
- {
- (char)((rune.Value >> 10) + 0xD800 - 0x40),
- (char)((rune.Value & 0x03FF) + 0xDC00)
- };
- }
- }
- }
-}
namespace System.Text.Unicode.Tests
{
- public partial class Utf8UtilityTests
+ public class Utf8UtilityTests
{
private unsafe delegate byte* GetPointerToFirstInvalidByteDel(byte* pInputBuffer, int inputLength, out int utf16CodeUnitCountAdjustment, out int scalarCountAdjustment);
private static readonly Lazy<GetPointerToFirstInvalidByteDel> _getPointerToFirstInvalidByteFn = CreateGetPointerToFirstInvalidByteFn();
namespace System.Tests
{
- public partial class TimeSpanTests
+ public class TimeSpanTests
{
[Fact]
public static void MaxValue()
{
Assert.Equal(expected, Math.Sign(timeSpan1.CompareTo(obj)));
}
+
+ public static IEnumerable<object[]> MultiplicationTestData()
+ {
+ yield return new object[] {new TimeSpan(2, 30, 0), 2.0, new TimeSpan(5, 0, 0)};
+ yield return new object[] {new TimeSpan(14, 2, 30, 0), 192.0, TimeSpan.FromDays(2708)};
+ yield return new object[] {TimeSpan.FromDays(366), Math.PI, new TimeSpan(993446995288779)};
+ yield return new object[] {TimeSpan.FromDays(366), -Math.E, new TimeSpan(-859585952922633)};
+ yield return new object[] {TimeSpan.FromDays(29.530587981), 13.0, TimeSpan.FromDays(29.530587981 * 13.0) };
+ yield return new object[] {TimeSpan.FromDays(-29.530587981), -12.0, TimeSpan.FromDays(-29.530587981 * -12.0) };
+ yield return new object[] {TimeSpan.FromDays(-29.530587981), 0.0, TimeSpan.Zero};
+ yield return new object[] {TimeSpan.MaxValue, 0.5, TimeSpan.FromTicks((long)(long.MaxValue * 0.5))};
+ }
+
+ // ParseDifferentLengthFractionWithLeadingZerosData mainly testing the behavior we have fixed in net core
+ // which is the way we normalize the parsed fraction and possibly rounding it.
+ public static IEnumerable<object[]> ParseDifferentLengthFractionWithLeadingZerosData()
+ {
+ yield return new object[] {"00:00:00.00000001", new TimeSpan(0)};
+ yield return new object[] {"00:00:00.00000005", new TimeSpan(1)};
+ yield return new object[] {"00:00:00.09999999", new TimeSpan(1_000_000)};
+ yield return new object[] {"00:00:00.0268435455", new TimeSpan(268435)};
+ yield return new object[] {"00:00:00.01", new TimeSpan(1_00_000)};
+ yield return new object[] {"0:00:00.01000000", new TimeSpan(100_000)};
+ yield return new object[] {"0:00:00.010000000", new TimeSpan(100_000)};
+ yield return new object[] {"0:00:00.0123456", new TimeSpan(123456)};
+ yield return new object[] {"0:00:00.00123456", new TimeSpan(12346)};
+ yield return new object[] {"0:00:00.00000098", new TimeSpan(10)};
+ yield return new object[] {"0:00:00.00000099", new TimeSpan(10)};
+ }
+
+ [Theory, MemberData(nameof(ParseDifferentLengthFractionWithLeadingZerosData))]
+ public static void Multiplication(string input, TimeSpan expected)
+ {
+ Assert.Equal(expected, TimeSpan.Parse(input, CultureInfo.InvariantCulture));
+ Assert.Equal(expected, TimeSpan.ParseExact(input, "g", CultureInfo.InvariantCulture));
+ }
+
+ [Theory, MemberData(nameof(MultiplicationTestData))]
+ public static void Multiplication(TimeSpan timeSpan, double factor, TimeSpan expected)
+ {
+ Assert.Equal(expected, timeSpan * factor);
+ Assert.Equal(expected, factor * timeSpan);
+ }
+
+ [Fact]
+ public static void OverflowingMultiplication()
+ {
+ Assert.Throws<OverflowException>(() => TimeSpan.MaxValue * 1.000000001);
+ Assert.Throws<OverflowException>(() => -1.000000001 * TimeSpan.MaxValue);
+ }
+
+ [Fact]
+ public static void NaNMultiplication()
+ {
+ AssertExtensions.Throws<ArgumentException>("factor", () => TimeSpan.FromDays(1) * double.NaN);
+ AssertExtensions.Throws<ArgumentException>("factor", () => double.NaN * TimeSpan.FromDays(1));
+ }
+
+ [Theory, MemberData(nameof(MultiplicationTestData))]
+ public static void Division(TimeSpan timeSpan, double factor, TimeSpan expected)
+ {
+ Assert.Equal(factor, expected / timeSpan, 14);
+ double divisor = 1.0 / factor;
+ Assert.Equal(expected, timeSpan / divisor);
+ }
+
+ [Fact]
+ public static void DivideByZero()
+ {
+ Assert.Throws<OverflowException>(() => TimeSpan.FromDays(1) / 0);
+ Assert.Throws<OverflowException>(() => TimeSpan.FromDays(-1) / 0);
+ Assert.Throws<OverflowException>(() => TimeSpan.Zero / 0);
+ Assert.Equal(double.PositiveInfinity, TimeSpan.FromDays(1) / TimeSpan.Zero);
+ Assert.Equal(double.NegativeInfinity, TimeSpan.FromDays(-1) / TimeSpan.Zero);
+ Assert.True(double.IsNaN(TimeSpan.Zero / TimeSpan.Zero));
+ }
+
+ [Fact]
+ public static void NaNDivision()
+ {
+ AssertExtensions.Throws<ArgumentException>("divisor", () => TimeSpan.FromDays(1) / double.NaN);
+ }
+
+ [Theory, MemberData(nameof(MultiplicationTestData))]
+ public static void NamedMultiplication(TimeSpan timeSpan, double factor, TimeSpan expected)
+ {
+ Assert.Equal(expected, timeSpan.Multiply(factor));
+ }
+
+ [Fact]
+ public static void NamedOverflowingMultiplication()
+ {
+ Assert.Throws<OverflowException>(() => TimeSpan.MaxValue.Multiply(1.000000001));
+ }
+
+ [Fact]
+ public static void NamedNaNMultiplication()
+ {
+ AssertExtensions.Throws<ArgumentException>("factor", () => TimeSpan.FromDays(1).Multiply(double.NaN));
+ }
+
+ [Theory, MemberData(nameof(MultiplicationTestData))]
+ public static void NamedDivision(TimeSpan timeSpan, double factor, TimeSpan expected)
+ {
+ Assert.Equal(factor, expected.Divide(timeSpan), 14);
+ double divisor = 1.0 / factor;
+ Assert.Equal(expected, timeSpan.Divide(divisor));
+ }
+
+ [Fact]
+ public static void NamedDivideByZero()
+ {
+ Assert.Throws<OverflowException>(() => TimeSpan.FromDays(1).Divide(0));
+ Assert.Throws<OverflowException>(() => TimeSpan.FromDays(-1).Divide(0));
+ Assert.Throws<OverflowException>(() => TimeSpan.Zero.Divide(0));
+ Assert.Equal(double.PositiveInfinity, TimeSpan.FromDays(1).Divide(TimeSpan.Zero));
+ Assert.Equal(double.NegativeInfinity, TimeSpan.FromDays(-1).Divide(TimeSpan.Zero));
+ Assert.True(double.IsNaN(TimeSpan.Zero.Divide(TimeSpan.Zero)));
+ }
+
+ [Fact]
+ public static void NamedNaNDivision()
+ {
+ AssertExtensions.Throws<ArgumentException>("divisor", () => TimeSpan.FromDays(1).Divide(double.NaN));
+ }
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2] };
+ }
+
+ yield return new object[] { " 12:24:02 ", 5, 8, null, new TimeSpan(0, 12, 24, 2, 0) };
+ yield return new object[] { " 12:24:02 ", 6, 7, null, new TimeSpan(0, 2, 24, 2, 0) };
+ yield return new object[] { " 12:24:02 ", 6, 6, null, new TimeSpan(0, 2, 24, 0, 0) };
+ yield return new object[] { "12:24:02.01", 0, 8, CultureInfo.InvariantCulture, new TimeSpan(0, 12, 24, 2, 0) };
+ yield return new object[] { "1:1:1.00000001", 0, 7, CultureInfo.InvariantCulture, new TimeSpan(1, 1, 1) };
+ yield return new object[] { "1:1:.00000001", 0, 6, CultureInfo.InvariantCulture, new TimeSpan(36600000000) };
+ yield return new object[] { "24:00:00", 1, 7, null, new TimeSpan(4, 0, 0) };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span(string inputString, int offset, int count, IFormatProvider provider, TimeSpan expected)
+ {
+ ReadOnlySpan<char> input = inputString.AsSpan(offset, count);
+ TimeSpan result;
+
+ // Default provider.
+ if (provider == null)
+ {
+ Assert.True(TimeSpan.TryParse(input, out result));
+ Assert.Equal(expected, result);
+ }
+
+ Assert.Equal(expected, TimeSpan.Parse(input, provider));
+ Assert.True(TimeSpan.TryParse(input, provider, out result));
+ Assert.Equal(expected, result);
+
+ // Also negate
+ if (!char.IsWhiteSpace(input[0]))
+ {
+ input = ("-" + inputString.Substring(offset, count)).AsSpan();
+ expected = -expected;
+
+ Assert.Equal(expected, TimeSpan.Parse(input, provider));
+ Assert.True(TimeSpan.TryParse(input, provider, out result));
+ Assert.Equal(expected, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string inputString, IFormatProvider provider, Type exceptionType)
+ {
+ if (inputString != null)
+ {
+ Assert.Throws(exceptionType, () => TimeSpan.Parse(inputString.AsSpan(), provider));
+ Assert.False(TimeSpan.TryParse(inputString.AsSpan(), provider, out TimeSpan result));
+ Assert.Equal(TimeSpan.Zero, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ParseExact_Valid_TestData))]
+ public static void ParseExact_Span_Valid(string inputString, string format, TimeSpan expected)
+ {
+ ReadOnlySpan<char> input = inputString.AsSpan();
+
+ TimeSpan result;
+ Assert.Equal(expected, TimeSpan.ParseExact(input, format, new CultureInfo("en-US")));
+ Assert.Equal(expected, TimeSpan.ParseExact(input, format, new CultureInfo("en-US"), TimeSpanStyles.None));
+ Assert.Equal(expected, TimeSpan.ParseExact(input, new[] { format }, new CultureInfo("en-US")));
+ Assert.Equal(expected, TimeSpan.ParseExact(input, new[] { format }, new CultureInfo("en-US"), TimeSpanStyles.None));
+
+ Assert.True(TimeSpan.TryParseExact(input, format, new CultureInfo("en-US"), out result));
+ Assert.Equal(expected, result);
+
+ Assert.True(TimeSpan.TryParseExact(input, format, new CultureInfo("en-US"), TimeSpanStyles.None, out result));
+ Assert.Equal(expected, result);
+
+ Assert.True(TimeSpan.TryParseExact(input, new[] { format }, new CultureInfo("en-US"), out result));
+ Assert.Equal(expected, result);
+
+ Assert.True(TimeSpan.TryParseExact(input, new[] { format }, new CultureInfo("en-US"), TimeSpanStyles.None, out result));
+ Assert.Equal(expected, result);
+
+ if (format != "c" && format != "t" && format != "T" && format != "g" && format != "G")
+ {
+ // TimeSpanStyles is interpreted only for custom formats
+ Assert.Equal(expected.Negate(), TimeSpan.ParseExact(input, format, new CultureInfo("en-US"), TimeSpanStyles.AssumeNegative));
+
+ Assert.True(TimeSpan.TryParseExact(input, format, new CultureInfo("en-US"), TimeSpanStyles.AssumeNegative, out result));
+ Assert.Equal(expected.Negate(), result);
+ }
+ else
+ {
+ // Inputs that can be parsed in standard formats with ParseExact should also be parsable with Parse
+ Assert.Equal(expected, TimeSpan.Parse(input, CultureInfo.InvariantCulture));
+
+ Assert.True(TimeSpan.TryParse(input, CultureInfo.InvariantCulture, out result));
+ Assert.Equal(expected, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ParseExact_Invalid_TestData))]
+ public static void ParseExactTest_Span_Invalid(string inputString, string format, Type exceptionType)
+ {
+ if (inputString != null && format != null)
+ {
+ Assert.Throws(exceptionType, () => TimeSpan.ParseExact(inputString.AsSpan(), format, new CultureInfo("en-US")));
+
+ TimeSpan result;
+ Assert.False(TimeSpan.TryParseExact(inputString.AsSpan(), format, new CultureInfo("en-US"), out result));
+ Assert.Equal(TimeSpan.Zero, result);
+
+ Assert.False(TimeSpan.TryParseExact(inputString.AsSpan(), format, new CultureInfo("en-US"), TimeSpanStyles.None, out result));
+ Assert.Equal(TimeSpan.Zero, result);
+
+ Assert.False(TimeSpan.TryParseExact(inputString.AsSpan(), new[] { format }, new CultureInfo("en-US"), out result));
+ Assert.Equal(TimeSpan.Zero, result);
+
+ Assert.False(TimeSpan.TryParseExact(inputString.AsSpan(), new[] { format }, new CultureInfo("en-US"), TimeSpanStyles.None, out result));
+ Assert.Equal(TimeSpan.Zero, result);
+ }
+ }
+
+ [Fact]
+ public static void ParseExactMultiple_Span_InvalidNullEmptyFormats()
+ {
+ TimeSpan result;
+
+ AssertExtensions.Throws<ArgumentNullException>("formats", () => TimeSpan.ParseExact("12:34:56".AsSpan(), (string[])null, null));
+ Assert.False(TimeSpan.TryParseExact("12:34:56".AsSpan(), (string[])null, null, out result));
+
+ Assert.Throws<FormatException>(() => TimeSpan.ParseExact("12:34:56".AsSpan(), new string[0], null));
+ Assert.False(TimeSpan.TryParseExact("12:34:56".AsSpan(), new string[0], null, out result));
+ }
+
+ [Theory]
+ [MemberData(nameof(ParseExact_InvalidStyles_TestData))]
+ public void ParseExact_InvalidStylesSpan_ThrowsArgumentException(TimeSpanStyles styles)
+ {
+ TimeSpan result;
+
+ string inputString = "00:00:00";
+ AssertExtensions.Throws<ArgumentException>("styles", () => TimeSpan.ParseExact(inputString.AsSpan(), "s", new CultureInfo("en-US"), styles));
+ AssertExtensions.Throws<ArgumentException>("styles", () => TimeSpan.ParseExact(inputString.AsSpan(), new string[] { "s" }, new CultureInfo("en-US"), styles));
+ AssertExtensions.Throws<ArgumentException>("styles", () => TimeSpan.TryParseExact(inputString.AsSpan(), "s", new CultureInfo("en-US"), styles, out result));
+ AssertExtensions.Throws<ArgumentException>("styles", () => TimeSpan.TryParseExact(inputString.AsSpan(), new string[] { "s" }, new CultureInfo("en-US"), styles, out result));
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat_Valid(TimeSpan input, string format, CultureInfo info, string expected)
+ {
+ int charsWritten;
+ Span<char> dst;
+
+ dst = new char[expected.Length - 1];
+ Assert.False(input.TryFormat(dst, out charsWritten, format, info));
+ Assert.Equal(0, charsWritten);
+
+ dst = new char[expected.Length];
+ Assert.True(input.TryFormat(dst, out charsWritten, format, info));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(dst));
+
+ dst = new char[expected.Length + 1];
+ Assert.True(input.TryFormat(dst, out charsWritten, format, info));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(dst.Slice(0, dst.Length - 1)));
+ Assert.Equal(0, dst[dst.Length - 1]);
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_InvalidFormat_TestData))]
+ public void TryFormat_InvalidFormat_ThrowsFormatException(string invalidFormat)
+ {
+ char[] dst = new char[1];
+ Assert.Throws<FormatException>(() => new TimeSpan().TryFormat(dst.AsSpan(), out int charsWritten, invalidFormat, null));
+ }
+
+ [Fact]
+ public static void ConvertToTimeSpanPrecisionTest()
+ {
+ Assert.Equal(12345, TimeSpan.FromMilliseconds(1.23456).Ticks);
+ Assert.Equal(12345, TimeSpan.FromMilliseconds(1.234567).Ticks);
+
+ Assert.Equal(12345600, TimeSpan.FromSeconds(1.23456).Ticks);
+
+ Assert.Equal(1.23456 * 60 * 10_000_000, TimeSpan.FromMinutes(1.23456).Ticks);
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class TimeSpanTests
- {
- public static IEnumerable<object[]> MultiplicationTestData()
- {
- yield return new object[] {new TimeSpan(2, 30, 0), 2.0, new TimeSpan(5, 0, 0)};
- yield return new object[] {new TimeSpan(14, 2, 30, 0), 192.0, TimeSpan.FromDays(2708)};
- yield return new object[] {TimeSpan.FromDays(366), Math.PI, new TimeSpan(993446995288779)};
- yield return new object[] {TimeSpan.FromDays(366), -Math.E, new TimeSpan(-859585952922633)};
- yield return new object[] {TimeSpan.FromDays(29.530587981), 13.0, TimeSpan.FromDays(29.530587981 * 13.0) };
- yield return new object[] {TimeSpan.FromDays(-29.530587981), -12.0, TimeSpan.FromDays(-29.530587981 * -12.0) };
- yield return new object[] {TimeSpan.FromDays(-29.530587981), 0.0, TimeSpan.Zero};
- yield return new object[] {TimeSpan.MaxValue, 0.5, TimeSpan.FromTicks((long)(long.MaxValue * 0.5))};
- }
-
- // ParseDifferentLengthFractionWithLeadingZerosData mainly testing the behavior we have fixed in net core
- // which is the way we normalize the parsed fraction and possibly rounding it.
- public static IEnumerable<object[]> ParseDifferentLengthFractionWithLeadingZerosData()
- {
- yield return new object[] {"00:00:00.00000001", new TimeSpan(0)};
- yield return new object[] {"00:00:00.00000005", new TimeSpan(1)};
- yield return new object[] {"00:00:00.09999999", new TimeSpan(1_000_000)};
- yield return new object[] {"00:00:00.0268435455", new TimeSpan(268435)};
- yield return new object[] {"00:00:00.01", new TimeSpan(1_00_000)};
- yield return new object[] {"0:00:00.01000000", new TimeSpan(100_000)};
- yield return new object[] {"0:00:00.010000000", new TimeSpan(100_000)};
- yield return new object[] {"0:00:00.0123456", new TimeSpan(123456)};
- yield return new object[] {"0:00:00.00123456", new TimeSpan(12346)};
- yield return new object[] {"0:00:00.00000098", new TimeSpan(10)};
- yield return new object[] {"0:00:00.00000099", new TimeSpan(10)};
- }
-
- [Theory, MemberData(nameof(ParseDifferentLengthFractionWithLeadingZerosData))]
- public static void Multiplication(string input, TimeSpan expected)
- {
- Assert.Equal(expected, TimeSpan.Parse(input, CultureInfo.InvariantCulture));
- Assert.Equal(expected, TimeSpan.ParseExact(input, "g", CultureInfo.InvariantCulture));
- }
-
- [Theory, MemberData(nameof(MultiplicationTestData))]
- public static void Multiplication(TimeSpan timeSpan, double factor, TimeSpan expected)
- {
- Assert.Equal(expected, timeSpan * factor);
- Assert.Equal(expected, factor * timeSpan);
- }
-
- [Fact]
- public static void OverflowingMultiplication()
- {
- Assert.Throws<OverflowException>(() => TimeSpan.MaxValue * 1.000000001);
- Assert.Throws<OverflowException>(() => -1.000000001 * TimeSpan.MaxValue);
- }
-
- [Fact]
- public static void NaNMultiplication()
- {
- AssertExtensions.Throws<ArgumentException>("factor", () => TimeSpan.FromDays(1) * double.NaN);
- AssertExtensions.Throws<ArgumentException>("factor", () => double.NaN * TimeSpan.FromDays(1));
- }
-
- [Theory, MemberData(nameof(MultiplicationTestData))]
- public static void Division(TimeSpan timeSpan, double factor, TimeSpan expected)
- {
- Assert.Equal(factor, expected / timeSpan, 14);
- double divisor = 1.0 / factor;
- Assert.Equal(expected, timeSpan / divisor);
- }
-
- [Fact]
- public static void DivideByZero()
- {
- Assert.Throws<OverflowException>(() => TimeSpan.FromDays(1) / 0);
- Assert.Throws<OverflowException>(() => TimeSpan.FromDays(-1) / 0);
- Assert.Throws<OverflowException>(() => TimeSpan.Zero / 0);
- Assert.Equal(double.PositiveInfinity, TimeSpan.FromDays(1) / TimeSpan.Zero);
- Assert.Equal(double.NegativeInfinity, TimeSpan.FromDays(-1) / TimeSpan.Zero);
- Assert.True(double.IsNaN(TimeSpan.Zero / TimeSpan.Zero));
- }
-
- [Fact]
- public static void NaNDivision()
- {
- AssertExtensions.Throws<ArgumentException>("divisor", () => TimeSpan.FromDays(1) / double.NaN);
- }
-
- [Theory, MemberData(nameof(MultiplicationTestData))]
- public static void NamedMultiplication(TimeSpan timeSpan, double factor, TimeSpan expected)
- {
- Assert.Equal(expected, timeSpan.Multiply(factor));
- }
-
- [Fact]
- public static void NamedOverflowingMultiplication()
- {
- Assert.Throws<OverflowException>(() => TimeSpan.MaxValue.Multiply(1.000000001));
- }
-
- [Fact]
- public static void NamedNaNMultiplication()
- {
- AssertExtensions.Throws<ArgumentException>("factor", () => TimeSpan.FromDays(1).Multiply(double.NaN));
- }
-
- [Theory, MemberData(nameof(MultiplicationTestData))]
- public static void NamedDivision(TimeSpan timeSpan, double factor, TimeSpan expected)
- {
- Assert.Equal(factor, expected.Divide(timeSpan), 14);
- double divisor = 1.0 / factor;
- Assert.Equal(expected, timeSpan.Divide(divisor));
- }
-
- [Fact]
- public static void NamedDivideByZero()
- {
- Assert.Throws<OverflowException>(() => TimeSpan.FromDays(1).Divide(0));
- Assert.Throws<OverflowException>(() => TimeSpan.FromDays(-1).Divide(0));
- Assert.Throws<OverflowException>(() => TimeSpan.Zero.Divide(0));
- Assert.Equal(double.PositiveInfinity, TimeSpan.FromDays(1).Divide(TimeSpan.Zero));
- Assert.Equal(double.NegativeInfinity, TimeSpan.FromDays(-1).Divide(TimeSpan.Zero));
- Assert.True(double.IsNaN(TimeSpan.Zero.Divide(TimeSpan.Zero)));
- }
-
- [Fact]
- public static void NamedNaNDivision()
- {
- AssertExtensions.Throws<ArgumentException>("divisor", () => TimeSpan.FromDays(1).Divide(double.NaN));
- }
-
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2] };
- }
-
- yield return new object[] { " 12:24:02 ", 5, 8, null, new TimeSpan(0, 12, 24, 2, 0) };
- yield return new object[] { " 12:24:02 ", 6, 7, null, new TimeSpan(0, 2, 24, 2, 0) };
- yield return new object[] { " 12:24:02 ", 6, 6, null, new TimeSpan(0, 2, 24, 0, 0) };
- yield return new object[] { "12:24:02.01", 0, 8, CultureInfo.InvariantCulture, new TimeSpan(0, 12, 24, 2, 0) };
- yield return new object[] { "1:1:1.00000001", 0, 7, CultureInfo.InvariantCulture, new TimeSpan(1, 1, 1) };
- yield return new object[] { "1:1:.00000001", 0, 6, CultureInfo.InvariantCulture, new TimeSpan(36600000000) };
- yield return new object[] { "24:00:00", 1, 7, null, new TimeSpan(4, 0, 0) };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span(string inputString, int offset, int count, IFormatProvider provider, TimeSpan expected)
- {
- ReadOnlySpan<char> input = inputString.AsSpan(offset, count);
- TimeSpan result;
-
- // Default provider.
- if (provider == null)
- {
- Assert.True(TimeSpan.TryParse(input, out result));
- Assert.Equal(expected, result);
- }
-
- Assert.Equal(expected, TimeSpan.Parse(input, provider));
- Assert.True(TimeSpan.TryParse(input, provider, out result));
- Assert.Equal(expected, result);
-
- // Also negate
- if (!char.IsWhiteSpace(input[0]))
- {
- input = ("-" + inputString.Substring(offset, count)).AsSpan();
- expected = -expected;
-
- Assert.Equal(expected, TimeSpan.Parse(input, provider));
- Assert.True(TimeSpan.TryParse(input, provider, out result));
- Assert.Equal(expected, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string inputString, IFormatProvider provider, Type exceptionType)
- {
- if (inputString != null)
- {
- Assert.Throws(exceptionType, () => TimeSpan.Parse(inputString.AsSpan(), provider));
- Assert.False(TimeSpan.TryParse(inputString.AsSpan(), provider, out TimeSpan result));
- Assert.Equal(TimeSpan.Zero, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ParseExact_Valid_TestData))]
- public static void ParseExact_Span_Valid(string inputString, string format, TimeSpan expected)
- {
- ReadOnlySpan<char> input = inputString.AsSpan();
-
- TimeSpan result;
- Assert.Equal(expected, TimeSpan.ParseExact(input, format, new CultureInfo("en-US")));
- Assert.Equal(expected, TimeSpan.ParseExact(input, format, new CultureInfo("en-US"), TimeSpanStyles.None));
- Assert.Equal(expected, TimeSpan.ParseExact(input, new[] { format }, new CultureInfo("en-US")));
- Assert.Equal(expected, TimeSpan.ParseExact(input, new[] { format }, new CultureInfo("en-US"), TimeSpanStyles.None));
-
- Assert.True(TimeSpan.TryParseExact(input, format, new CultureInfo("en-US"), out result));
- Assert.Equal(expected, result);
-
- Assert.True(TimeSpan.TryParseExact(input, format, new CultureInfo("en-US"), TimeSpanStyles.None, out result));
- Assert.Equal(expected, result);
-
- Assert.True(TimeSpan.TryParseExact(input, new[] { format }, new CultureInfo("en-US"), out result));
- Assert.Equal(expected, result);
-
- Assert.True(TimeSpan.TryParseExact(input, new[] { format }, new CultureInfo("en-US"), TimeSpanStyles.None, out result));
- Assert.Equal(expected, result);
-
- if (format != "c" && format != "t" && format != "T" && format != "g" && format != "G")
- {
- // TimeSpanStyles is interpreted only for custom formats
- Assert.Equal(expected.Negate(), TimeSpan.ParseExact(input, format, new CultureInfo("en-US"), TimeSpanStyles.AssumeNegative));
-
- Assert.True(TimeSpan.TryParseExact(input, format, new CultureInfo("en-US"), TimeSpanStyles.AssumeNegative, out result));
- Assert.Equal(expected.Negate(), result);
- }
- else
- {
- // Inputs that can be parsed in standard formats with ParseExact should also be parsable with Parse
- Assert.Equal(expected, TimeSpan.Parse(input, CultureInfo.InvariantCulture));
-
- Assert.True(TimeSpan.TryParse(input, CultureInfo.InvariantCulture, out result));
- Assert.Equal(expected, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ParseExact_Invalid_TestData))]
- public static void ParseExactTest_Span_Invalid(string inputString, string format, Type exceptionType)
- {
- if (inputString != null && format != null)
- {
- Assert.Throws(exceptionType, () => TimeSpan.ParseExact(inputString.AsSpan(), format, new CultureInfo("en-US")));
-
- TimeSpan result;
- Assert.False(TimeSpan.TryParseExact(inputString.AsSpan(), format, new CultureInfo("en-US"), out result));
- Assert.Equal(TimeSpan.Zero, result);
-
- Assert.False(TimeSpan.TryParseExact(inputString.AsSpan(), format, new CultureInfo("en-US"), TimeSpanStyles.None, out result));
- Assert.Equal(TimeSpan.Zero, result);
-
- Assert.False(TimeSpan.TryParseExact(inputString.AsSpan(), new[] { format }, new CultureInfo("en-US"), out result));
- Assert.Equal(TimeSpan.Zero, result);
-
- Assert.False(TimeSpan.TryParseExact(inputString.AsSpan(), new[] { format }, new CultureInfo("en-US"), TimeSpanStyles.None, out result));
- Assert.Equal(TimeSpan.Zero, result);
- }
- }
-
- [Fact]
- public static void ParseExactMultiple_Span_InvalidNullEmptyFormats()
- {
- TimeSpan result;
-
- AssertExtensions.Throws<ArgumentNullException>("formats", () => TimeSpan.ParseExact("12:34:56".AsSpan(), (string[])null, null));
- Assert.False(TimeSpan.TryParseExact("12:34:56".AsSpan(), (string[])null, null, out result));
-
- Assert.Throws<FormatException>(() => TimeSpan.ParseExact("12:34:56".AsSpan(), new string[0], null));
- Assert.False(TimeSpan.TryParseExact("12:34:56".AsSpan(), new string[0], null, out result));
- }
-
- [Theory]
- [MemberData(nameof(ParseExact_InvalidStyles_TestData))]
- public void ParseExact_InvalidStylesSpan_ThrowsArgumentException(TimeSpanStyles styles)
- {
- TimeSpan result;
-
- string inputString = "00:00:00";
- AssertExtensions.Throws<ArgumentException>("styles", () => TimeSpan.ParseExact(inputString.AsSpan(), "s", new CultureInfo("en-US"), styles));
- AssertExtensions.Throws<ArgumentException>("styles", () => TimeSpan.ParseExact(inputString.AsSpan(), new string[] { "s" }, new CultureInfo("en-US"), styles));
- AssertExtensions.Throws<ArgumentException>("styles", () => TimeSpan.TryParseExact(inputString.AsSpan(), "s", new CultureInfo("en-US"), styles, out result));
- AssertExtensions.Throws<ArgumentException>("styles", () => TimeSpan.TryParseExact(inputString.AsSpan(), new string[] { "s" }, new CultureInfo("en-US"), styles, out result));
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat_Valid(TimeSpan input, string format, CultureInfo info, string expected)
- {
- int charsWritten;
- Span<char> dst;
-
- dst = new char[expected.Length - 1];
- Assert.False(input.TryFormat(dst, out charsWritten, format, info));
- Assert.Equal(0, charsWritten);
-
- dst = new char[expected.Length];
- Assert.True(input.TryFormat(dst, out charsWritten, format, info));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(dst));
-
- dst = new char[expected.Length + 1];
- Assert.True(input.TryFormat(dst, out charsWritten, format, info));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(dst.Slice(0, dst.Length - 1)));
- Assert.Equal(0, dst[dst.Length - 1]);
- }
-
- [Theory]
- [MemberData(nameof(ToString_InvalidFormat_TestData))]
- public void TryFormat_InvalidFormat_ThrowsFormatException(string invalidFormat)
- {
- char[] dst = new char[1];
- Assert.Throws<FormatException>(() => new TimeSpan().TryFormat(dst.AsSpan(), out int charsWritten, invalidFormat, null));
- }
-
- [Fact]
- public static void ConvertToTimeSpanPrecisionTest()
- {
- Assert.Equal(12345, TimeSpan.FromMilliseconds(1.23456).Ticks);
- Assert.Equal(12345, TimeSpan.FromMilliseconds(1.234567).Ticks);
-
- Assert.Equal(12345600, TimeSpan.FromSeconds(1.23456).Ticks);
-
- Assert.Equal(1.23456 * 60 * 10_000_000, TimeSpan.FromMinutes(1.23456).Ticks);
- }
- }
-}
namespace System.Tests.Types
{
- public abstract partial class TypePropertyTestBase
+ public abstract class TypePropertyTestBase
{
public abstract Type CreateType();
{
Assert.Equal(UnderlyingSystemType, CreateType().UnderlyingSystemType);
}
+
+ [Fact]
+ public void IsGenericMethodParameter_Get_ReturnsExpected()
+ {
+ Assert.Equal(IsGenericMethodParameter, CreateType().IsGenericMethodParameter);
+ }
+
+ [Fact]
+ public void IsGenericTypeParameter_Get_ReturnsExpected()
+ {
+ Assert.Equal(IsGenericTypeParameter, CreateType().IsGenericTypeParameter);
+ }
+
+ [Fact]
+ public void IsSignatureType_Get_ReturnsExpected()
+ {
+ Assert.Equal(IsSignatureType, CreateType().IsSignatureType);
+ }
+
+ [Fact]
+ public void IsSZArray_Get_ReturnsExpected()
+ {
+ Assert.Equal(IsSZArray, CreateType().IsSZArray);
+ }
+
+ [Fact]
+ public void IsTypeDefinition_Get_ReturnsExpected()
+ {
+ Assert.Equal(IsTypeDefinition, CreateType().IsTypeDefinition);
+ }
+
+ [Fact]
+ public void IsVariableBoundArray_Get_ReturnsExpected()
+ {
+ Assert.Equal(IsVariableBoundArray, CreateType().IsVariableBoundArray);
+ }
}
public abstract class ArrayTypeTestBase : TypePropertyTestBase
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Reflection;
-using Xunit;
-
-namespace System.Tests.Types
-{
- public abstract partial class TypePropertyTestBase
- {
- [Fact]
- public void IsGenericMethodParameter_Get_ReturnsExpected()
- {
- Assert.Equal(IsGenericMethodParameter, CreateType().IsGenericMethodParameter);
- }
-
- [Fact]
- public void IsGenericTypeParameter_Get_ReturnsExpected()
- {
- Assert.Equal(IsGenericTypeParameter, CreateType().IsGenericTypeParameter);
- }
-
- [Fact]
- public void IsSignatureType_Get_ReturnsExpected()
- {
- Assert.Equal(IsSignatureType, CreateType().IsSignatureType);
- }
-
- [Fact]
- public void IsSZArray_Get_ReturnsExpected()
- {
- Assert.Equal(IsSZArray, CreateType().IsSZArray);
- }
-
- [Fact]
- public void IsTypeDefinition_Get_ReturnsExpected()
- {
- Assert.Equal(IsTypeDefinition, CreateType().IsTypeDefinition);
- }
-
- [Fact]
- public void IsVariableBoundArray_Get_ReturnsExpected()
- {
- Assert.Equal(IsVariableBoundArray, CreateType().IsVariableBoundArray);
- }
- }
-}
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Reflection;
+using System.Runtime.CompilerServices;
using Microsoft.DotNet.RemoteExecutor;
using Xunit;
{
public partial class TypeTests
{
+ private static readonly IList<Type> NonArrayBaseTypes;
+
+ static TypeTests()
+ {
+ NonArrayBaseTypes = new List<Type>()
+ {
+ typeof(int),
+ typeof(void),
+ typeof(int*),
+ typeof(Outside),
+ typeof(Outside<int>),
+ typeof(Outside<>).GetTypeInfo().GenericTypeParameters[0],
+ new object().GetType().GetType()
+ };
+
+ if (PlatformDetection.IsWindows)
+ {
+ NonArrayBaseTypes.Add(Type.GetTypeFromCLSID(default(Guid)));
+ }
+ }
+
[Fact]
public void FilterName_Get_ReturnsExpected()
{
Assert.Throws<PlatformNotSupportedException>(() => Type.ReflectionOnlyGetType("", true, true));
Assert.Throws<PlatformNotSupportedException>(() => Type.ReflectionOnlyGetType("System.Tests.TypeTests", false, true));
}
+
+ [Fact]
+ public void IsSZArray_FalseForNonArrayTypes()
+ {
+ foreach (Type type in NonArrayBaseTypes)
+ {
+ Assert.False(type.IsSZArray);
+ }
+ }
+
+ [Fact]
+ public void IsSZArray_TrueForSZArrayTypes()
+ {
+ foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType()))
+ {
+ Assert.True(type.IsSZArray);
+ }
+ }
+
+ [Fact]
+ public void IsSZArray_FalseForVariableBoundArrayTypes()
+ {
+ foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType(1)))
+ {
+ Assert.False(type.IsSZArray);
+ }
+
+ foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType(2)))
+ {
+ Assert.False(type.IsSZArray);
+ }
+ }
+
+ [Fact]
+ public void IsSZArray_FalseForNonArrayByRefType()
+ {
+ Assert.False(typeof(int).MakeByRefType().IsSZArray);
+ }
+
+ [Fact]
+ public void IsSZArray_FalseForByRefSZArrayType()
+ {
+ Assert.False(typeof(int[]).MakeByRefType().IsSZArray);
+ }
+
+
+ [Fact]
+ public void IsSZArray_FalseForByRefVariableArrayType()
+ {
+ Assert.False(typeof(int[,]).MakeByRefType().IsSZArray);
+ }
+
+ [Fact]
+ public void IsVariableBoundArray_FalseForNonArrayTypes()
+ {
+ foreach (Type type in NonArrayBaseTypes)
+ {
+ Assert.False(type.IsVariableBoundArray);
+ }
+ }
+
+ [Fact]
+ public void IsVariableBoundArray_FalseForSZArrayTypes()
+ {
+ foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType()))
+ {
+ Assert.False(type.IsVariableBoundArray);
+ }
+ }
+
+ [Fact]
+ public void IsVariableBoundArray_TrueForVariableBoundArrayTypes()
+ {
+ foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType(1)))
+ {
+ Assert.True(type.IsVariableBoundArray);
+ }
+
+ foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType(2)))
+ {
+ Assert.True(type.IsVariableBoundArray);
+ }
+ }
+
+ [Fact]
+ public void IsVariableBoundArray_FalseForNonArrayByRefType()
+ {
+ Assert.False(typeof(int).MakeByRefType().IsVariableBoundArray);
+ }
+
+ [Fact]
+ public void IsVariableBoundArray_FalseForByRefSZArrayType()
+ {
+ Assert.False(typeof(int[]).MakeByRefType().IsVariableBoundArray);
+ }
+
+
+ [Fact]
+ public void IsVariableBoundArray_FalseForByRefVariableArrayType()
+ {
+ Assert.False(typeof(int[,]).MakeByRefType().IsVariableBoundArray);
+ }
+
+ [Theory]
+ [MemberData(nameof(DefinedTypes))]
+ public void IsTypeDefinition_True(Type type)
+ {
+ Assert.True(type.IsTypeDefinition);
+ }
+
+ [Theory]
+ [MemberData(nameof(NotDefinedTypes))]
+ public void IsTypeDefinition_False(Type type)
+ {
+ Assert.False(type.IsTypeDefinition);
+ }
+
+ // In the unlikely event we ever add new values to the CorElementType enumeration, CoreCLR will probably miss it because of the way IsTypeDefinition
+ // works. It's likely that such a type will live in the core assembly so to improve our chances of catching this situation, test IsTypeDefinition
+ // on every type exposed out of that assembly.
+ //
+ // Skipping this on .NET Native because:
+ // - We really don't want to opt in all the metadata in System.Private.CoreLib
+ // - The .NET Native implementation of IsTypeDefinition is not the one that works by enumerating selected values off CorElementType.
+ // It has much less need of a test like this.
+ [Fact]
+ public void IsTypeDefinition_AllDefinedTypesInCoreAssembly()
+ {
+ foreach (Type type in typeof(object).Assembly.DefinedTypes)
+ {
+ Assert.True(type.IsTypeDefinition, "IsTypeDefinition expected to be true for type " + type);
+ }
+ }
+
+ public static IEnumerable<object[]> DefinedTypes
+ {
+ get
+ {
+ yield return new object[] { typeof(void) };
+ yield return new object[] { typeof(int) };
+ yield return new object[] { typeof(Outside) };
+ yield return new object[] { typeof(Outside.Inside) };
+ yield return new object[] { typeof(Outside<>) };
+ yield return new object[] { typeof(IEnumerable<>) };
+ yield return new object[] { 3.GetType().GetType() }; // This yields a reflection-blocked type on .NET Native - which is implemented separately
+
+ if (PlatformDetection.IsWindows)
+ yield return new object[] { Type.GetTypeFromCLSID(default(Guid)) };
+ }
+ }
+
+ public static IEnumerable<object[]> NotDefinedTypes
+ {
+ get
+ {
+ Type theT = typeof(Outside<>).GetTypeInfo().GenericTypeParameters[0];
+
+ yield return new object[] { typeof(int[]) };
+ yield return new object[] { theT.MakeArrayType(1) }; // Using an open type as element type gets around .NET Native nonsupport of rank-1 multidim arrays
+ yield return new object[] { typeof(int[,]) };
+
+ yield return new object[] { typeof(int).MakeByRefType() };
+
+ yield return new object[] { typeof(int).MakePointerType() };
+
+ yield return new object[] { typeof(Outside<int>) };
+ yield return new object[] { typeof(Outside<int>.Inside<int>) };
+
+ yield return new object[] { theT };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(IsByRefLikeTestData))]
+ public static void TestIsByRefLike(Type type, bool expected)
+ {
+ Assert.Equal(expected, type.IsByRefLike);
+ }
+
+ public static IEnumerable<object[]> IsByRefLikeTestData
+ {
+ get
+ {
+ Type theT = typeof(Outside<>).GetTypeInfo().GenericTypeParameters[0];
+
+ yield return new object[] { typeof(ArgIterator), true };
+ yield return new object[] { typeof(ByRefLikeStruct), true };
+ yield return new object[] { typeof(RegularStruct), false };
+ yield return new object[] { typeof(RuntimeArgumentHandle), true };
+ yield return new object[] { typeof(Span<>), true };
+ yield return new object[] { typeof(Span<>).MakeGenericType(theT), true };
+ yield return new object[] { typeof(Span<int>), true };
+ yield return new object[] { typeof(Span<int>).MakeByRefType(), false };
+ yield return new object[] { typeof(Span<int>).MakePointerType(), false };
+ yield return new object[] { typeof(TypedReference), true };
+ yield return new object[] { theT, false };
+ yield return new object[] { typeof(int[]), false };
+ yield return new object[] { typeof(int[,]), false };
+ yield return new object[] { typeof(object), false };
+ if (PlatformDetection.IsWindows) // GetTypeFromCLSID is Windows only
+ {
+ yield return new object[] { Type.GetTypeFromCLSID(default(Guid)), false };
+ }
+ }
+ }
+
+ private ref struct ByRefLikeStruct
+ {
+ public ByRefLikeStruct(int dummy)
+ {
+ S = default(Span<int>);
+ }
+
+ public Span<int> S;
+ }
+
+ private struct RegularStruct
+ {
+ }
+
+ [Theory]
+ [MemberData(nameof(IsGenericParameterTestData))]
+ public static void TestIsGenericParameter(Type type, bool isGenericParameter, bool isGenericTypeParameter, bool isGenericMethodParameter)
+ {
+ Assert.Equal(isGenericParameter, type.IsGenericParameter);
+ Assert.Equal(isGenericTypeParameter, type.IsGenericTypeParameter);
+ Assert.Equal(isGenericMethodParameter, type.IsGenericMethodParameter);
+ }
+
+ public static IEnumerable<object[]> IsGenericParameterTestData
+ {
+ get
+ {
+ yield return new object[] { typeof(void), false, false, false };
+ yield return new object[] { typeof(int), false, false, false };
+ yield return new object[] { typeof(int[]), false, false, false };
+ yield return new object[] { typeof(int).MakeArrayType(1), false, false, false };
+ yield return new object[] { typeof(int[,]), false, false, false };
+ yield return new object[] { typeof(int).MakeByRefType(), false, false, false };
+ yield return new object[] { typeof(int).MakePointerType(), false, false, false };
+ yield return new object[] { typeof(DummyGenericClassForTypeTests<>), false, false, false };
+ yield return new object[] { typeof(DummyGenericClassForTypeTests<int>), false, false, false };
+ if (PlatformDetection.IsWindows) // GetTypeFromCLSID is Windows only
+ {
+ yield return new object[] { Type.GetTypeFromCLSID(default(Guid)), false, false, false };
+ }
+
+ Type theT = typeof(Outside<>).GetTypeInfo().GenericTypeParameters[0];
+ yield return new object[] { theT, true, true, false };
+
+ Type theM = typeof(TypeTests).GetMethod(nameof(GenericMethod), BindingFlags.NonPublic | BindingFlags.Static).GetGenericArguments()[0];
+ yield return new object[] { theM, true, false, true };
+ }
+ }
+
+ private static void GenericMethod<M>() { }
}
public class TypeTestsExtended {
public interface GenericInterface<T> { }
public interface GenericInterface<T, U> { }
}
+
+internal class DummyGenericClassForTypeTests<T> { }
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using Xunit;
-
-namespace System.Tests
-{
- public class TypeTestsNetcore
- {
- private static readonly IList<Type> NonArrayBaseTypes;
-
- static TypeTestsNetcore()
- {
- NonArrayBaseTypes = new List<Type>()
- {
- typeof(int),
- typeof(void),
- typeof(int*),
- typeof(Outside),
- typeof(Outside<int>),
- typeof(Outside<>).GetTypeInfo().GenericTypeParameters[0],
- new object().GetType().GetType()
- };
-
- if (PlatformDetection.IsWindows)
- {
- NonArrayBaseTypes.Add(Type.GetTypeFromCLSID(default(Guid)));
- }
- }
-
- [Fact]
- public void IsSZArray_FalseForNonArrayTypes()
- {
- foreach (Type type in NonArrayBaseTypes)
- {
- Assert.False(type.IsSZArray);
- }
- }
-
- [Fact]
- public void IsSZArray_TrueForSZArrayTypes()
- {
- foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType()))
- {
- Assert.True(type.IsSZArray);
- }
- }
-
- [Fact]
- public void IsSZArray_FalseForVariableBoundArrayTypes()
- {
- foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType(1)))
- {
- Assert.False(type.IsSZArray);
- }
-
- foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType(2)))
- {
- Assert.False(type.IsSZArray);
- }
- }
-
- [Fact]
- public void IsSZArray_FalseForNonArrayByRefType()
- {
- Assert.False(typeof(int).MakeByRefType().IsSZArray);
- }
-
- [Fact]
- public void IsSZArray_FalseForByRefSZArrayType()
- {
- Assert.False(typeof(int[]).MakeByRefType().IsSZArray);
- }
-
-
- [Fact]
- public void IsSZArray_FalseForByRefVariableArrayType()
- {
- Assert.False(typeof(int[,]).MakeByRefType().IsSZArray);
- }
-
- [Fact]
- public void IsVariableBoundArray_FalseForNonArrayTypes()
- {
- foreach (Type type in NonArrayBaseTypes)
- {
- Assert.False(type.IsVariableBoundArray);
- }
- }
-
- [Fact]
- public void IsVariableBoundArray_FalseForSZArrayTypes()
- {
- foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType()))
- {
- Assert.False(type.IsVariableBoundArray);
- }
- }
-
- [Fact]
- public void IsVariableBoundArray_TrueForVariableBoundArrayTypes()
- {
- foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType(1)))
- {
- Assert.True(type.IsVariableBoundArray);
- }
-
- foreach (Type type in NonArrayBaseTypes.Select(nonArrayBaseType => nonArrayBaseType.MakeArrayType(2)))
- {
- Assert.True(type.IsVariableBoundArray);
- }
- }
-
- [Fact]
- public void IsVariableBoundArray_FalseForNonArrayByRefType()
- {
- Assert.False(typeof(int).MakeByRefType().IsVariableBoundArray);
- }
-
- [Fact]
- public void IsVariableBoundArray_FalseForByRefSZArrayType()
- {
- Assert.False(typeof(int[]).MakeByRefType().IsVariableBoundArray);
- }
-
-
- [Fact]
- public void IsVariableBoundArray_FalseForByRefVariableArrayType()
- {
- Assert.False(typeof(int[,]).MakeByRefType().IsVariableBoundArray);
- }
-
- [Theory]
- [MemberData(nameof(DefinedTypes))]
- public void IsTypeDefinition_True(Type type)
- {
- Assert.True(type.IsTypeDefinition);
- }
-
- [Theory]
- [MemberData(nameof(NotDefinedTypes))]
- public void IsTypeDefinition_False(Type type)
- {
- Assert.False(type.IsTypeDefinition);
- }
-
- // In the unlikely event we ever add new values to the CorElementType enumeration, CoreCLR will probably miss it because of the way IsTypeDefinition
- // works. It's likely that such a type will live in the core assembly so to improve our chances of catching this situation, test IsTypeDefinition
- // on every type exposed out of that assembly.
- //
- // Skipping this on .NET Native because:
- // - We really don't want to opt in all the metadata in System.Private.CoreLib
- // - The .NET Native implementation of IsTypeDefinition is not the one that works by enumerating selected values off CorElementType.
- // It has much less need of a test like this.
- [Fact]
- public void IsTypeDefinition_AllDefinedTypesInCoreAssembly()
- {
- foreach (Type type in typeof(object).Assembly.DefinedTypes)
- {
- Assert.True(type.IsTypeDefinition, "IsTypeDefinition expected to be true for type " + type);
- }
- }
-
- public static IEnumerable<object[]> DefinedTypes
- {
- get
- {
- yield return new object[] { typeof(void) };
- yield return new object[] { typeof(int) };
- yield return new object[] { typeof(Outside) };
- yield return new object[] { typeof(Outside.Inside) };
- yield return new object[] { typeof(Outside<>) };
- yield return new object[] { typeof(IEnumerable<>) };
- yield return new object[] { 3.GetType().GetType() }; // This yields a reflection-blocked type on .NET Native - which is implemented separately
-
- if (PlatformDetection.IsWindows)
- yield return new object[] { Type.GetTypeFromCLSID(default(Guid)) };
- }
- }
-
- public static IEnumerable<object[]> NotDefinedTypes
- {
- get
- {
- Type theT = typeof(Outside<>).GetTypeInfo().GenericTypeParameters[0];
-
- yield return new object[] { typeof(int[]) };
- yield return new object[] { theT.MakeArrayType(1) }; // Using an open type as element type gets around .NET Native nonsupport of rank-1 multidim arrays
- yield return new object[] { typeof(int[,]) };
-
- yield return new object[] { typeof(int).MakeByRefType() };
-
- yield return new object[] { typeof(int).MakePointerType() };
-
- yield return new object[] { typeof(Outside<int>) };
- yield return new object[] { typeof(Outside<int>.Inside<int>) };
-
- yield return new object[] { theT };
- }
- }
-
- [Theory]
- [MemberData(nameof(IsByRefLikeTestData))]
- public static void TestIsByRefLike(Type type, bool expected)
- {
- Assert.Equal(expected, type.IsByRefLike);
- }
-
- public static IEnumerable<object[]> IsByRefLikeTestData
- {
- get
- {
- Type theT = typeof(Outside<>).GetTypeInfo().GenericTypeParameters[0];
-
- yield return new object[] { typeof(ArgIterator), true };
- yield return new object[] { typeof(ByRefLikeStruct), true };
- yield return new object[] { typeof(RegularStruct), false };
- yield return new object[] { typeof(RuntimeArgumentHandle), true };
- yield return new object[] { typeof(Span<>), true };
- yield return new object[] { typeof(Span<>).MakeGenericType(theT), true };
- yield return new object[] { typeof(Span<int>), true };
- yield return new object[] { typeof(Span<int>).MakeByRefType(), false };
- yield return new object[] { typeof(Span<int>).MakePointerType(), false };
- yield return new object[] { typeof(TypedReference), true };
- yield return new object[] { theT, false };
- yield return new object[] { typeof(int[]), false };
- yield return new object[] { typeof(int[,]), false };
- yield return new object[] { typeof(object), false };
- if (PlatformDetection.IsWindows) // GetTypeFromCLSID is Windows only
- {
- yield return new object[] { Type.GetTypeFromCLSID(default(Guid)), false };
- }
- }
- }
-
- private ref struct ByRefLikeStruct
- {
- public ByRefLikeStruct(int dummy)
- {
- S = default(Span<int>);
- }
-
- public Span<int> S;
- }
-
- private struct RegularStruct
- {
- }
-
- [Theory]
- [MemberData(nameof(IsGenericParameterTestData))]
- public static void TestIsGenericParameter(Type type, bool isGenericParameter, bool isGenericTypeParameter, bool isGenericMethodParameter)
- {
- Assert.Equal(isGenericParameter, type.IsGenericParameter);
- Assert.Equal(isGenericTypeParameter, type.IsGenericTypeParameter);
- Assert.Equal(isGenericMethodParameter, type.IsGenericMethodParameter);
- }
-
- public static IEnumerable<object[]> IsGenericParameterTestData
- {
- get
- {
- yield return new object[] { typeof(void), false, false, false };
- yield return new object[] { typeof(int), false, false, false };
- yield return new object[] { typeof(int[]), false, false, false };
- yield return new object[] { typeof(int).MakeArrayType(1), false, false, false };
- yield return new object[] { typeof(int[,]), false, false, false };
- yield return new object[] { typeof(int).MakeByRefType(), false, false, false };
- yield return new object[] { typeof(int).MakePointerType(), false, false, false };
- yield return new object[] { typeof(DummyGenericClassForTypeTestsNetcore<>), false, false, false };
- yield return new object[] { typeof(DummyGenericClassForTypeTestsNetcore<int>), false, false, false };
- if (PlatformDetection.IsWindows) // GetTypeFromCLSID is Windows only
- {
- yield return new object[] { Type.GetTypeFromCLSID(default(Guid)), false, false, false };
- }
-
- Type theT = typeof(Outside<>).GetTypeInfo().GenericTypeParameters[0];
- yield return new object[] { theT, true, true, false };
-
- Type theM = typeof(TypeTestsNetcore).GetMethod(nameof(GenericMethod), BindingFlags.NonPublic | BindingFlags.Static).GetGenericArguments()[0];
- yield return new object[] { theM, true, false, true };
- }
- }
-
- private static void GenericMethod<M>() { }
- }
-}
-
-internal class DummyGenericClassForTypeTestsNetcore<T> { }
namespace System.Tests
{
- public partial class UInt16Tests
+ public class UInt16Tests
{
[Fact]
public static void Ctor_Empty()
AssertExtensions.Throws<ArgumentException>(paramName, () => ushort.Parse("1", style));
AssertExtensions.Throws<ArgumentException>(paramName, () => ushort.Parse("1", style, null));
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ yield return new object[] { "123", 0, 2, NumberStyles.Integer, null, (ushort)12 };
+ yield return new object[] { "123", 1, 2, NumberStyles.Integer, null, (ushort)23 };
+ yield return new object[] { "+123", 0, 2, NumberStyles.Integer, null, (ushort)1 };
+ yield return new object[] { "+123", 1, 3, NumberStyles.Integer, null, (ushort)123 };
+ yield return new object[] { "AJK", 0, 1, NumberStyles.HexNumber, new NumberFormatInfo(), (ushort)0XA };
+ yield return new object[] { "$1,000", 0, 2, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (ushort)1 };
+ yield return new object[] { "$1,000", 1, 3, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (ushort)10 };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, ushort expected)
+ {
+ ushort result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.True(ushort.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+ }
+
+ Assert.Equal(expected, ushort.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(ushort.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ ushort result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.False(ushort.TryParse(value.AsSpan(), out result));
+ Assert.Equal(0u, result);
+ }
+
+ Assert.Throws(exceptionType, () => ushort.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(ushort.TryParse(value.AsSpan(), style, provider, out result));
+ Assert.Equal(0u, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat(ushort i, string format, IFormatProvider provider, string expected)
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual));
+
+ // Longer than needed
+ actual = new char[expected.Length + 1];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (expected.Length > 0)
+ {
+ actual = new char[expected.Length - 1];
+ Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(0, charsWritten);
+ }
+
+ if (format != null)
+ {
+ // Upper format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToUpperInvariant(), new string(actual));
+
+ // Lower format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToLowerInvariant(), new string(actual));
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class UInt16Tests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- yield return new object[] { "123", 0, 2, NumberStyles.Integer, null, (ushort)12 };
- yield return new object[] { "123", 1, 2, NumberStyles.Integer, null, (ushort)23 };
- yield return new object[] { "+123", 0, 2, NumberStyles.Integer, null, (ushort)1 };
- yield return new object[] { "+123", 1, 3, NumberStyles.Integer, null, (ushort)123 };
- yield return new object[] { "AJK", 0, 1, NumberStyles.HexNumber, new NumberFormatInfo(), (ushort)0XA };
- yield return new object[] { "$1,000", 0, 2, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (ushort)1 };
- yield return new object[] { "$1,000", 1, 3, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (ushort)10 };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, ushort expected)
- {
- ushort result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.True(ushort.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
- }
-
- Assert.Equal(expected, ushort.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(ushort.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- ushort result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.False(ushort.TryParse(value.AsSpan(), out result));
- Assert.Equal(0u, result);
- }
-
- Assert.Throws(exceptionType, () => ushort.Parse(value.AsSpan(), style, provider));
-
- Assert.False(ushort.TryParse(value.AsSpan(), style, provider, out result));
- Assert.Equal(0u, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat(ushort i, string format, IFormatProvider provider, string expected)
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual));
-
- // Longer than needed
- actual = new char[expected.Length + 1];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual, 0, charsWritten));
-
- // Too short
- if (expected.Length > 0)
- {
- actual = new char[expected.Length - 1];
- Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(0, charsWritten);
- }
-
- if (format != null)
- {
- // Upper format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToUpperInvariant(), new string(actual));
-
- // Lower format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToLowerInvariant(), new string(actual));
- }
- }
- }
-}
namespace System.Tests
{
- public partial class UInt32Tests
+ public class UInt32Tests
{
[Fact]
public static void Ctor_Empty()
AssertExtensions.Throws<ArgumentException>(paramName, () => uint.Parse("1", style));
AssertExtensions.Throws<ArgumentException>(paramName, () => uint.Parse("1", style, null));
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ yield return new object[] { "123", 0, 2, NumberStyles.Integer, null, (uint)12 };
+ yield return new object[] { "123", 1, 2, NumberStyles.Integer, null, (uint)23 };
+ yield return new object[] { "4294967295", 0, 1, NumberStyles.Integer, null, 4 };
+ yield return new object[] { "4294967295", 9, 1, NumberStyles.Integer, null, 5 };
+ yield return new object[] { "12", 0, 1, NumberStyles.HexNumber, null, (uint)0x1 };
+ yield return new object[] { "12", 1, 1, NumberStyles.HexNumber, null, (uint)0x2 };
+ yield return new object[] { "$1,000", 1, 3, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (uint)10 };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, uint expected)
+ {
+ uint result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.True(uint.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+ }
+
+ Assert.Equal(expected, uint.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(uint.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ uint result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.False(uint.TryParse(value.AsSpan(), out result));
+ Assert.Equal(0u, result);
+ }
+
+ Assert.Throws(exceptionType, () => uint.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(uint.TryParse(value.AsSpan(), style, provider, out result));
+ Assert.Equal(0u, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat(uint i, string format, IFormatProvider provider, string expected)
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual));
+
+ // Longer than needed
+ actual = new char[expected.Length + 1];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (expected.Length > 0)
+ {
+ actual = new char[expected.Length - 1];
+ Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(0, charsWritten);
+ }
+
+ if (format != null)
+ {
+ // Upper format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToUpperInvariant(), new string(actual));
+
+ // Lower format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToLowerInvariant(), new string(actual));
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class UInt32Tests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- yield return new object[] { "123", 0, 2, NumberStyles.Integer, null, (uint)12 };
- yield return new object[] { "123", 1, 2, NumberStyles.Integer, null, (uint)23 };
- yield return new object[] { "4294967295", 0, 1, NumberStyles.Integer, null, 4 };
- yield return new object[] { "4294967295", 9, 1, NumberStyles.Integer, null, 5 };
- yield return new object[] { "12", 0, 1, NumberStyles.HexNumber, null, (uint)0x1 };
- yield return new object[] { "12", 1, 1, NumberStyles.HexNumber, null, (uint)0x2 };
- yield return new object[] { "$1,000", 1, 3, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (uint)10 };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, uint expected)
- {
- uint result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.True(uint.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
- }
-
- Assert.Equal(expected, uint.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(uint.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- uint result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.False(uint.TryParse(value.AsSpan(), out result));
- Assert.Equal(0u, result);
- }
-
- Assert.Throws(exceptionType, () => uint.Parse(value.AsSpan(), style, provider));
-
- Assert.False(uint.TryParse(value.AsSpan(), style, provider, out result));
- Assert.Equal(0u, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat(uint i, string format, IFormatProvider provider, string expected)
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual));
-
- // Longer than needed
- actual = new char[expected.Length + 1];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual, 0, charsWritten));
-
- // Too short
- if (expected.Length > 0)
- {
- actual = new char[expected.Length - 1];
- Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(0, charsWritten);
- }
-
- if (format != null)
- {
- // Upper format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToUpperInvariant(), new string(actual));
-
- // Lower format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToLowerInvariant(), new string(actual));
- }
- }
- }
-}
namespace System.Tests
{
- public partial class UInt64Tests
+ public class UInt64Tests
{
[Fact]
public static void Ctor_Empty()
AssertExtensions.Throws<ArgumentException>(paramName, () => ulong.Parse("1", style));
AssertExtensions.Throws<ArgumentException>(paramName, () => ulong.Parse("1", style, null));
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
+ }
+
+ yield return new object[] { "+123", 1, 3, NumberStyles.Integer, null, (ulong)123 };
+ yield return new object[] { "+123", 0, 3, NumberStyles.Integer, null, (ulong)12 };
+ yield return new object[] { " 123 ", 1, 2, NumberStyles.Integer, null, (ulong)1 };
+ yield return new object[] { "12", 0, 1, NumberStyles.HexNumber, null, (ulong)0x1 };
+ yield return new object[] { "ABC", 1, 1, NumberStyles.HexNumber, null, (ulong)0xb };
+ yield return new object[] { "$1,000", 1, 3, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (ulong)10 };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, ulong expected)
+ {
+ ulong result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.True(ulong.TryParse(value.AsSpan(offset, count), out result));
+ Assert.Equal(expected, result);
+ }
+
+ Assert.Equal(expected, ulong.Parse(value.AsSpan(offset, count), style, provider));
+
+ Assert.True(ulong.TryParse(value.AsSpan(offset, count), style, provider, out result));
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
+ {
+ if (value != null)
+ {
+ ulong result;
+
+ // Default style and provider
+ if (style == NumberStyles.Integer && provider == null)
+ {
+ Assert.False(ulong.TryParse(value.AsSpan(), out result));
+ Assert.Equal(0u, result);
+ }
+
+ Assert.Throws(exceptionType, () => ulong.Parse(value.AsSpan(), style, provider));
+
+ Assert.False(ulong.TryParse(value.AsSpan(), style, provider, out result));
+ Assert.Equal(0u, result);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat(ulong i, string format, IFormatProvider provider, string expected)
+ {
+ char[] actual;
+ int charsWritten;
+
+ // Just right
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual));
+
+ // Longer than needed
+ actual = new char[expected.Length + 1];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected, new string(actual, 0, charsWritten));
+
+ // Too short
+ if (expected.Length > 0)
+ {
+ actual = new char[expected.Length - 1];
+ Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
+ Assert.Equal(0, charsWritten);
+ }
+
+ if (format != null)
+ {
+ // Upper format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToUpperInvariant(), new string(actual));
+
+ // Lower format
+ actual = new char[expected.Length];
+ Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
+ Assert.Equal(expected.Length, charsWritten);
+ Assert.Equal(expected.ToLowerInvariant(), new string(actual));
+ }
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using System.Globalization;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class UInt64Tests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1], inputs[2], inputs[3] };
- }
-
- yield return new object[] { "+123", 1, 3, NumberStyles.Integer, null, (ulong)123 };
- yield return new object[] { "+123", 0, 3, NumberStyles.Integer, null, (ulong)12 };
- yield return new object[] { " 123 ", 1, 2, NumberStyles.Integer, null, (ulong)1 };
- yield return new object[] { "12", 0, 1, NumberStyles.HexNumber, null, (ulong)0x1 };
- yield return new object[] { "ABC", 1, 1, NumberStyles.HexNumber, null, (ulong)0xb };
- yield return new object[] { "$1,000", 1, 3, NumberStyles.Currency, new NumberFormatInfo() { CurrencySymbol = "$" }, (ulong)10 };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_Valid(string value, int offset, int count, NumberStyles style, IFormatProvider provider, ulong expected)
- {
- ulong result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.True(ulong.TryParse(value.AsSpan(offset, count), out result));
- Assert.Equal(expected, result);
- }
-
- Assert.Equal(expected, ulong.Parse(value.AsSpan(offset, count), style, provider));
-
- Assert.True(ulong.TryParse(value.AsSpan(offset, count), style, provider, out result));
- Assert.Equal(expected, result);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_Invalid(string value, NumberStyles style, IFormatProvider provider, Type exceptionType)
- {
- if (value != null)
- {
- ulong result;
-
- // Default style and provider
- if (style == NumberStyles.Integer && provider == null)
- {
- Assert.False(ulong.TryParse(value.AsSpan(), out result));
- Assert.Equal(0u, result);
- }
-
- Assert.Throws(exceptionType, () => ulong.Parse(value.AsSpan(), style, provider));
-
- Assert.False(ulong.TryParse(value.AsSpan(), style, provider, out result));
- Assert.Equal(0u, result);
- }
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat(ulong i, string format, IFormatProvider provider, string expected)
- {
- char[] actual;
- int charsWritten;
-
- // Just right
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual));
-
- // Longer than needed
- actual = new char[expected.Length + 1];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected, new string(actual, 0, charsWritten));
-
- // Too short
- if (expected.Length > 0)
- {
- actual = new char[expected.Length - 1];
- Assert.False(i.TryFormat(actual.AsSpan(), out charsWritten, format, provider));
- Assert.Equal(0, charsWritten);
- }
-
- if (format != null)
- {
- // Upper format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToUpperInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToUpperInvariant(), new string(actual));
-
- // Lower format
- actual = new char[expected.Length];
- Assert.True(i.TryFormat(actual.AsSpan(), out charsWritten, format.ToLowerInvariant(), provider));
- Assert.Equal(expected.Length, charsWritten);
- Assert.Equal(expected.ToLowerInvariant(), new string(actual));
- }
- }
- }
-}
namespace System.Tests
{
- public static partial class UIntPtrTests
+ public static class UIntPtrTests
{
private static unsafe bool Is64Bit => sizeof(void*) == 8;
Assert.Equal(expected, ptr1 == ptr2);
Assert.Equal(!expected, ptr1 != ptr2);
Assert.Equal(expected, ptr1.GetHashCode().Equals(ptr2.GetHashCode()));
+
+ IEquatable<UIntPtr> iEquatable = ptr1;
+ Assert.Equal(expected, iEquatable.Equals((UIntPtr)obj));
}
Assert.Equal(expected, ptr1.Equals(obj));
Assert.Equal(ptr1.GetHashCode(), ptr1.GetHashCode());
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections.Generic;
-using Xunit;
-
-namespace System.Tests
-{
- public static partial class UIntPtrTests
- {
- [Theory]
- [MemberData(nameof(Equals_TestData))]
- public static void Equals_NetCoreApp11(UIntPtr ptr, object obj, bool expected)
- {
- if (!(obj is UIntPtr))
- {
- return;
- }
-
- IEquatable<UIntPtr> iEquatable = ptr;
- Assert.Equal(expected, iEquatable.Equals((UIntPtr)obj));
- }
- }
-}
namespace System.Tests
{
- public partial class VersionTests
+ public class VersionTests
{
[Fact]
public void Ctor_Default()
Assert.Equal(version.Build, clone.Build);
Assert.Equal(version.Revision, clone.Revision);
}
+
+ public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
+ {
+ foreach (object[] inputs in Parse_Valid_TestData())
+ {
+ yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1] };
+ }
+
+ yield return new object[] { "1.2.3", 0, 3, new Version(1, 2) };
+ yield return new object[] { "1.2.3", 2, 3, new Version(2, 3) };
+ yield return new object[] { "2 .3. 4. \t\r\n15 ", 0, 11, new Version(2, 3, 4) };
+ yield return new object[] { "+1.+2.+3.+4", 3, 5, new Version(2, 3) };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
+ public static void Parse_Span_ValidInput_ReturnsExpected(string input, int offset, int count, Version expected)
+ {
+ if (input == null)
+ {
+ return;
+ }
+
+ Assert.Equal(expected, Version.Parse(input.AsSpan(offset, count)));
+
+ Assert.True(Version.TryParse(input.AsSpan(offset, count), out Version version));
+ Assert.Equal(expected, version);
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_Invalid_TestData))]
+ public static void Parse_Span_InvalidInput_ThrowsException(string input, Type exceptionType)
+ {
+ if (input == null)
+ {
+ return;
+ }
+
+ Assert.Throws(exceptionType, () => Version.Parse(input.AsSpan()));
+
+ Assert.False(Version.TryParse(input.AsSpan(), out Version version));
+ Assert.Null(version);
+ }
+
+ [Theory]
+ [MemberData(nameof(ToString_TestData))]
+ public static void TryFormat_Invoke_WritesExpected(Version version, string[] expected)
+ {
+ char[] dest;
+ int charsWritten;
+
+ for (int i = 0; i < expected.Length; i++)
+ {
+ if (i > 0)
+ {
+ // Too small
+ dest = new char[expected[i].Length - 1];
+ Assert.False(version.TryFormat(dest, i, out charsWritten));
+ Assert.Equal(0, charsWritten);
+ }
+
+ // Just right
+ dest = new char[expected[i].Length];
+ Assert.True(version.TryFormat(dest, i, out charsWritten));
+ Assert.Equal(expected[i].Length, charsWritten);
+ Assert.Equal(expected[i], new string(dest, 0, charsWritten));
+
+ // More than needed
+ dest = new char[expected[i].Length + 10];
+ Assert.True(version.TryFormat(dest, i, out charsWritten));
+ Assert.Equal(expected[i].Length, charsWritten);
+ Assert.Equal(expected[i], new string(dest, 0, charsWritten));
+ }
+
+ int maxFieldCount = expected.Length - 1;
+ dest = new char[expected[maxFieldCount].Length];
+ Assert.True(version.TryFormat(dest, out charsWritten));
+ Assert.Equal(expected[maxFieldCount].Length, charsWritten);
+ Assert.Equal(expected[maxFieldCount], new string(dest, 0, charsWritten));
+
+ dest = new char[0];
+ AssertExtensions.Throws<ArgumentException>("fieldCount", () => version.TryFormat(dest, -1, out charsWritten)); // Index < 0
+ AssertExtensions.Throws<ArgumentException>("fieldCount", () => version.TryFormat(dest, maxFieldCount + 1, out charsWritten)); // Index > version.fieldCount
+ }
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Collections.Generic;
-using Xunit;
-
-namespace System.Tests
-{
- public partial class VersionTests
- {
- public static IEnumerable<object[]> Parse_ValidWithOffsetCount_TestData()
- {
- foreach (object[] inputs in Parse_Valid_TestData())
- {
- yield return new object[] { inputs[0], 0, ((string)inputs[0]).Length, inputs[1] };
- }
-
- yield return new object[] { "1.2.3", 0, 3, new Version(1, 2) };
- yield return new object[] { "1.2.3", 2, 3, new Version(2, 3) };
- yield return new object[] { "2 .3. 4. \t\r\n15 ", 0, 11, new Version(2, 3, 4) };
- yield return new object[] { "+1.+2.+3.+4", 3, 5, new Version(2, 3) };
- }
-
- [Theory]
- [MemberData(nameof(Parse_ValidWithOffsetCount_TestData))]
- public static void Parse_Span_ValidInput_ReturnsExpected(string input, int offset, int count, Version expected)
- {
- if (input == null)
- {
- return;
- }
-
- Assert.Equal(expected, Version.Parse(input.AsSpan(offset, count)));
-
- Assert.True(Version.TryParse(input.AsSpan(offset, count), out Version version));
- Assert.Equal(expected, version);
- }
-
- [Theory]
- [MemberData(nameof(Parse_Invalid_TestData))]
- public static void Parse_Span_InvalidInput_ThrowsException(string input, Type exceptionType)
- {
- if (input == null)
- {
- return;
- }
-
- Assert.Throws(exceptionType, () => Version.Parse(input.AsSpan()));
-
- Assert.False(Version.TryParse(input.AsSpan(), out Version version));
- Assert.Null(version);
- }
-
- [Theory]
- [MemberData(nameof(ToString_TestData))]
- public static void TryFormat_Invoke_WritesExpected(Version version, string[] expected)
- {
- char[] dest;
- int charsWritten;
-
- for (int i = 0; i < expected.Length; i++)
- {
- if (i > 0)
- {
- // Too small
- dest = new char[expected[i].Length - 1];
- Assert.False(version.TryFormat(dest, i, out charsWritten));
- Assert.Equal(0, charsWritten);
- }
-
- // Just right
- dest = new char[expected[i].Length];
- Assert.True(version.TryFormat(dest, i, out charsWritten));
- Assert.Equal(expected[i].Length, charsWritten);
- Assert.Equal(expected[i], new string(dest, 0, charsWritten));
-
- // More than needed
- dest = new char[expected[i].Length + 10];
- Assert.True(version.TryFormat(dest, i, out charsWritten));
- Assert.Equal(expected[i].Length, charsWritten);
- Assert.Equal(expected[i], new string(dest, 0, charsWritten));
- }
-
- int maxFieldCount = expected.Length - 1;
- dest = new char[expected[maxFieldCount].Length];
- Assert.True(version.TryFormat(dest, out charsWritten));
- Assert.Equal(expected[maxFieldCount].Length, charsWritten);
- Assert.Equal(expected[maxFieldCount], new string(dest, 0, charsWritten));
-
- dest = new char[0];
- AssertExtensions.Throws<ArgumentException>("fieldCount", () => version.TryFormat(dest, -1, out charsWritten)); // Index < 0
- AssertExtensions.Throws<ArgumentException>("fieldCount", () => version.TryFormat(dest, maxFieldCount + 1, out charsWritten)); // Index > version.fieldCount
- }
- }
-}