Consolidate .netcoreapp.cs test files in System.Runtime (dotnet/corefx#42100)
authorRoman Marusyk <Marusyk@users.noreply.github.com>
Mon, 28 Oct 2019 03:22:40 +0000 (04:22 +0100)
committerJan Kotas <jkotas@microsoft.com>
Mon, 28 Oct 2019 03:22:40 +0000 (20:22 -0700)
* Consolidate .netcoreapp.cs files because System.Runtime project is no longer cross-compiled

Commit migrated from https://github.com/dotnet/corefx/commit/d6dac9e6a7875862b91139334c8ec620f599cd4d

117 files changed:
src/libraries/System.Runtime/tests/Helpers.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/Helpers.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj
src/libraries/System.Runtime/tests/System/ActivatorTests.cs
src/libraries/System.Runtime/tests/System/ActivatorTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/ArgIteratorTests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/ArgIteratorTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/ArraySegmentTests.cs
src/libraries/System.Runtime/tests/System/ArraySegmentTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/ArrayTests.cs
src/libraries/System.Runtime/tests/System/ArrayTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/BooleanTests.cs
src/libraries/System.Runtime/tests/System/BooleanTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/ByteTests.cs
src/libraries/System.Runtime/tests/System/ByteTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/CharTests.cs
src/libraries/System.Runtime/tests/System/CharTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Collections/Generic/KeyValuePairTests.cs
src/libraries/System.Runtime/tests/System/Collections/Generic/KeyValuePairTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.cs
src/libraries/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/DateTimeOffsetTests.cs
src/libraries/System.Runtime/tests/System/DateTimeOffsetTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/DateTimeTests.cs
src/libraries/System.Runtime/tests/System/DateTimeTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/DecimalTests.cs
src/libraries/System.Runtime/tests/System/DecimalTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/DoubleTests.cs
src/libraries/System.Runtime/tests/System/DoubleTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/EnumTests.cs
src/libraries/System.Runtime/tests/System/EnumTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/FormattableStringTests.cs
src/libraries/System.Runtime/tests/System/FormattableStringTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/GCTests.cs
src/libraries/System.Runtime/tests/System/GCTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/GuidTests.cs
src/libraries/System.Runtime/tests/System/GuidTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/HashCodeTests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/HashCodeTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Int16Tests.cs
src/libraries/System.Runtime/tests/System/Int16Tests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Int32Tests.cs
src/libraries/System.Runtime/tests/System/Int32Tests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Int64Tests.cs
src/libraries/System.Runtime/tests/System/Int64Tests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/IntPtrTests.cs
src/libraries/System.Runtime/tests/System/IntPtrTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/LazyTests.cs
src/libraries/System.Runtime/tests/System/LazyTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/RealFormatterTests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/RealFormatterTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Reflection/BindingFlagsDoNotWrap.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Reflection/BindingFlagsDoNotWrap.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Reflection/MethodBaseTests.cs
src/libraries/System.Runtime/tests/System/Reflection/MethodBaseTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Reflection/SignatureTypes.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Reflection/SignatureTypes.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Reflection/TypeDelegatorTests.cs
src/libraries/System.Runtime/tests/System/Reflection/TypeDelegatorTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.cs
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/MethodImplAttributeTests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/MethodImplAttributeTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeFeatureTests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeFeatureTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs
src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeHelpersTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Runtime/ExceptionServices/ExceptionDispatchInfoTests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Runtime/ExceptionServices/ExceptionDispatchInfoTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/SByteTests.cs
src/libraries/System.Runtime/tests/System/SByteTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/SingleTests.cs
src/libraries/System.Runtime/tests/System/SingleTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/StringComparerTests.cs
src/libraries/System.Runtime/tests/System/StringComparerTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/StringGetHashCodeTests.cs
src/libraries/System.Runtime/tests/System/StringGetHashCodeTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/StringTests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/StringTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/ASCIIUtilityTests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Text/ASCIIUtilityTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/RuneTests.TestData.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Text/RuneTests.TestData.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/RuneTests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Text/RuneTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/StringBuilderTests.cs
src/libraries/System.Runtime/tests/System/Text/StringBuilderTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/Unicode/UnicodeData.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Text/Unicode/UnicodeData.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/Unicode/Utf16UtilityTests.ValidateChars.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Text/Unicode/Utf16UtilityTests.ValidateChars.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.ToBytes.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.ToChars.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8UtilityTests.ValidateBytes.cs [new file with mode: 0644]
src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8UtilityTests.ValidateBytes.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/TimeSpanTests.cs
src/libraries/System.Runtime/tests/System/TimeSpanTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Type/TypePropertyTests.cs
src/libraries/System.Runtime/tests/System/Type/TypePropertyTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/Type/TypeTests.cs
src/libraries/System.Runtime/tests/System/Type/TypeTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/UInt16Tests.cs
src/libraries/System.Runtime/tests/System/UInt16Tests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/UInt32Tests.cs
src/libraries/System.Runtime/tests/System/UInt32Tests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/UInt64Tests.cs
src/libraries/System.Runtime/tests/System/UInt64Tests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/UIntPtrTests.cs
src/libraries/System.Runtime/tests/System/UIntPtrTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime/tests/System/VersionTests.cs
src/libraries/System.Runtime/tests/System/VersionTests.netcoreapp.cs [deleted file]

diff --git a/src/libraries/System.Runtime/tests/Helpers.cs b/src/libraries/System.Runtime/tests/Helpers.cs
new file mode 100644 (file)
index 0000000..a092d70
--- /dev/null
@@ -0,0 +1,49 @@
+// 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 System.Reflection;
+using System.Reflection.Emit;
+
+namespace System.Tests
+{
+    public static class Helpers
+    {
+        private static Type s_refEmitType;
+
+        public static IEnumerable<Type> NonRuntimeTypes
+        {
+            get
+            {
+                if (PlatformDetection.IsReflectionEmitSupported)
+                    yield return RefEmitType();
+
+                yield return new NonRuntimeType();
+            }
+        }
+
+        private static Type RefEmitType()
+        {
+            if (s_refEmitType == null)
+            {
+                AssemblyName assemblyName = new AssemblyName("AssemblyName");
+                AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
+                ModuleBuilder mboduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
+
+                TypeBuilder typeBuilder = mboduleBuilder.DefineType("TestType", TypeAttributes.Public);
+
+                GenericTypeParameterBuilder[] typeParams = typeBuilder.DefineGenericParameters("T");
+                s_refEmitType = typeParams[0].UnderlyingSystemType;
+            }
+
+            return s_refEmitType;
+        }
+
+        private sealed class NonRuntimeType : MockType
+        {
+            public sealed override Type UnderlyingSystemType => this;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/Helpers.netcoreapp.cs b/src/libraries/System.Runtime/tests/Helpers.netcoreapp.cs
deleted file mode 100644 (file)
index fcfe264..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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 System.Reflection;
-using System.Reflection.Emit;
-
-namespace System.Tests
-{
-    public static partial class Helpers
-    {
-        private static Type s_refEmitType;
-
-        public static IEnumerable<Type> NonRuntimeTypes
-        {
-            get
-            {
-                if (PlatformDetection.IsReflectionEmitSupported)
-                    yield return RefEmitType();
-
-                yield return new NonRuntimeType();
-            }
-        }
-
-        private static Type RefEmitType()
-        {
-            if (s_refEmitType == null)
-            {
-                AssemblyName assemblyName = new AssemblyName("AssemblyName");
-                AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
-                ModuleBuilder mboduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
-
-                TypeBuilder typeBuilder = mboduleBuilder.DefineType("TestType", TypeAttributes.Public);
-
-                GenericTypeParameterBuilder[] typeParams = typeBuilder.DefineGenericParameters("T");
-                s_refEmitType = typeParams[0].UnderlyingSystemType;
-            }
-
-            return s_refEmitType;
-        }
-
-        private sealed class NonRuntimeType : MockType
-        {
-            public sealed override Type UnderlyingSystemType => this;
-        }
-    }
-}
index 9cec3ded9e51483f40323433a35d5c6ec09422f1..c306add0e4785bfb57d67bc3d0eed81c601d7ffe 100644 (file)
     <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" />
@@ -91,7 +93,9 @@
     <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>
index a32ac6302d8d6f18fc68ddc01a57874957249669..27c458e32d040e985ff8c918eb05e600d911bc2b 100644 (file)
@@ -4,8 +4,13 @@
 
 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
@@ -563,5 +568,266 @@ 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]));
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/ActivatorTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/ActivatorTests.netcoreapp.cs
deleted file mode 100644 (file)
index fb2f85f..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-// 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]));
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/ArgIteratorTests.cs b/src/libraries/System.Runtime/tests/System/ArgIteratorTests.cs
new file mode 100644 (file)
index 0000000..1ad30e5
--- /dev/null
@@ -0,0 +1,109 @@
+// 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.Reflection;
+using Xunit;
+
+namespace System.Tests
+{
+    public static class ArgIteratorTests
+    {
+        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsArgIteratorSupported))]
+        public static void ArgIterator_GetRemainingCount_GetNextArg()
+        {
+            object[] result = GetAllArgs("a", "r", "g", "s", __arglist(true, "hello", 0.42));
+            Assert.Equal(new object[] {"a", "r", "g", "s", true, "hello", 0.42}, result);
+        }
+
+        private static object[] GetAllArgs(Object arg0, Object arg1, Object arg2, Object arg3, __arglist)
+        {
+            ArgIterator args = new ArgIterator(__arglist);
+            int argCount = args.GetRemainingCount() + 4;
+            object[] objArgs = new Object[argCount];
+
+            // Handle the hard-coded arguments
+            objArgs[0] = arg0;
+            objArgs[1] = arg1;
+            objArgs[2] = arg2;
+            objArgs[3] = arg3;
+
+            // Walk all of the args in the variable part of the argument list.
+            for (int i = 4; i < argCount; i++)
+            {
+                objArgs[i] = TypedReference.ToObject(args.GetNextArg());
+            }
+            args.End();
+
+            return objArgs;
+        }
+
+        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsArgIteratorSupported))]
+        public static void ArgIterator_GetNextArgType()
+        {
+            var types = new Type[]
+            {
+                typeof(string),
+                typeof(byte),
+                typeof(short),
+                typeof(long),
+                typeof(int),
+                typeof(float),
+                typeof(double),
+                typeof(DummyClass),
+                typeof(DummyStruct)
+            };
+
+            VerifyTypes(types, __arglist(
+                default(string),
+                default(byte),
+                default(short),
+                default(long),
+                default(int),
+                default(float),
+                default(double),
+                default(DummyClass),
+                default(DummyStruct)
+            ));
+        }
+
+        private class DummyClass { }
+        private struct DummyStruct { }
+
+        private static void VerifyTypes(Type[] types, __arglist)
+        {
+            ArgIterator args = new ArgIterator(__arglist);
+            int argCount = args.GetRemainingCount();
+            Assert.Equal(types.Length, argCount);
+
+            object[] objArgs = new Object[argCount];
+            for (int i = 0; i < argCount; i++)
+            {
+                RuntimeTypeHandle handle = args.GetNextArgType();
+                Type type = Type.GetTypeFromHandle(handle);
+                Assert.Equal(types[i], type);
+                args.GetNextArg(handle);
+            }
+        }
+
+        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsArgIteratorNotSupported))]
+        public static unsafe void ArgIterator_Throws_PlatformNotSupportedException()
+        {
+            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator(new RuntimeArgumentHandle()));
+            Assert.Throws<PlatformNotSupportedException>(() => {
+                fixed (void* p = "test")
+                {
+                    new ArgIterator(new RuntimeArgumentHandle(), p);
+                }
+            });
+            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().End());
+            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().Equals(new object()));
+            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetHashCode());
+            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetNextArg());
+            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetNextArg(new RuntimeTypeHandle()));
+            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetNextArgType());
+            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetRemainingCount());
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/ArgIteratorTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/ArgIteratorTests.netcoreapp.cs
deleted file mode 100644 (file)
index 1ad30e5..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-// 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.Reflection;
-using Xunit;
-
-namespace System.Tests
-{
-    public static class ArgIteratorTests
-    {
-        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsArgIteratorSupported))]
-        public static void ArgIterator_GetRemainingCount_GetNextArg()
-        {
-            object[] result = GetAllArgs("a", "r", "g", "s", __arglist(true, "hello", 0.42));
-            Assert.Equal(new object[] {"a", "r", "g", "s", true, "hello", 0.42}, result);
-        }
-
-        private static object[] GetAllArgs(Object arg0, Object arg1, Object arg2, Object arg3, __arglist)
-        {
-            ArgIterator args = new ArgIterator(__arglist);
-            int argCount = args.GetRemainingCount() + 4;
-            object[] objArgs = new Object[argCount];
-
-            // Handle the hard-coded arguments
-            objArgs[0] = arg0;
-            objArgs[1] = arg1;
-            objArgs[2] = arg2;
-            objArgs[3] = arg3;
-
-            // Walk all of the args in the variable part of the argument list.
-            for (int i = 4; i < argCount; i++)
-            {
-                objArgs[i] = TypedReference.ToObject(args.GetNextArg());
-            }
-            args.End();
-
-            return objArgs;
-        }
-
-        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsArgIteratorSupported))]
-        public static void ArgIterator_GetNextArgType()
-        {
-            var types = new Type[]
-            {
-                typeof(string),
-                typeof(byte),
-                typeof(short),
-                typeof(long),
-                typeof(int),
-                typeof(float),
-                typeof(double),
-                typeof(DummyClass),
-                typeof(DummyStruct)
-            };
-
-            VerifyTypes(types, __arglist(
-                default(string),
-                default(byte),
-                default(short),
-                default(long),
-                default(int),
-                default(float),
-                default(double),
-                default(DummyClass),
-                default(DummyStruct)
-            ));
-        }
-
-        private class DummyClass { }
-        private struct DummyStruct { }
-
-        private static void VerifyTypes(Type[] types, __arglist)
-        {
-            ArgIterator args = new ArgIterator(__arglist);
-            int argCount = args.GetRemainingCount();
-            Assert.Equal(types.Length, argCount);
-
-            object[] objArgs = new Object[argCount];
-            for (int i = 0; i < argCount; i++)
-            {
-                RuntimeTypeHandle handle = args.GetNextArgType();
-                Type type = Type.GetTypeFromHandle(handle);
-                Assert.Equal(types[i], type);
-                args.GetNextArg(handle);
-            }
-        }
-
-        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsArgIteratorNotSupported))]
-        public static unsafe void ArgIterator_Throws_PlatformNotSupportedException()
-        {
-            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator(new RuntimeArgumentHandle()));
-            Assert.Throws<PlatformNotSupportedException>(() => {
-                fixed (void* p = "test")
-                {
-                    new ArgIterator(new RuntimeArgumentHandle(), p);
-                }
-            });
-            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().End());
-            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().Equals(new object()));
-            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetHashCode());
-            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetNextArg());
-            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetNextArg(new RuntimeTypeHandle()));
-            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetNextArgType());
-            Assert.Throws<PlatformNotSupportedException>(() => new ArgIterator().GetRemainingCount());
-        }
-    }
-}
index 343e93d19e2b5df8f9c72f9b5ee7c0f7b6a83be2..986c7ca9ea7558ad1c4a02736fbc6c0ff28ff6ef 100644 (file)
@@ -88,6 +88,116 @@ namespace System.Tests
             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>
@@ -272,5 +382,352 @@ namespace System.Tests
                 (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) });
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/ArraySegmentTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/ArraySegmentTests.netcoreapp.cs
deleted file mode 100644 (file)
index 3247fd1..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
-// 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) });
-        }
-    }
-}
index 4375e6d0c453af32cc497eab8be281c4ad3acde2..bf0ef632697fa5a92e4451503f2b9e6079cd0007 100644 (file)
@@ -7,11 +7,12 @@ using System.Collections.Generic;
 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()
@@ -4064,6 +4065,188 @@ namespace System.Tests
             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);
diff --git a/src/libraries/System.Runtime/tests/System/ArrayTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/ArrayTests.netcoreapp.cs
deleted file mode 100644 (file)
index 457556f..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-// 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]));
-            }
-        }
-    }
-}
index f56c28aee7ff28fb08d3dea18a945e737f387b9d..bb6073fe3f6466e658b9fa6e7f0b36b72e0a7d42 100644 (file)
@@ -146,5 +146,68 @@ namespace System.Tests
         {
             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);
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/BooleanTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/BooleanTests.netcoreapp.cs
deleted file mode 100644 (file)
index 3d23b79..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// 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);
-            }
-        }
-    }
-}
index 570abba62569140665e442032e355835b99005d4..5522c8ef7833a1571755a13572c803586478c602 100644 (file)
@@ -8,7 +8,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class ByteTests
+    public class ByteTests
     {
         [Fact]
         public static void Ctor_Empty()
@@ -288,5 +288,106 @@ namespace System.Tests
             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));
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/ByteTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/ByteTests.netcoreapp.cs
deleted file mode 100644 (file)
index 01103fc..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-// 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));
-            }
-        }
-    }
-}
index b7a6a47436f38abbd72991c0f22017af09ea14b4..055c046a32ff76d1bbfe6be97f74f59657121c14 100644 (file)
@@ -5,11 +5,13 @@
 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)]
@@ -1106,5 +1108,159 @@ namespace System.Tests
             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."));
+                }
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/CharTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/CharTests.netcoreapp.cs
deleted file mode 100644 (file)
index 5af4344..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-// 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."));
-                }
-            }
-        }
-    }
-}
index c4bcf03576be7f67cef546dd63945ddba4b815ff..7666aebe2cc1059a9d0f5c88af87fcff587f4806 100644 (file)
@@ -6,7 +6,7 @@ using Xunit;
 
 namespace System.Collections.Generic.Tests
 {
-    public partial class KeyValuePairTests
+    public class KeyValuePairTests
     {
         [Fact]
         public void Ctor_KeyValue_ReturnsExpected()
@@ -43,5 +43,13 @@ namespace System.Collections.Generic.Tests
             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);
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Collections/Generic/KeyValuePairTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Collections/Generic/KeyValuePairTests.netcoreapp.cs
deleted file mode 100644 (file)
index 3b84d01..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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);
-        }
-    }
-}
index 19b31041ec14a7a14ea3ec49d05da1d5746aec53..038ee851f7bfe03fb441abbcb1f0793830e3703a 100644 (file)
@@ -11,7 +11,7 @@ using Xunit;
 
 namespace System.ComponentModel.Tests
 {
-    public partial class DefaultValueAttributeTests
+    public class DefaultValueAttributeTests
     {
         [Fact]
         public static void Ctor()
@@ -23,9 +23,16 @@ namespace System.ComponentModel.Tests
             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);
diff --git a/src/libraries/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/ComponentModel/DefaultValueAttributeTests.netcoreapp.cs
deleted file mode 100644 (file)
index 178de91..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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);
-        }
-    }
-}
index 7c9a42c14a6c5726d150002a7d634b6ca4aa9ce4..fef1844306c2c27b0cf24a17d18a9fb18c7e35a1 100644 (file)
@@ -10,7 +10,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public static partial class DateTimeOffsetTests
+    public static class DateTimeOffsetTests
     {
         [Fact]
         public static void MaxValue()
@@ -1275,5 +1275,98 @@ namespace System.Tests
         {
             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);
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/DateTimeOffsetTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/DateTimeOffsetTests.netcoreapp.cs
deleted file mode 100644 (file)
index c927975..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// 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);
-        }
-    }
-}
index a3901444e113769e16c6bb4594cb1ebd2df7ecea..ff8964fb1117fd198c8eb248854f090e3b311724 100644 (file)
@@ -12,7 +12,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class DateTimeTests
+    public class DateTimeTests
     {
         [Fact]
         public static void MaxValue()
@@ -2273,5 +2273,98 @@ namespace System.Tests
                 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);
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/DateTimeTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/DateTimeTests.netcoreapp.cs
deleted file mode 100644 (file)
index 13eee84..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// 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);
-        }
-    }
-}
index 8d2b8ede3165ea4f3d5ba1aec1b80519f293b7ab..f132752714c25e667392eaa2491e7beef7ef37f7 100644 (file)
@@ -12,7 +12,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class DecimalTests
+    public class DecimalTests
     {
         [Fact]
         public void MaxValue_Get_ReturnsExpected()
@@ -2179,5 +2179,127 @@ namespace System.Tests
                 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}");
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/DecimalTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/DecimalTests.netcoreapp.cs
deleted file mode 100644 (file)
index fcd5b81..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-// 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}");
-                    }
-                }
-            }
-        }
-    }
-}
index c1b4fe34e56a46ad58aad49777a3b4215ff9badd..de096f5672cb79c78088ae4fa183ca24304edd57 100644 (file)
@@ -11,7 +11,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class DoubleTests
+    public class DoubleTests
     {
         // NOTE: Consider duplicating any tests added here in SingleTests.cs
 
@@ -492,5 +492,215 @@ namespace System.Tests
             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));
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/DoubleTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/DoubleTests.netcoreapp.cs
deleted file mode 100644 (file)
index 056145b..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-// 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));
-        }
-    }
-}
index ca353e2bdeb9e867ea26109d2b38a9a342e8ca59..2d4d38511af6b67c6cdf9a99b52285d910e5dda7 100644 (file)
@@ -5,11 +5,12 @@
 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()
         {
@@ -130,12 +131,14 @@ namespace System.Tests
                 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()
@@ -226,19 +229,35 @@ namespace System.Tests
 
         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()
@@ -1589,5 +1608,155 @@ namespace System.Tests
             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();
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/EnumTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/EnumTests.netcoreapp.cs
deleted file mode 100644 (file)
index 51fd0f5..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-// 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();
-        }
-    }
-}
index d8c1a49833bf3f7933b384b975cc0421755148f3..8faa9ec1006e932caf4d1c5fd2a80829e71f064e 100644 (file)
@@ -9,7 +9,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class FormattableStringTests
+    public class FormattableStringTests
     {
         [Fact]
         public static void Invariant_Null_ThrowsArgumentNullException()
@@ -50,5 +50,32 @@ namespace System.Tests
             }
         }
 
+        [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);
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/FormattableStringTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/FormattableStringTests.netcoreapp.cs
deleted file mode 100644 (file)
index f87b454..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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);
-            }
-        }
-    }
-}
index 6ae1d76ea568560b27f095c9c63a5e775588057e..e5012845777434cb7173503bff9a7fe5a43b21db 100644 (file)
@@ -2,7 +2,9 @@
 // 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;
@@ -11,7 +13,7 @@ using Xunit;
 
 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
 
@@ -762,5 +764,130 @@ namespace System.Tests
             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);
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/GCTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/GCTests.netcoreapp.cs
deleted file mode 100644 (file)
index f2bd13a..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-// 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);
-            }
-        }
-    }
-}
index ac04a5a68bc6ded60a524cfced2096b4455e5e5a..1cd179b4e7007d3906246b1cbe0edb38bff6718b 100644 (file)
@@ -9,7 +9,7 @@ using Xunit;
 
 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);
@@ -761,5 +761,120 @@ namespace System.Tests
         {
             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);
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/GuidTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/GuidTests.netcoreapp.cs
deleted file mode 100644 (file)
index 83faf85..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-// 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);
-            }
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/HashCodeTests.cs b/src/libraries/System.Runtime/tests/System/HashCodeTests.cs
new file mode 100644 (file)
index 0000000..8564559
--- /dev/null
@@ -0,0 +1,295 @@
+// 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;
+
+public static class HashCodeTests
+{
+    [Fact]
+    public static void HashCode_Add()
+    {
+        // The version of xUnit used by corefx does not support params theories.
+        void Theory(uint expected, params uint[] vector)
+        {
+            var hc = new HashCode();
+            for (int i = 0; i < vector.Length; i++)
+                hc.Add(vector[i]);
+
+#if SYSTEM_HASHCODE_TESTVECTORS
+            // HashCode is not deterministic across AppDomains by design. This means
+            // that these tests can not be executed against the version that exists
+            // within CoreCLR. Copy HashCode and set m_seed to 0 in order to execute
+            // these tests.
+
+            Assert.Equal(expected, (uint)hc.ToHashCode());
+#else
+            // Validate that the HashCode.m_seed is randomized. This has a 1 in 4
+            // billion chance of resulting in a false negative, as HashCode.m_seed
+            // can be 0.
+
+            Assert.NotEqual(expected, (uint)hc.ToHashCode());
+#endif
+        }
+
+        // These test vectors were created using https://asecuritysite.com/encryption/xxHash
+        // 1. Find the hash for "".
+        // 2. Find the hash for "abcd". ASCII "abcd" and bit convert to uint.
+        // 3. Find the hash for "abcd1234". ASCII [ "abcd", "1234"] and bit convert to 2 uints.
+        // n. Continue until "abcd0123efgh4567ijkl8901mnop2345qrst6789uvwx0123yzab".
+
+        Theory(0x02cc5d05U);
+        Theory(0xa3643705U, 0x64636261U );
+        Theory(0x4603e94cU, 0x64636261U, 0x33323130U );
+        Theory(0xd8a1e80fU, 0x64636261U, 0x33323130U, 0x68676665U );
+        Theory(0x4b62a7cfU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U );
+        Theory(0xc33a7641U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U );
+        Theory(0x1a794705U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U );
+        Theory(0x4d79177dU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU );
+        Theory(0x59d79205U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U );
+        Theory(0x49585aaeU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U );
+        Theory(0x2f005ff1U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U, 0x39383736U );
+        Theory(0x0ce339bdU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U, 0x39383736U, 0x78777675U );
+        Theory(0xb31bd2ffU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U, 0x39383736U, 0x78777675U, 0x33323130U );
+        Theory(0xa821efa3U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U, 0x39383736U, 0x78777675U, 0x33323130U, 0x62617a79U );
+    }
+
+    [Fact]
+    public static void HashCode_Add_HashCode()
+    {
+        var hc1 = new HashCode();
+        hc1.Add("Hello");
+
+        var hc2 = new HashCode();
+        hc2.Add("Hello".GetHashCode());
+
+        Assert.Equal(hc1.ToHashCode(), hc2.ToHashCode());
+    }
+
+    [Fact]
+    public static void HashCode_Add_Generic()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add(new ConstHashCodeType());
+
+        var expected = new HashCode();
+        expected.Add(1);
+        expected.Add(ConstComparer.ConstantValue);
+
+        Assert.Equal(expected.ToHashCode(), hc.ToHashCode());
+    }
+
+    [Fact]
+    public static void HashCode_Add_Null()
+    {
+        var hc = new HashCode();
+        hc.Add<string>(null);
+
+        var expected = new HashCode();
+        expected.Add(EqualityComparer<string>.Default.GetHashCode(null));
+
+        Assert.Equal(expected.ToHashCode(), hc.ToHashCode());
+    }
+
+    [Fact]
+    public static void HashCode_Add_GenericEqualityComparer()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add("Hello", new ConstComparer());
+
+        var expected = new HashCode();
+        expected.Add(1);
+        expected.Add(ConstComparer.ConstantValue);
+
+        Assert.Equal(expected.ToHashCode(), hc.ToHashCode());
+    }
+
+    [Fact]
+    public static void HashCode_Add_NullEqualityComparer()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add("Hello", null);
+
+        var expected = new HashCode();
+        expected.Add(1);
+        expected.Add("Hello");
+
+        Assert.Equal(expected.ToHashCode(), hc.ToHashCode());
+    }
+
+    [Fact]
+    public static void HashCode_Combine()
+    {
+        var hcs = new int[]
+        {
+            HashCode.Combine(1),
+            HashCode.Combine(1, 2),
+            HashCode.Combine(1, 2, 3),
+            HashCode.Combine(1, 2, 3, 4),
+            HashCode.Combine(1, 2, 3, 4, 5),
+            HashCode.Combine(1, 2, 3, 4, 5, 6),
+            HashCode.Combine(1, 2, 3, 4, 5, 6, 7),
+            HashCode.Combine(1, 2, 3, 4, 5, 6, 7, 8),
+
+            HashCode.Combine(2),
+            HashCode.Combine(2, 3),
+            HashCode.Combine(2, 3, 4),
+            HashCode.Combine(2, 3, 4, 5),
+            HashCode.Combine(2, 3, 4, 5, 6),
+            HashCode.Combine(2, 3, 4, 5, 6, 7),
+            HashCode.Combine(2, 3, 4, 5, 6, 7, 8),
+            HashCode.Combine(2, 3, 4, 5, 6, 7, 8, 9),
+        };
+
+        for (int i = 0; i < hcs.Length; i++)
+            for (int j = 0; j < hcs.Length; j++)
+            {
+                if (i == j) continue;
+                Assert.NotEqual(hcs[i], hcs[j]);
+            }
+    }
+
+    [Fact]
+    public static void HashCode_Combine_Add_1()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1));
+    }
+
+    [Fact]
+    public static void HashCode_Combine_Add_2()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add(2);
+        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2));
+    }
+
+    [Fact]
+    public static void HashCode_Combine_Add_3()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add(2);
+        hc.Add(3);
+        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3));
+    }
+
+    [Fact]
+    public static void HashCode_Combine_Add_4()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add(2);
+        hc.Add(3);
+        hc.Add(4);
+        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4));
+    }
+
+    [Fact]
+    public static void HashCode_Combine_Add_5()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add(2);
+        hc.Add(3);
+        hc.Add(4);
+        hc.Add(5);
+        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4, 5));
+    }
+
+    [Fact]
+    public static void HashCode_Combine_Add_6()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add(2);
+        hc.Add(3);
+        hc.Add(4);
+        hc.Add(5);
+        hc.Add(6);
+        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4, 5, 6));
+    }
+
+    [Fact]
+    public static void HashCode_Combine_Add_7()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add(2);
+        hc.Add(3);
+        hc.Add(4);
+        hc.Add(5);
+        hc.Add(6);
+        hc.Add(7);
+        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4, 5, 6, 7));
+    }
+
+    [Fact]
+    public static void HashCode_Combine_Add_8()
+    {
+        var hc = new HashCode();
+        hc.Add(1);
+        hc.Add(2);
+        hc.Add(3);
+        hc.Add(4);
+        hc.Add(5);
+        hc.Add(6);
+        hc.Add(7);
+        hc.Add(8);
+        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4, 5, 6, 7, 8));
+    }
+
+    [Fact]
+    public static void HashCode_GetHashCode()
+    {
+        var hc = new HashCode();
+
+        Assert.Throws<NotSupportedException>(() => hc.GetHashCode());
+    }
+
+    [Fact]
+    public static void HashCode_Equals()
+    {
+        var hc = new HashCode();
+
+        Assert.Throws<NotSupportedException>(() => hc.Equals(hc));
+    }
+
+    [Fact]
+    public static void HashCode_GetHashCode_Boxed()
+    {
+        var hc = new HashCode();
+        var obj = (object)hc;
+
+        Assert.Throws<NotSupportedException>(() => obj.GetHashCode());
+    }
+
+    [Fact]
+    public static void HashCode_Equals_Boxed()
+    {
+        var hc = new HashCode();
+        var obj = (object)hc;
+
+        Assert.Throws<NotSupportedException>(() => obj.Equals(obj));
+    }
+
+    public class ConstComparer : System.Collections.Generic.IEqualityComparer<string>
+    {
+        public const int ConstantValue = 1234;
+
+        public bool Equals(string x, string y) => false;
+        public int GetHashCode(string obj) => ConstantValue;
+    }
+
+    public class ConstHashCodeType
+    {
+        public override int GetHashCode() => ConstComparer.ConstantValue;
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/HashCodeTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/HashCodeTests.netcoreapp.cs
deleted file mode 100644 (file)
index 8564559..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-// 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;
-
-public static class HashCodeTests
-{
-    [Fact]
-    public static void HashCode_Add()
-    {
-        // The version of xUnit used by corefx does not support params theories.
-        void Theory(uint expected, params uint[] vector)
-        {
-            var hc = new HashCode();
-            for (int i = 0; i < vector.Length; i++)
-                hc.Add(vector[i]);
-
-#if SYSTEM_HASHCODE_TESTVECTORS
-            // HashCode is not deterministic across AppDomains by design. This means
-            // that these tests can not be executed against the version that exists
-            // within CoreCLR. Copy HashCode and set m_seed to 0 in order to execute
-            // these tests.
-
-            Assert.Equal(expected, (uint)hc.ToHashCode());
-#else
-            // Validate that the HashCode.m_seed is randomized. This has a 1 in 4
-            // billion chance of resulting in a false negative, as HashCode.m_seed
-            // can be 0.
-
-            Assert.NotEqual(expected, (uint)hc.ToHashCode());
-#endif
-        }
-
-        // These test vectors were created using https://asecuritysite.com/encryption/xxHash
-        // 1. Find the hash for "".
-        // 2. Find the hash for "abcd". ASCII "abcd" and bit convert to uint.
-        // 3. Find the hash for "abcd1234". ASCII [ "abcd", "1234"] and bit convert to 2 uints.
-        // n. Continue until "abcd0123efgh4567ijkl8901mnop2345qrst6789uvwx0123yzab".
-
-        Theory(0x02cc5d05U);
-        Theory(0xa3643705U, 0x64636261U );
-        Theory(0x4603e94cU, 0x64636261U, 0x33323130U );
-        Theory(0xd8a1e80fU, 0x64636261U, 0x33323130U, 0x68676665U );
-        Theory(0x4b62a7cfU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U );
-        Theory(0xc33a7641U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U );
-        Theory(0x1a794705U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U );
-        Theory(0x4d79177dU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU );
-        Theory(0x59d79205U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U );
-        Theory(0x49585aaeU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U );
-        Theory(0x2f005ff1U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U, 0x39383736U );
-        Theory(0x0ce339bdU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U, 0x39383736U, 0x78777675U );
-        Theory(0xb31bd2ffU, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U, 0x39383736U, 0x78777675U, 0x33323130U );
-        Theory(0xa821efa3U, 0x64636261U, 0x33323130U, 0x68676665U, 0x37363534U, 0x6c6b6a69U, 0x31303938U, 0x706f6e6dU, 0x35343332U, 0x74737271U, 0x39383736U, 0x78777675U, 0x33323130U, 0x62617a79U );
-    }
-
-    [Fact]
-    public static void HashCode_Add_HashCode()
-    {
-        var hc1 = new HashCode();
-        hc1.Add("Hello");
-
-        var hc2 = new HashCode();
-        hc2.Add("Hello".GetHashCode());
-
-        Assert.Equal(hc1.ToHashCode(), hc2.ToHashCode());
-    }
-
-    [Fact]
-    public static void HashCode_Add_Generic()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add(new ConstHashCodeType());
-
-        var expected = new HashCode();
-        expected.Add(1);
-        expected.Add(ConstComparer.ConstantValue);
-
-        Assert.Equal(expected.ToHashCode(), hc.ToHashCode());
-    }
-
-    [Fact]
-    public static void HashCode_Add_Null()
-    {
-        var hc = new HashCode();
-        hc.Add<string>(null);
-
-        var expected = new HashCode();
-        expected.Add(EqualityComparer<string>.Default.GetHashCode(null));
-
-        Assert.Equal(expected.ToHashCode(), hc.ToHashCode());
-    }
-
-    [Fact]
-    public static void HashCode_Add_GenericEqualityComparer()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add("Hello", new ConstComparer());
-
-        var expected = new HashCode();
-        expected.Add(1);
-        expected.Add(ConstComparer.ConstantValue);
-
-        Assert.Equal(expected.ToHashCode(), hc.ToHashCode());
-    }
-
-    [Fact]
-    public static void HashCode_Add_NullEqualityComparer()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add("Hello", null);
-
-        var expected = new HashCode();
-        expected.Add(1);
-        expected.Add("Hello");
-
-        Assert.Equal(expected.ToHashCode(), hc.ToHashCode());
-    }
-
-    [Fact]
-    public static void HashCode_Combine()
-    {
-        var hcs = new int[]
-        {
-            HashCode.Combine(1),
-            HashCode.Combine(1, 2),
-            HashCode.Combine(1, 2, 3),
-            HashCode.Combine(1, 2, 3, 4),
-            HashCode.Combine(1, 2, 3, 4, 5),
-            HashCode.Combine(1, 2, 3, 4, 5, 6),
-            HashCode.Combine(1, 2, 3, 4, 5, 6, 7),
-            HashCode.Combine(1, 2, 3, 4, 5, 6, 7, 8),
-
-            HashCode.Combine(2),
-            HashCode.Combine(2, 3),
-            HashCode.Combine(2, 3, 4),
-            HashCode.Combine(2, 3, 4, 5),
-            HashCode.Combine(2, 3, 4, 5, 6),
-            HashCode.Combine(2, 3, 4, 5, 6, 7),
-            HashCode.Combine(2, 3, 4, 5, 6, 7, 8),
-            HashCode.Combine(2, 3, 4, 5, 6, 7, 8, 9),
-        };
-
-        for (int i = 0; i < hcs.Length; i++)
-            for (int j = 0; j < hcs.Length; j++)
-            {
-                if (i == j) continue;
-                Assert.NotEqual(hcs[i], hcs[j]);
-            }
-    }
-
-    [Fact]
-    public static void HashCode_Combine_Add_1()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1));
-    }
-
-    [Fact]
-    public static void HashCode_Combine_Add_2()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add(2);
-        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2));
-    }
-
-    [Fact]
-    public static void HashCode_Combine_Add_3()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add(2);
-        hc.Add(3);
-        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3));
-    }
-
-    [Fact]
-    public static void HashCode_Combine_Add_4()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add(2);
-        hc.Add(3);
-        hc.Add(4);
-        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4));
-    }
-
-    [Fact]
-    public static void HashCode_Combine_Add_5()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add(2);
-        hc.Add(3);
-        hc.Add(4);
-        hc.Add(5);
-        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4, 5));
-    }
-
-    [Fact]
-    public static void HashCode_Combine_Add_6()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add(2);
-        hc.Add(3);
-        hc.Add(4);
-        hc.Add(5);
-        hc.Add(6);
-        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4, 5, 6));
-    }
-
-    [Fact]
-    public static void HashCode_Combine_Add_7()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add(2);
-        hc.Add(3);
-        hc.Add(4);
-        hc.Add(5);
-        hc.Add(6);
-        hc.Add(7);
-        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4, 5, 6, 7));
-    }
-
-    [Fact]
-    public static void HashCode_Combine_Add_8()
-    {
-        var hc = new HashCode();
-        hc.Add(1);
-        hc.Add(2);
-        hc.Add(3);
-        hc.Add(4);
-        hc.Add(5);
-        hc.Add(6);
-        hc.Add(7);
-        hc.Add(8);
-        Assert.Equal(hc.ToHashCode(), HashCode.Combine(1, 2, 3, 4, 5, 6, 7, 8));
-    }
-
-    [Fact]
-    public static void HashCode_GetHashCode()
-    {
-        var hc = new HashCode();
-
-        Assert.Throws<NotSupportedException>(() => hc.GetHashCode());
-    }
-
-    [Fact]
-    public static void HashCode_Equals()
-    {
-        var hc = new HashCode();
-
-        Assert.Throws<NotSupportedException>(() => hc.Equals(hc));
-    }
-
-    [Fact]
-    public static void HashCode_GetHashCode_Boxed()
-    {
-        var hc = new HashCode();
-        var obj = (object)hc;
-
-        Assert.Throws<NotSupportedException>(() => obj.GetHashCode());
-    }
-
-    [Fact]
-    public static void HashCode_Equals_Boxed()
-    {
-        var hc = new HashCode();
-        var obj = (object)hc;
-
-        Assert.Throws<NotSupportedException>(() => obj.Equals(obj));
-    }
-
-    public class ConstComparer : System.Collections.Generic.IEqualityComparer<string>
-    {
-        public const int ConstantValue = 1234;
-
-        public bool Equals(string x, string y) => false;
-        public int GetHashCode(string obj) => ConstantValue;
-    }
-
-    public class ConstHashCodeType
-    {
-        public override int GetHashCode() => ConstComparer.ConstantValue;
-    }
-}
index 1264754b3c5e153bac317ba315f1d09ac320caab..46b286d0d3a8ebd72e83cf0bc3acda1a0d2e9c61 100644 (file)
@@ -8,7 +8,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class Int16Tests
+    public class Int16Tests
     {
         [Fact]
         public static void Ctor_Empty()
@@ -314,5 +314,106 @@ namespace System.Tests
             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));
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Int16Tests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Int16Tests.netcoreapp.cs
deleted file mode 100644 (file)
index c2ad54c..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-// 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));
-            }
-        }
-    }
-}
index dd624390d8d31fca1d1e6576484f07a44dcd1ea1..2a338f0b99cfd81c07df9fa7ba1b500343d77a01 100644 (file)
@@ -8,7 +8,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class Int32Tests
+    public class Int32Tests
     {
         [Fact]
         public static void Ctor_Empty()
@@ -677,5 +677,153 @@ namespace System.Tests
             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));
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Int32Tests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Int32Tests.netcoreapp.cs
deleted file mode 100644 (file)
index 086744b..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-// 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));
-            }
-        }
-    }
-}
index 2d3115164dac39be8395b519988bb15ff918b86c..d005869c21d9ec45768c7ad93fed0d1612917f94 100644 (file)
@@ -9,7 +9,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class Int64Tests
+    public class Int64Tests
     {
         [Fact]
         public static void Ctor_Empty()
@@ -330,5 +330,104 @@ namespace System.Tests
             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));
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Int64Tests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Int64Tests.netcoreapp.cs
deleted file mode 100644 (file)
index 8a7bc04..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// 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));
-            }
-        }
-    }
-}
index 31828f1462e36d7b3b75aa200d6a1f7c9e40013b..dca78325956f8f328f3b32ed30c66140ac9fec6a 100644 (file)
@@ -8,7 +8,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public static partial class IntPtrTests
+    public static class IntPtrTests
     {
         private static unsafe bool Is64Bit => sizeof(void*) == 8;
 
@@ -116,6 +116,9 @@ namespace System.Tests
                 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());
diff --git a/src/libraries/System.Runtime/tests/System/IntPtrTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/IntPtrTests.netcoreapp.cs
deleted file mode 100644 (file)
index d7497e6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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));
-        }
-    }
-}
index 07361953a188139305fe4074203304403ee0a269..f2ccfdde59de57dff545f9d28798bcaccca9aff9 100644 (file)
@@ -9,7 +9,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public static partial class LazyTests
+    public static class LazyTests
     {
         [Fact]
         public static void Ctor()
@@ -535,6 +535,49 @@ namespace System.Tests
             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);
diff --git a/src/libraries/System.Runtime/tests/System/LazyTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/LazyTests.netcoreapp.cs
deleted file mode 100644 (file)
index bb85e8f..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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));
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/RealFormatterTests.cs b/src/libraries/System.Runtime/tests/System/RealFormatterTests.cs
new file mode 100644 (file)
index 0000000..77ba848
--- /dev/null
@@ -0,0 +1,118 @@
+// 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 class RealFormatterTests : RealFormatterTestsBase
+    {
+        // The actual tests are defined in: src\Common\tests\System\RealFormatterTestsBase.netcoreapp.cs
+
+        protected override string InvariantToStringDouble(double d, string format)
+        {
+            return d.ToString(format, CultureInfo.InvariantCulture);
+        }
+
+        protected override string InvariantToStringSingle(float f, string format)
+        {
+            return f.ToString(format, CultureInfo.InvariantCulture);
+        }
+
+        [Theory]
+        [InlineData("##.#", double.Epsilon, "")]
+        [InlineData("##.#", double.MaxValue, "179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
+        [InlineData("##.#", Math.E, "2.7")]
+        [InlineData("##.#", Math.PI, "3.1")]
+        [InlineData("##.#", 0.0, "")]
+        [InlineData("##.#", 0.0046, "")]
+        [InlineData("##.#", 0.005, "")]
+        [InlineData("##.#", 0.125, ".1")]
+        [InlineData("##.#", 0.5, ".5")]
+        [InlineData("##.#", 0.51, ".5")]
+        [InlineData("##.#", 0.56789, ".6")]
+        [InlineData("##.#", 0.84551240822557006, ".8")]
+        [InlineData("##.#", 1.0, "1")]
+        [InlineData("##.#", 46.5f, "46.5")]
+        [InlineData("##.#", 505.0, "505")]
+        [InlineData("##.#", 506.0, "506")]
+        [InlineData("##.#", 545.0, "545")]
+        [InlineData("##.#", 545.1, "545.1")]
+        [InlineData("##.#", 555.0, "555")]
+        [InlineData("##.#", 46500.0f, "46500")]
+        [InlineData("##.#", 65747.125, "65747.1")]
+        [InlineData("##.#", 1844674407370955.25, "1844674407370960")]
+        [InlineData("#,###.00", double.Epsilon, ".00")]
+        [InlineData("#,###.00", double.MaxValue, "179,769,313,486,232,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000.00")]
+        [InlineData("#,###.00", Math.E, "2.72")]
+        [InlineData("#,###.00", Math.PI, "3.14")]
+        [InlineData("#,###.00", 0.0, ".00")]
+        [InlineData("#,###.00", 0.0046, ".00")]
+        [InlineData("#,###.00", 0.005, ".01")]
+        [InlineData("#,###.00", 0.125, ".13")]
+        [InlineData("#,###.00", 0.5, ".50")]
+        [InlineData("#,###.00", 0.51, ".51")]
+        [InlineData("#,###.00", 0.56789, ".57")]
+        [InlineData("#,###.00", 0.84551240822557006, ".85")]
+        [InlineData("#,###.00", 1.0, "1.00")]
+        [InlineData("#,###.00", 46.5f, "46.50")]
+        [InlineData("#,###.00", 505.0, "505.00")]
+        [InlineData("#,###.00", 506.0, "506.00")]
+        [InlineData("#,###.00", 545.0, "545.00")]
+        [InlineData("#,###.00", 545.1, "545.10")]
+        [InlineData("#,###.00", 555.0, "555.00")]
+        [InlineData("#,###.00", 46500.0f, "46,500.00")]
+        [InlineData("#,###.00", 65747.125, "65,747.13")]
+        [InlineData("#,###.00", 1844674407370955.25, "1,844,674,407,370,960.00")]
+        public void TestFormatterDouble_Custom(string format, double value, string expectedResult) => TestFormatterDouble_Standard(value, format, expectedResult);
+
+        [Theory]
+        [InlineData("##.#", float.Epsilon, "")]
+        [InlineData("##.#", float.MaxValue, "340282300000000000000000000000000000000")]
+        [InlineData("##.#", MathF.E, "2.7")]
+        [InlineData("##.#", MathF.PI, "3.1")]
+        [InlineData("##.#", 0.0f, "")]
+        [InlineData("##.#", 0.0046f, "")]
+        [InlineData("##.#", 0.005f, "")]
+        [InlineData("##.#", 0.125f, ".1")]
+        [InlineData("##.#", 0.5f, ".5")]
+        [InlineData("##.#", 0.51f, ".5")]
+        [InlineData("##.#", 0.56789f, ".6")]
+        [InlineData("##.#", 0.845512390f, ".8")]
+        [InlineData("##.#", 1.0f, "1")]
+        [InlineData("##.#", 46.5f, "46.5")]
+        [InlineData("##.#", 505.0f, "505")]
+        [InlineData("##.#", 506.0f, "506")]
+        [InlineData("##.#", 545.0f, "545")]
+        [InlineData("##.#", 545.1f, "545.1")]
+        [InlineData("##.#", 555.0f, "555")]
+        [InlineData("##.#", 46500.0f, "46500")]
+        [InlineData("##.#", 65747.125f, "65747.1")]
+        [InlineData("##.#", 429496.72f, "429496.7")]
+        [InlineData("#,###.00", float.Epsilon, ".00")]
+        [InlineData("#,###.00", float.MaxValue, "340,282,300,000,000,000,000,000,000,000,000,000,000.00")]
+        [InlineData("#,###.00", MathF.E, "2.72")]
+        [InlineData("#,###.00", MathF.PI, "3.14")]
+        [InlineData("#,###.00", 0.0f, ".00")]
+        [InlineData("#,###.00", 0.0046f, ".00")]
+        [InlineData("#,###.00", 0.005f, ".01")]
+        [InlineData("#,###.00", 0.125f, ".13")]
+        [InlineData("#,###.00", 0.5f, ".50")]
+        [InlineData("#,###.00", 0.51f, ".51")]
+        [InlineData("#,###.00", 0.56789f, ".57")]
+        [InlineData("#,###.00", 0.845512390f, ".85")]
+        [InlineData("#,###.00", 1.0f, "1.00")]
+        [InlineData("#,###.00", 46.5f, "46.50")]
+        [InlineData("#,###.00", 505.0f, "505.00")]
+        [InlineData("#,###.00", 506.0f, "506.00")]
+        [InlineData("#,###.00", 545.0f, "545.00")]
+        [InlineData("#,###.00", 545.1f, "545.10")]
+        [InlineData("#,###.00", 555.0f, "555.00")]
+        [InlineData("#,###.00", 46500.0f, "46,500.00")]
+        [InlineData("#,###.00", 65747.125f, "65,747.12")]
+        [InlineData("#,###.00", 429496.72f, "429,496.70")]
+        public void TestFormatteSingle_Custom(string format, float value, string expectedResult) => TestFormatterSingle_Standard(value, format, expectedResult);
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/RealFormatterTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/RealFormatterTests.netcoreapp.cs
deleted file mode 100644 (file)
index 77ba848..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-// 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 class RealFormatterTests : RealFormatterTestsBase
-    {
-        // The actual tests are defined in: src\Common\tests\System\RealFormatterTestsBase.netcoreapp.cs
-
-        protected override string InvariantToStringDouble(double d, string format)
-        {
-            return d.ToString(format, CultureInfo.InvariantCulture);
-        }
-
-        protected override string InvariantToStringSingle(float f, string format)
-        {
-            return f.ToString(format, CultureInfo.InvariantCulture);
-        }
-
-        [Theory]
-        [InlineData("##.#", double.Epsilon, "")]
-        [InlineData("##.#", double.MaxValue, "179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")]
-        [InlineData("##.#", Math.E, "2.7")]
-        [InlineData("##.#", Math.PI, "3.1")]
-        [InlineData("##.#", 0.0, "")]
-        [InlineData("##.#", 0.0046, "")]
-        [InlineData("##.#", 0.005, "")]
-        [InlineData("##.#", 0.125, ".1")]
-        [InlineData("##.#", 0.5, ".5")]
-        [InlineData("##.#", 0.51, ".5")]
-        [InlineData("##.#", 0.56789, ".6")]
-        [InlineData("##.#", 0.84551240822557006, ".8")]
-        [InlineData("##.#", 1.0, "1")]
-        [InlineData("##.#", 46.5f, "46.5")]
-        [InlineData("##.#", 505.0, "505")]
-        [InlineData("##.#", 506.0, "506")]
-        [InlineData("##.#", 545.0, "545")]
-        [InlineData("##.#", 545.1, "545.1")]
-        [InlineData("##.#", 555.0, "555")]
-        [InlineData("##.#", 46500.0f, "46500")]
-        [InlineData("##.#", 65747.125, "65747.1")]
-        [InlineData("##.#", 1844674407370955.25, "1844674407370960")]
-        [InlineData("#,###.00", double.Epsilon, ".00")]
-        [InlineData("#,###.00", double.MaxValue, "179,769,313,486,232,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000.00")]
-        [InlineData("#,###.00", Math.E, "2.72")]
-        [InlineData("#,###.00", Math.PI, "3.14")]
-        [InlineData("#,###.00", 0.0, ".00")]
-        [InlineData("#,###.00", 0.0046, ".00")]
-        [InlineData("#,###.00", 0.005, ".01")]
-        [InlineData("#,###.00", 0.125, ".13")]
-        [InlineData("#,###.00", 0.5, ".50")]
-        [InlineData("#,###.00", 0.51, ".51")]
-        [InlineData("#,###.00", 0.56789, ".57")]
-        [InlineData("#,###.00", 0.84551240822557006, ".85")]
-        [InlineData("#,###.00", 1.0, "1.00")]
-        [InlineData("#,###.00", 46.5f, "46.50")]
-        [InlineData("#,###.00", 505.0, "505.00")]
-        [InlineData("#,###.00", 506.0, "506.00")]
-        [InlineData("#,###.00", 545.0, "545.00")]
-        [InlineData("#,###.00", 545.1, "545.10")]
-        [InlineData("#,###.00", 555.0, "555.00")]
-        [InlineData("#,###.00", 46500.0f, "46,500.00")]
-        [InlineData("#,###.00", 65747.125, "65,747.13")]
-        [InlineData("#,###.00", 1844674407370955.25, "1,844,674,407,370,960.00")]
-        public void TestFormatterDouble_Custom(string format, double value, string expectedResult) => TestFormatterDouble_Standard(value, format, expectedResult);
-
-        [Theory]
-        [InlineData("##.#", float.Epsilon, "")]
-        [InlineData("##.#", float.MaxValue, "340282300000000000000000000000000000000")]
-        [InlineData("##.#", MathF.E, "2.7")]
-        [InlineData("##.#", MathF.PI, "3.1")]
-        [InlineData("##.#", 0.0f, "")]
-        [InlineData("##.#", 0.0046f, "")]
-        [InlineData("##.#", 0.005f, "")]
-        [InlineData("##.#", 0.125f, ".1")]
-        [InlineData("##.#", 0.5f, ".5")]
-        [InlineData("##.#", 0.51f, ".5")]
-        [InlineData("##.#", 0.56789f, ".6")]
-        [InlineData("##.#", 0.845512390f, ".8")]
-        [InlineData("##.#", 1.0f, "1")]
-        [InlineData("##.#", 46.5f, "46.5")]
-        [InlineData("##.#", 505.0f, "505")]
-        [InlineData("##.#", 506.0f, "506")]
-        [InlineData("##.#", 545.0f, "545")]
-        [InlineData("##.#", 545.1f, "545.1")]
-        [InlineData("##.#", 555.0f, "555")]
-        [InlineData("##.#", 46500.0f, "46500")]
-        [InlineData("##.#", 65747.125f, "65747.1")]
-        [InlineData("##.#", 429496.72f, "429496.7")]
-        [InlineData("#,###.00", float.Epsilon, ".00")]
-        [InlineData("#,###.00", float.MaxValue, "340,282,300,000,000,000,000,000,000,000,000,000,000.00")]
-        [InlineData("#,###.00", MathF.E, "2.72")]
-        [InlineData("#,###.00", MathF.PI, "3.14")]
-        [InlineData("#,###.00", 0.0f, ".00")]
-        [InlineData("#,###.00", 0.0046f, ".00")]
-        [InlineData("#,###.00", 0.005f, ".01")]
-        [InlineData("#,###.00", 0.125f, ".13")]
-        [InlineData("#,###.00", 0.5f, ".50")]
-        [InlineData("#,###.00", 0.51f, ".51")]
-        [InlineData("#,###.00", 0.56789f, ".57")]
-        [InlineData("#,###.00", 0.845512390f, ".85")]
-        [InlineData("#,###.00", 1.0f, "1.00")]
-        [InlineData("#,###.00", 46.5f, "46.50")]
-        [InlineData("#,###.00", 505.0f, "505.00")]
-        [InlineData("#,###.00", 506.0f, "506.00")]
-        [InlineData("#,###.00", 545.0f, "545.00")]
-        [InlineData("#,###.00", 545.1f, "545.10")]
-        [InlineData("#,###.00", 555.0f, "555.00")]
-        [InlineData("#,###.00", 46500.0f, "46,500.00")]
-        [InlineData("#,###.00", 65747.125f, "65,747.12")]
-        [InlineData("#,###.00", 429496.72f, "429,496.70")]
-        public void TestFormatteSingle_Custom(string format, float value, string expectedResult) => TestFormatterSingle_Standard(value, format, expectedResult);
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Reflection/BindingFlagsDoNotWrap.cs b/src/libraries/System.Runtime/tests/System/Reflection/BindingFlagsDoNotWrap.cs
new file mode 100644 (file)
index 0000000..0da2df6
--- /dev/null
@@ -0,0 +1,174 @@
+// 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 System.Linq;
+using Xunit;
+
+namespace System.Reflection.Tests
+{
+    public static class BindingFlagsDoNotWrapTests
+    {
+        [Fact]
+        public static void MethodInvoke()
+        {
+            MethodInfo m = typeof(TestClass).GetMethod(nameof(TestClass.Moo), BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
+            TestDoNotWrap<MyException1>((bf) => m.Invoke(null, bf, null, Array.Empty<object>(), null));
+        }
+
+        [Fact]
+        public static void ConstructorInvoke()
+        {
+            ConstructorInfo c = typeof(TestClass).GetConstructor(BindingFlags.Public|BindingFlags.Instance, null, Array.Empty<Type>(), null);
+            TestDoNotWrap<MyException2>((bf) => c.Invoke(bf, null, Array.Empty<object>(), null));
+        }
+
+        [Fact]
+        public static void ConstructorInvokeStringCtor()
+        {
+            // Code coverage: Project N - String constructors go through a separate code path.
+            ConstructorInfo c = typeof(string).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(char[]), typeof(int), typeof(int) }, null);
+            TestDoNotWrap<ArgumentNullException>((bf) => c.Invoke(bf, null, new object[] { null, 0, 0 }, null));
+        }
+
+        [Fact]
+        public static void ConstructorInvokeUsingMethodInfoInvoke()
+        {
+            ConstructorInfo c = typeof(TestClass).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Array.Empty<Type>(), null);
+            TestDoNotWrap<MyException2>((bf) => c.Invoke(new TestClass(0), bf, null, Array.Empty<object>(), null));
+        }
+
+        [Fact]
+        public static void PropertyGet()
+        {
+            PropertyInfo p = typeof(TestClass).GetProperty(nameof(TestClass.MyProperty));
+            TestDoNotWrap<MyException3>((bf) => p.GetValue(null, bf, null, null, null));
+        }
+
+        [Fact]
+        public static void PropertySet()
+        {
+            PropertyInfo p = typeof(TestClass).GetProperty(nameof(TestClass.MyProperty));
+            TestDoNotWrap<MyException4>((bf) => p.SetValue(null, 42, bf, null, null, null));
+        }
+
+        [Fact]
+        public static void InvokeMember_Method()
+        {
+            Type t = typeof(TestClass);
+            const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.InvokeMethod;
+            TestDoNotWrap<MyException1>((bf) => t.InvokeMember(nameof(TestClass.Moo), bf | flags, null, null, Array.Empty<object>(), null, null, null));
+        }
+
+        [Fact]
+        public static void InvokeMember_PropertyGet()
+        {
+            Type t = typeof(TestClass);
+            const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.GetProperty;
+            TestDoNotWrap<MyException3>((bf) => t.InvokeMember(nameof(TestClass.MyProperty), bf | flags, null, null, Array.Empty<object>(), null, null, null));
+        }
+
+        [Fact]
+        public static void InvokeMember_PropertySet()
+        {
+            Type t = typeof(TestClass);
+            const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.SetProperty;
+            TestDoNotWrap<MyException4>((bf) => t.InvokeMember(nameof(TestClass.MyProperty), bf | flags, null, null, new object[] { 42 }, null, null, null));
+        }
+
+        [Fact]
+        public static void ActivatorCreateInstance()
+        {
+            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
+            TestDoNotWrap<MyException2>((bf) => Activator.CreateInstance(typeof(TestClass), bf | flags, null, Array.Empty<object>(), null, null));
+        }
+
+        [Fact]
+        public static void ActivatorCreateInstanceOneArgument()
+        {
+            // For code coverage on CoreCLR: Activator.CreateInstance with parameters uses different code path from one without parameters.
+            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
+            TestDoNotWrap<MyException5>((bf) => Activator.CreateInstance(typeof(TestClass), bf | flags, null, new object[] { "Hello" }, null, null));
+        }
+
+        [Fact]
+        public static void ActivatorCreateInstanceCaching()
+        {
+            // For code coverage on CoreCLR: Activator.CreateInstance - second call after non-throwing call goes through a different path
+            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
+            TestClassConditional.ThrowInConstructor = true;
+            TestDoNotWrap<MyException6>((bf) => Activator.CreateInstance(typeof(TestClassConditional), bf | flags, null, Array.Empty<object>(), null, null));
+
+            TestClassConditional.ThrowInConstructor = false;
+            Assert.True(Activator.CreateInstance(typeof(TestClassConditional), flags, null, Array.Empty<object>(), null, null) is TestClassConditional);
+
+            TestClassConditional.ThrowInConstructor = true;
+            TestDoNotWrap<MyException6>((bf) => Activator.CreateInstance(typeof(TestClassConditional), bf | flags, null, Array.Empty<object>(), null, null));
+        }
+
+        [Fact]
+        public static void ActivatorCreateInstance_BadCCtor()
+        {
+            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
+            TestDoNotWrap<TypeInitializationException>((bf) => Activator.CreateInstance(typeof(TestClassBadCCtor), bf | flags, null, Array.Empty<object>(), null, null));
+        }
+
+        [Fact]
+        public static void AssemblyCreateInstance()
+        {
+            Assembly a = typeof(TestClass).Assembly;
+            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
+            TestDoNotWrap<MyException2>((bf) => a.CreateInstance(typeof(TestClass).FullName, false, bf | flags, null, Array.Empty<object>(), null, null));
+        }
+
+        [Fact]
+        public static void AssemblyCreateInstance_BadCCtor()
+        {
+            Assembly a = typeof(TestClass).Assembly;
+            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
+            TestDoNotWrap<TypeInitializationException>((bf) => a.CreateInstance(typeof(TestClassBadCCtor).FullName, false, bf | flags, null, Array.Empty<object>(), null, null));
+        }
+
+        private static void TestDoNotWrap<T>(Action<BindingFlags> action) where T : Exception
+        {
+            Assert.Throws<T>(() => action(BindingFlags.DoNotWrapExceptions));
+            TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => action(default(BindingFlags)));
+            Assert.Equal(typeof(T), tie.InnerException.GetType());
+        }
+
+        private sealed class TestClass
+        {
+            public TestClass() => throw new MyException2();
+            public TestClass(int _) { }
+            public TestClass(string s) => throw new MyException5();
+            public static void Moo() => throw new MyException1();
+            public static int MyProperty { get { throw new MyException3(); } set { throw new MyException4(); } }
+        }
+
+        public sealed class TestClassBadCCtor
+        {
+            public TestClassBadCCtor() { }
+
+            static TestClassBadCCtor()
+            {
+                throw new MyException1();
+            }
+        }
+
+        private sealed class TestClassConditional
+        {
+            public TestClassConditional() { if (ThrowInConstructor) throw new MyException6(); }
+
+            public static bool ThrowInConstructor;
+        }
+
+        private sealed class MyException1 : Exception { }
+        private sealed class MyException2 : Exception { }
+        private sealed class MyException3 : Exception { }
+        private sealed class MyException4 : Exception { }
+        private sealed class MyException5 : Exception { }
+        private sealed class MyException6 : Exception { }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Reflection/BindingFlagsDoNotWrap.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Reflection/BindingFlagsDoNotWrap.netcoreapp.cs
deleted file mode 100644 (file)
index 0da2df6..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-// 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 System.Linq;
-using Xunit;
-
-namespace System.Reflection.Tests
-{
-    public static class BindingFlagsDoNotWrapTests
-    {
-        [Fact]
-        public static void MethodInvoke()
-        {
-            MethodInfo m = typeof(TestClass).GetMethod(nameof(TestClass.Moo), BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
-            TestDoNotWrap<MyException1>((bf) => m.Invoke(null, bf, null, Array.Empty<object>(), null));
-        }
-
-        [Fact]
-        public static void ConstructorInvoke()
-        {
-            ConstructorInfo c = typeof(TestClass).GetConstructor(BindingFlags.Public|BindingFlags.Instance, null, Array.Empty<Type>(), null);
-            TestDoNotWrap<MyException2>((bf) => c.Invoke(bf, null, Array.Empty<object>(), null));
-        }
-
-        [Fact]
-        public static void ConstructorInvokeStringCtor()
-        {
-            // Code coverage: Project N - String constructors go through a separate code path.
-            ConstructorInfo c = typeof(string).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(char[]), typeof(int), typeof(int) }, null);
-            TestDoNotWrap<ArgumentNullException>((bf) => c.Invoke(bf, null, new object[] { null, 0, 0 }, null));
-        }
-
-        [Fact]
-        public static void ConstructorInvokeUsingMethodInfoInvoke()
-        {
-            ConstructorInfo c = typeof(TestClass).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Array.Empty<Type>(), null);
-            TestDoNotWrap<MyException2>((bf) => c.Invoke(new TestClass(0), bf, null, Array.Empty<object>(), null));
-        }
-
-        [Fact]
-        public static void PropertyGet()
-        {
-            PropertyInfo p = typeof(TestClass).GetProperty(nameof(TestClass.MyProperty));
-            TestDoNotWrap<MyException3>((bf) => p.GetValue(null, bf, null, null, null));
-        }
-
-        [Fact]
-        public static void PropertySet()
-        {
-            PropertyInfo p = typeof(TestClass).GetProperty(nameof(TestClass.MyProperty));
-            TestDoNotWrap<MyException4>((bf) => p.SetValue(null, 42, bf, null, null, null));
-        }
-
-        [Fact]
-        public static void InvokeMember_Method()
-        {
-            Type t = typeof(TestClass);
-            const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.InvokeMethod;
-            TestDoNotWrap<MyException1>((bf) => t.InvokeMember(nameof(TestClass.Moo), bf | flags, null, null, Array.Empty<object>(), null, null, null));
-        }
-
-        [Fact]
-        public static void InvokeMember_PropertyGet()
-        {
-            Type t = typeof(TestClass);
-            const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.GetProperty;
-            TestDoNotWrap<MyException3>((bf) => t.InvokeMember(nameof(TestClass.MyProperty), bf | flags, null, null, Array.Empty<object>(), null, null, null));
-        }
-
-        [Fact]
-        public static void InvokeMember_PropertySet()
-        {
-            Type t = typeof(TestClass);
-            const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.SetProperty;
-            TestDoNotWrap<MyException4>((bf) => t.InvokeMember(nameof(TestClass.MyProperty), bf | flags, null, null, new object[] { 42 }, null, null, null));
-        }
-
-        [Fact]
-        public static void ActivatorCreateInstance()
-        {
-            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
-            TestDoNotWrap<MyException2>((bf) => Activator.CreateInstance(typeof(TestClass), bf | flags, null, Array.Empty<object>(), null, null));
-        }
-
-        [Fact]
-        public static void ActivatorCreateInstanceOneArgument()
-        {
-            // For code coverage on CoreCLR: Activator.CreateInstance with parameters uses different code path from one without parameters.
-            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
-            TestDoNotWrap<MyException5>((bf) => Activator.CreateInstance(typeof(TestClass), bf | flags, null, new object[] { "Hello" }, null, null));
-        }
-
-        [Fact]
-        public static void ActivatorCreateInstanceCaching()
-        {
-            // For code coverage on CoreCLR: Activator.CreateInstance - second call after non-throwing call goes through a different path
-            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
-            TestClassConditional.ThrowInConstructor = true;
-            TestDoNotWrap<MyException6>((bf) => Activator.CreateInstance(typeof(TestClassConditional), bf | flags, null, Array.Empty<object>(), null, null));
-
-            TestClassConditional.ThrowInConstructor = false;
-            Assert.True(Activator.CreateInstance(typeof(TestClassConditional), flags, null, Array.Empty<object>(), null, null) is TestClassConditional);
-
-            TestClassConditional.ThrowInConstructor = true;
-            TestDoNotWrap<MyException6>((bf) => Activator.CreateInstance(typeof(TestClassConditional), bf | flags, null, Array.Empty<object>(), null, null));
-        }
-
-        [Fact]
-        public static void ActivatorCreateInstance_BadCCtor()
-        {
-            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
-            TestDoNotWrap<TypeInitializationException>((bf) => Activator.CreateInstance(typeof(TestClassBadCCtor), bf | flags, null, Array.Empty<object>(), null, null));
-        }
-
-        [Fact]
-        public static void AssemblyCreateInstance()
-        {
-            Assembly a = typeof(TestClass).Assembly;
-            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
-            TestDoNotWrap<MyException2>((bf) => a.CreateInstance(typeof(TestClass).FullName, false, bf | flags, null, Array.Empty<object>(), null, null));
-        }
-
-        [Fact]
-        public static void AssemblyCreateInstance_BadCCtor()
-        {
-            Assembly a = typeof(TestClass).Assembly;
-            const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
-            TestDoNotWrap<TypeInitializationException>((bf) => a.CreateInstance(typeof(TestClassBadCCtor).FullName, false, bf | flags, null, Array.Empty<object>(), null, null));
-        }
-
-        private static void TestDoNotWrap<T>(Action<BindingFlags> action) where T : Exception
-        {
-            Assert.Throws<T>(() => action(BindingFlags.DoNotWrapExceptions));
-            TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => action(default(BindingFlags)));
-            Assert.Equal(typeof(T), tie.InnerException.GetType());
-        }
-
-        private sealed class TestClass
-        {
-            public TestClass() => throw new MyException2();
-            public TestClass(int _) { }
-            public TestClass(string s) => throw new MyException5();
-            public static void Moo() => throw new MyException1();
-            public static int MyProperty { get { throw new MyException3(); } set { throw new MyException4(); } }
-        }
-
-        public sealed class TestClassBadCCtor
-        {
-            public TestClassBadCCtor() { }
-
-            static TestClassBadCCtor()
-            {
-                throw new MyException1();
-            }
-        }
-
-        private sealed class TestClassConditional
-        {
-            public TestClassConditional() { if (ThrowInConstructor) throw new MyException6(); }
-
-            public static bool ThrowInConstructor;
-        }
-
-        private sealed class MyException1 : Exception { }
-        private sealed class MyException2 : Exception { }
-        private sealed class MyException3 : Exception { }
-        private sealed class MyException4 : Exception { }
-        private sealed class MyException5 : Exception { }
-        private sealed class MyException6 : Exception { }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.cs b/src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.cs
new file mode 100644 (file)
index 0000000..b0180cc
--- /dev/null
@@ -0,0 +1,182 @@
+// 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.Runtime.CompilerServices;
+
+using Xunit;
+
+namespace System.Reflection.Tests
+{
+    public class InvokeRefReturnNetcoreTests
+    {
+        [Theory]
+        [MemberData(nameof(RefReturnInvokeTestData))]
+        public static void TestRefReturnPropertyGetValue<T>(T value)
+        {
+            TestRefReturnInvoke<T>(value, (p, t) => p.GetValue(t));
+        }
+
+        [Theory]
+        [MemberData(nameof(RefReturnInvokeTestData))]
+        public static void TestRefReturnMethodInvoke<T>(T value)
+        {
+            TestRefReturnInvoke<T>(value, (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
+        }
+
+        [Fact]
+        public static void TestRefReturnNullable()
+        {
+            TestRefReturnInvokeNullable<int>(42);
+        }
+
+        [Fact]
+        public static void TestRefReturnNullableNoValue()
+        {
+            TestRefReturnInvokeNullable<int>(default(int?));
+        }
+
+        [Theory]
+        [MemberData(nameof(RefReturnInvokeTestData))]
+        public static void TestNullRefReturnInvoke<T>(T value)
+        {
+            TestClass<T> tc = new TestClass<T>(value);
+            PropertyInfo p = typeof(TestClass<T>).GetProperty(nameof(TestClass<T>.NullRefReturningProp));
+            Assert.NotNull(p);
+            Assert.Throws<NullReferenceException>(() => p.GetValue(tc));
+        }
+
+        [Fact]
+        public static unsafe void TestRefReturnOfPointer()
+        {
+            int* expected = (int*)0x1122334455667788;
+            TestClassIntPointer tc = new TestClassIntPointer(expected);
+            PropertyInfo p = typeof(TestClassIntPointer).GetProperty(nameof(TestClassIntPointer.RefReturningProp));
+            object rv = p.GetValue(tc);
+            Assert.True(rv is Pointer);
+            int* actual = (int*)(Pointer.Unbox(rv));
+            Assert.Equal((IntPtr)expected, (IntPtr)actual);
+        }
+
+        [Fact]
+        public static unsafe void TestNullRefReturnOfPointer()
+        {
+            TestClassIntPointer tc = new TestClassIntPointer(null);
+
+            PropertyInfo p = typeof(TestClassIntPointer).GetProperty(nameof(TestClassIntPointer.NullRefReturningProp));
+            Assert.NotNull(p);
+            Assert.Throws<NullReferenceException>(() => p.GetValue(tc));
+        }
+
+        [Fact]
+        public static unsafe void TestByRefLikeRefReturn()
+        {
+            ByRefLike brl = new ByRefLike();
+            ByRefLike* pBrl = &brl;
+            MethodInfo mi = typeof(TestClass<int>).GetMethod(nameof(TestClass<int>.ByRefLikeRefReturningMethod));
+            try
+            {
+                // Don't use Assert.Throws because that will make a lambda and invalidate the pointer
+                object o = mi.Invoke(null, new object[] { Pointer.Box(pBrl, typeof(ByRefLike*)) });
+
+                // If this is reached, it means `o` is a boxed byref-like type. That's a GC hole right there.
+                throw new Xunit.Sdk.XunitException("Boxed a byref-like type.");
+            }
+            catch (NotSupportedException)
+            {
+                // We expect a NotSupportedException from the Invoke call. Methods returning byref-like types by reference
+                // are not reflection invokable.
+            }
+        }
+
+        public static IEnumerable<object[]> RefReturnInvokeTestData
+        {
+            get
+            {
+                yield return new object[] { true };
+                yield return new object[] { 'a' };
+                yield return new object[] { (byte)42 };
+                yield return new object[] { (sbyte)42 };
+                yield return new object[] { (ushort)42 };
+                yield return new object[] { (short)42 };
+                yield return new object[] { 42u };
+                yield return new object[] { 42 };
+                yield return new object[] { 42UL };
+                yield return new object[] { 42L };
+                yield return new object[] { 43.67f };
+                yield return new object[] { 43.67 };
+                // [ActiveIssue("https://github.com/xunit/xunit/issues/1771")]
+                //yield return new object[] { new IntPtr(42) };
+                //yield return new object[] { new UIntPtr(42) };
+                //yield return new object[] { 232953453454m };
+                yield return new object[] { BindingFlags.IgnoreCase };
+                yield return new object[] { "Hello" };
+                yield return new object[] { new object() };
+                yield return new object[] { new UriBuilder() };
+                yield return new object[] { new int[5] };
+                yield return new object[] { new int[5, 5] };
+            }
+        }
+
+        private static void TestRefReturnInvoke<T>(T value, Func<PropertyInfo, TestClass<T>, object> invoker)
+        {
+            TestClass<T> tc = new TestClass<T>(value);
+            PropertyInfo p = typeof(TestClass<T>).GetProperty(nameof(TestClass<T>.RefReturningProp));
+            object rv = invoker(p, tc);
+            if (rv != null)
+            {
+                Assert.Equal(typeof(T), rv.GetType());
+            }
+
+            if (typeof(T).IsValueType)
+            {
+                Assert.Equal(value, rv);
+            }
+            else
+            {
+                Assert.Same((object)value, rv);
+            }
+        }
+
+        private static void TestRefReturnInvokeNullable<T>(T? nullable) where T : struct
+        {
+            TestClass<T?> tc = new TestClass<T?>(nullable);
+            PropertyInfo p = typeof(TestClass<T?>).GetProperty(nameof(TestClass<T?>.RefReturningProp));
+            object rv = p.GetValue(tc);
+            if (rv != null)
+            {
+                Assert.Equal(typeof(T), rv.GetType());
+            }
+            if (nullable.HasValue)
+            {
+                Assert.Equal(nullable.Value, rv);
+            }
+            else
+            {
+                Assert.Null(rv);
+            }
+        }
+
+        public ref struct ByRefLike { }
+
+        private sealed class TestClass<T>
+        {
+            private T _value;
+
+            public TestClass(T value) { _value = value; }
+            public ref T RefReturningProp => ref _value;
+            public unsafe ref T NullRefReturningProp => ref Unsafe.AsRef<T>((void*)null);
+            public static unsafe ref ByRefLike ByRefLikeRefReturningMethod(ByRefLike* a) => ref *a;
+        }
+
+        private sealed unsafe class TestClassIntPointer
+        {
+            private int* _value;
+
+            public TestClassIntPointer(int* value) { _value = value; }
+            public ref int* RefReturningProp => ref _value;
+            public ref int* NullRefReturningProp => ref *(int**)null;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.netcoreapp.cs
deleted file mode 100644 (file)
index b0180cc..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-// 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.Runtime.CompilerServices;
-
-using Xunit;
-
-namespace System.Reflection.Tests
-{
-    public class InvokeRefReturnNetcoreTests
-    {
-        [Theory]
-        [MemberData(nameof(RefReturnInvokeTestData))]
-        public static void TestRefReturnPropertyGetValue<T>(T value)
-        {
-            TestRefReturnInvoke<T>(value, (p, t) => p.GetValue(t));
-        }
-
-        [Theory]
-        [MemberData(nameof(RefReturnInvokeTestData))]
-        public static void TestRefReturnMethodInvoke<T>(T value)
-        {
-            TestRefReturnInvoke<T>(value, (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
-        }
-
-        [Fact]
-        public static void TestRefReturnNullable()
-        {
-            TestRefReturnInvokeNullable<int>(42);
-        }
-
-        [Fact]
-        public static void TestRefReturnNullableNoValue()
-        {
-            TestRefReturnInvokeNullable<int>(default(int?));
-        }
-
-        [Theory]
-        [MemberData(nameof(RefReturnInvokeTestData))]
-        public static void TestNullRefReturnInvoke<T>(T value)
-        {
-            TestClass<T> tc = new TestClass<T>(value);
-            PropertyInfo p = typeof(TestClass<T>).GetProperty(nameof(TestClass<T>.NullRefReturningProp));
-            Assert.NotNull(p);
-            Assert.Throws<NullReferenceException>(() => p.GetValue(tc));
-        }
-
-        [Fact]
-        public static unsafe void TestRefReturnOfPointer()
-        {
-            int* expected = (int*)0x1122334455667788;
-            TestClassIntPointer tc = new TestClassIntPointer(expected);
-            PropertyInfo p = typeof(TestClassIntPointer).GetProperty(nameof(TestClassIntPointer.RefReturningProp));
-            object rv = p.GetValue(tc);
-            Assert.True(rv is Pointer);
-            int* actual = (int*)(Pointer.Unbox(rv));
-            Assert.Equal((IntPtr)expected, (IntPtr)actual);
-        }
-
-        [Fact]
-        public static unsafe void TestNullRefReturnOfPointer()
-        {
-            TestClassIntPointer tc = new TestClassIntPointer(null);
-
-            PropertyInfo p = typeof(TestClassIntPointer).GetProperty(nameof(TestClassIntPointer.NullRefReturningProp));
-            Assert.NotNull(p);
-            Assert.Throws<NullReferenceException>(() => p.GetValue(tc));
-        }
-
-        [Fact]
-        public static unsafe void TestByRefLikeRefReturn()
-        {
-            ByRefLike brl = new ByRefLike();
-            ByRefLike* pBrl = &brl;
-            MethodInfo mi = typeof(TestClass<int>).GetMethod(nameof(TestClass<int>.ByRefLikeRefReturningMethod));
-            try
-            {
-                // Don't use Assert.Throws because that will make a lambda and invalidate the pointer
-                object o = mi.Invoke(null, new object[] { Pointer.Box(pBrl, typeof(ByRefLike*)) });
-
-                // If this is reached, it means `o` is a boxed byref-like type. That's a GC hole right there.
-                throw new Xunit.Sdk.XunitException("Boxed a byref-like type.");
-            }
-            catch (NotSupportedException)
-            {
-                // We expect a NotSupportedException from the Invoke call. Methods returning byref-like types by reference
-                // are not reflection invokable.
-            }
-        }
-
-        public static IEnumerable<object[]> RefReturnInvokeTestData
-        {
-            get
-            {
-                yield return new object[] { true };
-                yield return new object[] { 'a' };
-                yield return new object[] { (byte)42 };
-                yield return new object[] { (sbyte)42 };
-                yield return new object[] { (ushort)42 };
-                yield return new object[] { (short)42 };
-                yield return new object[] { 42u };
-                yield return new object[] { 42 };
-                yield return new object[] { 42UL };
-                yield return new object[] { 42L };
-                yield return new object[] { 43.67f };
-                yield return new object[] { 43.67 };
-                // [ActiveIssue("https://github.com/xunit/xunit/issues/1771")]
-                //yield return new object[] { new IntPtr(42) };
-                //yield return new object[] { new UIntPtr(42) };
-                //yield return new object[] { 232953453454m };
-                yield return new object[] { BindingFlags.IgnoreCase };
-                yield return new object[] { "Hello" };
-                yield return new object[] { new object() };
-                yield return new object[] { new UriBuilder() };
-                yield return new object[] { new int[5] };
-                yield return new object[] { new int[5, 5] };
-            }
-        }
-
-        private static void TestRefReturnInvoke<T>(T value, Func<PropertyInfo, TestClass<T>, object> invoker)
-        {
-            TestClass<T> tc = new TestClass<T>(value);
-            PropertyInfo p = typeof(TestClass<T>).GetProperty(nameof(TestClass<T>.RefReturningProp));
-            object rv = invoker(p, tc);
-            if (rv != null)
-            {
-                Assert.Equal(typeof(T), rv.GetType());
-            }
-
-            if (typeof(T).IsValueType)
-            {
-                Assert.Equal(value, rv);
-            }
-            else
-            {
-                Assert.Same((object)value, rv);
-            }
-        }
-
-        private static void TestRefReturnInvokeNullable<T>(T? nullable) where T : struct
-        {
-            TestClass<T?> tc = new TestClass<T?>(nullable);
-            PropertyInfo p = typeof(TestClass<T?>).GetProperty(nameof(TestClass<T?>.RefReturningProp));
-            object rv = p.GetValue(tc);
-            if (rv != null)
-            {
-                Assert.Equal(typeof(T), rv.GetType());
-            }
-            if (nullable.HasValue)
-            {
-                Assert.Equal(nullable.Value, rv);
-            }
-            else
-            {
-                Assert.Null(rv);
-            }
-        }
-
-        public ref struct ByRefLike { }
-
-        private sealed class TestClass<T>
-        {
-            private T _value;
-
-            public TestClass(T value) { _value = value; }
-            public ref T RefReturningProp => ref _value;
-            public unsafe ref T NullRefReturningProp => ref Unsafe.AsRef<T>((void*)null);
-            public static unsafe ref ByRefLike ByRefLikeRefReturningMethod(ByRefLike* a) => ref *a;
-        }
-
-        private sealed unsafe class TestClassIntPointer
-        {
-            private int* _value;
-
-            public TestClassIntPointer(int* value) { _value = value; }
-            public ref int* RefReturningProp => ref _value;
-            public ref int* NullRefReturningProp => ref *(int**)null;
-        }
-    }
-}
index a2cce6330ffc07adf06b2c4d79a222903f370e60..0883838ea23d7eaa8e7cf61cf5c030c54d2a5932 100644 (file)
@@ -22,19 +22,6 @@ namespace System.Reflection.Tests
             Assert.True(m.DeclaringType == typeof(MethodBaseTests));
         }
 
-        [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()
         {
@@ -91,12 +78,6 @@ namespace System.Reflection.Tests
 #endif
         }
 
-        public static MethodBase MyFakeGenericMethod<T>()
-        {
-            MethodBase m = MethodBase.GetCurrentMethod();
-            return m;
-        }
-
         private static int MyAnotherMethod(int x)
         {
             return x+1;
@@ -119,5 +100,38 @@ namespace System.Reflection.Tests
             }
         }
 #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>()
+        {
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Reflection/MethodBaseTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Reflection/MethodBaseTests.netcoreapp.cs
deleted file mode 100644 (file)
index 643e372..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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>()
-        {
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Reflection/SignatureTypes.cs b/src/libraries/System.Runtime/tests/System/Reflection/SignatureTypes.cs
new file mode 100644 (file)
index 0000000..f02c70e
--- /dev/null
@@ -0,0 +1,564 @@
+// 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 System.Linq;
+using Xunit;
+
+namespace System.Reflection.Tests
+{
+    public static class SignatureTypeTests
+    {
+        [Fact]
+        public static void IsSignatureType()
+        {
+            // Executing [Theory] logic manually. Signature Types cannot be used in theory data because Xunit preemptively invokes an unguarded
+            // System.Type pretty printer that invokes members that Signature Types don't support.
+            foreach (object[] pair in IsSignatureTypeTestData)
+            {
+                Type type = (Type)(pair[0]);
+                bool expected = (bool)(pair[1]);
+
+                Assert.Equal(expected, type.IsSignatureType);
+            }
+        }
+
+        public static IEnumerable<object[]> IsSignatureTypeTestData
+        {
+            get
+            {
+                yield return new object[] { typeof(int), false };
+                yield return new object[] { typeof(int).MakeArrayType(), false };
+                yield return new object[] { typeof(int).MakeArrayType(1), false };
+                yield return new object[] { typeof(int).MakeArrayType(2), false };
+                yield return new object[] { typeof(int).MakeByRefType(), false };
+                yield return new object[] { typeof(int).MakePointerType(), false };
+                yield return new object[] { typeof(List<>).MakeGenericType(typeof(int)), false };
+                yield return new object[] { typeof(List<>).GetGenericArguments()[0], false };
+
+                Type sigType = Type.MakeGenericMethodParameter(2);
+
+                yield return new object[] { sigType, true };
+                yield return new object[] { sigType.MakeArrayType(), true };
+                yield return new object[] { sigType.MakeArrayType(1), true };
+                yield return new object[] { sigType.MakeArrayType(2), true };
+                yield return new object[] { sigType.MakeByRefType(), true };
+                yield return new object[] { sigType.MakePointerType(), true };
+                yield return new object[] { typeof(List<>).MakeGenericType(sigType), true };
+
+                yield return new object[] { Type.MakeGenericSignatureType(typeof(List<>), typeof(int)), true };
+                yield return new object[] { Type.MakeGenericSignatureType(typeof(List<>), sigType), true };
+            }
+        }
+
+        [Fact]
+        public static void GetMethodWithGenericParameterCount()
+        {
+            Type t = typeof(TestClass1);
+            const BindingFlags bf = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
+            Type[] args = { typeof(int) };
+            MethodInfo m;
+
+            Assert.Throws<AmbiguousMatchException>(() => t.GetMethod("Moo", bf, null, args, null));
+
+            for (int genericParameterCount = 0; genericParameterCount < 4; genericParameterCount++)
+            {
+                m = t.GetMethod("Moo", genericParameterCount, bf, null, args, null);
+                Assert.NotNull(m);
+                AssertIsMarked(m, genericParameterCount);
+
+                // Verify that generic parameter count filtering occurs before candidates are passed to the binder.
+                m = t.GetMethod("Moo", genericParameterCount, bf, new InflexibleBinder(genericParameterCount), args, null);
+                Assert.NotNull(m);
+                AssertIsMarked(m, genericParameterCount);
+            }
+
+            m = t.GetMethod("Moo", 4, bf, null, args, null);
+            Assert.Null(m);
+        }
+
+        private sealed class InflexibleBinder : Binder
+        {
+            public InflexibleBinder(int genericParameterCount)
+            {
+                _genericParameterCount = genericParameterCount;
+            }
+
+            public sealed override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture) => throw null;
+            public sealed override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state) => throw null;
+            public sealed override object ChangeType(object value, Type type, CultureInfo culture) => throw null;
+            public sealed override void ReorderArgumentArray(ref object[] args, object state) => throw null;
+
+            public sealed override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
+            {
+                foreach (MethodBase methodBase in match)
+                {
+                    Assert.True(methodBase is MethodInfo methodInfo && methodInfo.GetGenericArguments().Length == _genericParameterCount);
+                }
+                return Type.DefaultBinder.SelectMethod(bindingAttr, match, types, modifiers);
+            }
+
+            public sealed override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers) { throw null; }
+
+            private readonly int _genericParameterCount;
+        }
+
+        [Fact]
+        public static void GetMethodWithNegativeGenericParameterCount()
+        {
+            Type t = typeof(TestClass1);
+            const BindingFlags bf = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
+            Type[] args = { typeof(int) };
+            Assert.Throws<ArgumentException>(() => t.GetMethod("Moo", -1, bf, null, args, null));
+        }
+
+        [Theory]
+        [InlineData(true)]
+        [InlineData(false)]
+        public static void GetMethodOverloadTest(bool exactBinding)
+        {
+            Type t = typeof(TestClass2);
+            BindingFlags bf = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
+            if (exactBinding)
+            {
+                bf |= BindingFlags.ExactBinding;
+            }
+            Type[] args = { Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(1).MakeArrayType() };
+            MethodInfo moo = t.GetMethod("Moo", 2, bf, null, args, null);
+            AssertIsMarked(moo, 3);
+        }
+
+        [Theory]
+        [InlineData(true)]
+        [InlineData(false)]
+        public static void SignatureTypeComparisonLogicCodeCoverage(bool exactBinding)
+        {
+            Type t = typeof(TestClass3<,>);
+            MethodInfo[] methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
+            BindingFlags bf = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
+            if (exactBinding)
+            {
+                bf |= BindingFlags.ExactBinding;
+            }
+
+            foreach (MethodInfo m in methods)
+            {
+                ParameterInfo[] parameters = m.GetParameters();
+                Type[] sigTypes = new Type[parameters.Length];
+                for (int i = 0; i < sigTypes.Length; i++)
+                {
+                    sigTypes[i] = parameters[i].ParameterType.ToSignatureType();
+                }
+                MethodInfo match = t.GetMethod("Moo", m.GetGenericArguments().Length, bf, null, sigTypes, null);
+                Assert.NotNull(match);
+                Assert.True(m.HasSameMetadataDefinitionAs(match));
+            }
+        }
+
+        [Fact]
+        public static void SigTypeResolutionResilience()
+        {
+            // Make sure the framework can't be tricked into throwing an exception because it tried to look up a nonexistent method generic parameter
+            // or trying to construct a generic type where the constraints don't validate.
+            Type t = typeof(TestClass4<>);
+            Type[] args = { typeof(TestClass4<>).MakeGenericType(Type.MakeGenericMethodParameter(1)), Type.MakeGenericMethodParameter(500) };
+            CountingBinder binder = new CountingBinder();
+            Assert.Null(t.GetMethod("Moo", BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, binder, args, null));
+            Assert.Equal(3, binder.NumCandidatesReceived);
+        }
+
+        private sealed class CountingBinder : Binder
+        {
+            public sealed override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture) => throw null;
+            public sealed override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state) => throw null;
+            public sealed override object ChangeType(object value, Type type, CultureInfo culture) => throw null;
+            public sealed override void ReorderArgumentArray(ref object[] args, object state) => throw null;
+
+            public sealed override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
+            {
+                NumCandidatesReceived += match.Length;
+                return Type.DefaultBinder.SelectMethod(bindingAttr, match, types, modifiers);
+            }
+
+            public sealed override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers) { throw null; }
+
+            public int NumCandidatesReceived { get; private set; }
+        }
+
+        [Theory]
+        [InlineData(0)]
+        [InlineData(3)]
+        [InlineData(400)]
+        [InlineData(int.MaxValue)]
+        public static void MakeGenericMethodParameter(int position)
+        {
+            Type t = Type.MakeGenericMethodParameter(position);
+            Assert.True(t.IsGenericParameter);
+            Assert.False(t.IsGenericTypeParameter);
+            Assert.True(t.IsGenericMethodParameter);
+            Assert.Equal(position, t.GenericParameterPosition);
+            TestSignatureTypeInvariants(t);
+        }
+
+        [Theory]
+        [InlineData(-1)]
+        [InlineData(-5)]
+        [InlineData(int.MinValue)]
+        public static void MakeGenericMethodParameterNegative(int position)
+        {
+            Assert.Throws<ArgumentException>(() => Type.MakeGenericMethodParameter(position));
+        }
+
+        [Fact]
+        public static void MakeSignatureArrayType()
+        {
+            Type t = Type.MakeGenericMethodParameter(5);
+            t = t.MakeArrayType();
+            Assert.True(t.IsArray);
+            Assert.True(t.IsSZArray);
+            Assert.Equal(1, t.GetArrayRank());
+
+            Type et = t.GetElementType();
+            Assert.True(et.IsSignatureType);
+            Assert.True(et.IsGenericParameter);
+            Assert.False(et.IsGenericTypeParameter);
+            Assert.True(et.IsGenericMethodParameter);
+            Assert.Equal(5, et.GenericParameterPosition);
+
+            TestSignatureTypeInvariants(t);
+        }
+
+        [Theory]
+        [InlineData(1)]
+        [InlineData(2)]
+        [InlineData(3)]
+        public static void MakeSignatureMdArrayType(int rank)
+        {
+            Type t = Type.MakeGenericMethodParameter(5);
+            t = t.MakeArrayType(rank);
+            Assert.True(t.IsArray);
+            Assert.True(t.IsVariableBoundArray);
+            Assert.Equal(rank, t.GetArrayRank());
+
+            TestSignatureTypeInvariants(t);
+        }
+
+        [Fact]
+        public static void MakeSignatureByRefType()
+        {
+            Type t = Type.MakeGenericMethodParameter(5);
+            t = t.MakeByRefType();
+            Assert.True(t.IsByRef);
+
+            Type et = t.GetElementType();
+            Assert.True(et.IsSignatureType);
+            Assert.True(et.IsGenericParameter);
+            Assert.False(et.IsGenericTypeParameter);
+            Assert.True(et.IsGenericMethodParameter);
+            Assert.Equal(5, et.GenericParameterPosition);
+
+            TestSignatureTypeInvariants(t);
+        }
+
+        [Fact]
+        public static void MakeSignaturePointerType()
+        {
+            Type t = Type.MakeGenericMethodParameter(5);
+            t = t.MakePointerType();
+            Assert.True(t.IsPointer);
+
+            Type et = t.GetElementType();
+            Assert.True(et.IsSignatureType);
+            Assert.True(et.IsGenericParameter);
+            Assert.False(et.IsGenericTypeParameter);
+            Assert.True(et.IsGenericMethodParameter);
+            Assert.Equal(5, et.GenericParameterPosition);
+
+            TestSignatureTypeInvariants(t);
+        }
+
+        [Theory]
+        [InlineData(typeof(List<>))]
+        [InlineData(typeof(Span<>))]
+        public static void MakeSignatureConstructedGenericType(Type genericTypeDefinition)
+        {
+            Type gmp = Type.MakeGenericMethodParameter(5);
+
+            Type[] testTypes = { genericTypeDefinition.MakeGenericType(gmp), Type.MakeGenericSignatureType(genericTypeDefinition, gmp) };
+            Assert.All(testTypes,
+                (Type t) =>
+                {
+                    Assert.True(t.IsConstructedGenericType);
+                    Assert.Equal(genericTypeDefinition, t.GetGenericTypeDefinition());
+                    Assert.Equal(1, t.GenericTypeArguments.Length);
+
+                    Type et = t.GenericTypeArguments[0];
+                    Assert.True(et.IsSignatureType);
+                    Assert.True(et.IsGenericParameter);
+                    Assert.False(et.IsGenericTypeParameter);
+                    Assert.True(et.IsGenericMethodParameter);
+                    Assert.Equal(5, et.GenericParameterPosition);
+
+                    TestSignatureTypeInvariants(t);
+                });
+        }
+
+        [Fact]
+        public static void MakeGenericSignatureTypeValidation()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("genericTypeDefinition", () => Type.MakeGenericSignatureType(null));
+            AssertExtensions.Throws<ArgumentNullException>("typeArguments", () => Type.MakeGenericSignatureType(typeof(IList<>), typeArguments: null));
+            AssertExtensions.Throws<ArgumentNullException>("typeArguments", () => Type.MakeGenericSignatureType(typeof(IList<>), new Type[] { null }));
+        }
+
+        private static Type ToSignatureType(this Type type)
+        {
+            if (type.IsTypeDefinition)
+                return type;
+            if (type.IsSZArray)
+                return type.GetElementType().ToSignatureType().MakeArrayType();
+            if (type.IsVariableBoundArray)
+                return type.GetElementType().ToSignatureType().MakeArrayType(type.GetArrayRank());
+            if (type.IsByRef)
+                return type.GetElementType().ToSignatureType().MakeByRefType();
+            if (type.IsPointer)
+                return type.GetElementType().ToSignatureType().MakePointerType();
+            if (type.IsConstructedGenericType)
+            {
+                Type[] genericTypeArguments = type.GenericTypeArguments.Select(t => t.ToSignatureType()).ToArray();
+                return type.GetGenericTypeDefinition().MakeGenericType(genericTypeArguments);
+            }
+            if (type.IsGenericTypeParameter)
+                return type;
+            if (type.IsGenericMethodParameter)
+                return Type.MakeGenericMethodParameter(type.GenericParameterPosition);
+
+            throw new Exception("Unknown type flavor.");
+        }
+
+        private static void AssertIsMarked(MemberInfo member, int value)
+        {
+            MarkerAttribute marker = member.GetCustomAttribute<MarkerAttribute>(inherit: false);
+            Assert.NotNull(marker);
+            Assert.Equal(value, marker.Value);
+        }
+
+        [AttributeUsage(AttributeTargets.All, Inherited = false)]
+        private sealed class MarkerAttribute : Attribute
+        {
+            public MarkerAttribute(int value)
+            {
+                Value = value;
+            }
+
+            public int Value { get; }
+        }
+
+        private sealed class TestClass1
+        {
+            [Marker(0)] public static void Moo(int x) { }
+            [Marker(1)] public static void Moo<T1>(int x) { }
+            [Marker(2)] public static void Moo<T1, T2>(int x) { }
+            [Marker(3)] public static void Moo<T1, T2, T3>(int x) {}
+        }
+
+        private class TestClass2
+        {
+            [Marker(0)] public static void Moo(int x, int[] y) { }
+            [Marker(1)] public static void Moo<T>(T x, T[] y) { }
+            [Marker(2)] public static void Moo<T>(int x, int[] y) { }
+            [Marker(3)] public static void Moo<T, U>(T x, U[] y) { }
+            [Marker(4)] public static void Moo<T, U>(int x, int[] y) { }
+        }
+
+        private class TestClass3<T,U>
+        {
+            public static void Moo(T p1, T[] p2, T[,] p3, ref T p4, TestClass3<T, T> p5, ref TestClass3<T, T[]>[,] p6) { }
+            public static void Moo(U p1, U[] p2, U[,] p3, ref U p4, TestClass3<U, U> p5, ref TestClass3<U, U[]>[,] p6) { }
+            public static void Moo<M>(T p1, T[] p2, T[,] p3, ref T p4, TestClass3<T, T> p5, ref TestClass3<T, T[]>[,] p6) { }
+            public static void Moo<M>(U p1, U[] p2, U[,] p3, ref U p4, TestClass3<U, U> p5, ref TestClass3<U, U[]>[,] p6) { }
+            public static void Moo<M>(M p1, M[] p2, M[,] p3, ref M p4, TestClass3<M, M> p5, ref TestClass3<M, M[]>[,] p6) { }
+            public static void Moo<M, N>(T p1, T[] p2, T[,] p3, ref T p4, TestClass3<T, T> p5, ref TestClass3<T, T[]>[,] p6) { }
+            public static void Moo<M, N>(U p1, U[] p2, U[,] p3, ref U p4, TestClass3<U, U> p5, ref TestClass3<U, U[]>[,] p6) { }
+            public static void Moo<M, N>(M p1, M[] p2, M[,] p3, ref M p4, TestClass3<M, M> p5, ref TestClass3<M, M[]>[,] p6) { }
+            public static void Moo<M, N>(N p1, N[] p2, N[,] p3, ref N p4, TestClass3<N, N> p5, ref TestClass3<N, N[]>[,] p6) { }
+        }
+
+        private class TestClass4<T> where T: NoOneSubclasses, new()
+        {
+            public static void Moo<M>(int p1, int p2) where M : NoOneSubclassesThisEither { }
+            public static void Moo<N, O>(TestClass4<N> p1, int p2) where N : NoOneSubclasses, new() { }
+            public static void Moo<N, O>(O p1, int p2) where N : NoOneSubclasses, new() { }
+        }
+
+        private class NoOneSubclasses { }
+        private class NoOneSubclassesThisEither { }
+
+        private static void TestSignatureTypeInvariants(Type type)
+        {
+            Assert.True(type.IsSignatureType);
+            Assert.False(type.IsTypeDefinition);
+            Assert.False(type.IsGenericTypeDefinition);
+            Assert.NotNull(type.Name);
+            Assert.Null(type.FullName);
+            Assert.Null(type.AssemblyQualifiedName);
+            Assert.NotNull(type.ToString());
+            Assert.Equal(MemberTypes.TypeInfo, type.MemberType);
+            Assert.Same(type, type.UnderlyingSystemType);
+
+            // SignatureTypes don't override Equality/GetHashCode at this time, but they don't promise never to do so either.
+            // Thus, we'll only test the most basic behavior.
+            Assert.True(type.Equals((object)type));
+            Assert.True(type.Equals((Type)type));
+            Assert.False(type.Equals((object)null));
+            Assert.False(type.Equals((Type)null));
+            int _ = type.GetHashCode();
+
+            bool categorized = false;
+            if (type.IsArray)
+            {
+                Assert.False(categorized);
+                categorized = true;
+                Assert.True(type.HasElementType);
+                Assert.True(type.IsSZArray != type.IsVariableBoundArray);
+                Assert.Equal(type.GetElementType().ContainsGenericParameters, type.ContainsGenericParameters);
+                string elementTypeName = type.GetElementType().Name;
+                if (type.IsSZArray)
+                {
+                    Assert.Equal(1, type.GetArrayRank());
+
+                    Assert.Equal(elementTypeName + "[]", type.Name);
+                }
+                else
+                {
+                    int rank = type.GetArrayRank();
+                    Assert.True(rank >= 1);
+                    if (rank == 1)
+                    {
+                        Assert.Equal(elementTypeName + "[*]", type.Name);
+                    }
+                    else
+                    {
+                        Assert.Equal(elementTypeName + "[" + new string(',', rank - 1) + "]", type.Name);
+                    }
+                }
+            }
+
+            if (type.IsByRef)
+            {
+                Assert.False(categorized);
+                categorized = true;
+
+                Assert.True(type.HasElementType);
+                Assert.Equal(type.GetElementType().ContainsGenericParameters, type.ContainsGenericParameters);
+                string elementTypeName = type.GetElementType().Name;
+                Assert.Equal(elementTypeName + "&", type.Name);
+            }
+
+            if (type.IsPointer)
+            {
+                Assert.False(categorized);
+                categorized = true;
+
+                Assert.True(type.HasElementType);
+                Assert.Equal(type.GetElementType().ContainsGenericParameters, type.ContainsGenericParameters);
+                string elementTypeName = type.GetElementType().Name;
+                Assert.Equal(elementTypeName + "*", type.Name);
+            }
+
+            if (type.IsConstructedGenericType)
+            {
+                Assert.False(categorized);
+                categorized = true;
+
+                Assert.True(type.IsGenericType);
+                Assert.False(type.HasElementType);
+                Type genericTypeDefinition = type.GetGenericTypeDefinition();
+                Assert.Equal(genericTypeDefinition.IsByRefLike, type.IsByRefLike);
+                Assert.NotNull(genericTypeDefinition);
+                Assert.True(genericTypeDefinition.IsGenericTypeDefinition);
+                Type[] genericTypeArguments = type.GetGenericArguments();
+                Type[] genericTypeArgumentsClone = type.GetGenericArguments();
+                Assert.NotSame(genericTypeArguments, genericTypeArgumentsClone);
+                Type[] genericTypeArgumentsFromProperty = type.GenericTypeArguments;
+                Type[] genericTypeArgumentsFromPropertyClone = type.GenericTypeArguments;
+                Assert.NotSame(genericTypeArgumentsFromProperty, genericTypeArgumentsFromPropertyClone);
+                for (int i = 0; i < genericTypeArguments.Length; i++)
+                {
+                    if (genericTypeArguments[i].IsSignatureType)
+                    {
+                        TestSignatureTypeInvariants(genericTypeArguments[i]);
+                    }
+                }
+                Assert.Equal(genericTypeDefinition.Name, type.Name);
+                Assert.Equal(genericTypeDefinition.Namespace, type.Namespace);
+
+
+                bool containsGenericParameters = false;
+                for (int i = 0; i < genericTypeArguments.Length; i++)
+                {
+                    containsGenericParameters = containsGenericParameters || genericTypeArguments[i].ContainsGenericParameters;
+                }
+                Assert.Equal(containsGenericParameters, type.ContainsGenericParameters);
+            }
+
+            if (type.IsGenericParameter)
+            {
+                Assert.False(categorized);
+                categorized = true;
+
+                Assert.False(type.HasElementType);
+                Assert.True(type.ContainsGenericParameters);
+                Assert.Null(type.Namespace);
+
+                int position = type.GenericParameterPosition;
+                Assert.True(position >= 0);
+
+                if (type.IsGenericTypeParameter)
+                {
+                    throw new Exception("Unexpected: There is no mechanism at this time to create Signature Types of generic parameters on types.");
+                }
+                else
+                {
+                    Assert.True(type.IsGenericMethodParameter);
+                    Assert.Equal("!!" + position, type.Name);
+                }
+            }
+
+            Assert.True(categorized);
+
+            if (type.HasElementType)
+            {
+                TestSignatureTypeInvariants(type.GetElementType());
+                Assert.Equal(type.GetElementType().Namespace, type.Namespace);
+            }
+            else
+            {
+                Assert.Null(type.GetElementType());
+            }
+
+            if (!type.IsConstructedGenericType)
+            {
+                Assert.Throws<InvalidOperationException>(() => type.GetGenericTypeDefinition());
+                Assert.Equal(0, type.GetGenericArguments().Length);
+                Assert.Equal(0, type.GenericTypeArguments.Length);
+                Assert.False(type.IsGenericType);
+                Assert.False(type.IsByRefLike);
+            }
+
+            if (!type.IsArray)
+            {
+                Assert.Throws<ArgumentException>(() => type.GetArrayRank());
+            }
+
+            if (!type.IsGenericParameter)
+            {
+                Assert.False(type.IsGenericTypeParameter);
+                Assert.False(type.IsGenericMethodParameter);
+                Assert.Throws<InvalidOperationException>(() => type.GenericParameterPosition);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Reflection/SignatureTypes.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Reflection/SignatureTypes.netcoreapp.cs
deleted file mode 100644 (file)
index f02c70e..0000000
+++ /dev/null
@@ -1,564 +0,0 @@
-// 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 System.Linq;
-using Xunit;
-
-namespace System.Reflection.Tests
-{
-    public static class SignatureTypeTests
-    {
-        [Fact]
-        public static void IsSignatureType()
-        {
-            // Executing [Theory] logic manually. Signature Types cannot be used in theory data because Xunit preemptively invokes an unguarded
-            // System.Type pretty printer that invokes members that Signature Types don't support.
-            foreach (object[] pair in IsSignatureTypeTestData)
-            {
-                Type type = (Type)(pair[0]);
-                bool expected = (bool)(pair[1]);
-
-                Assert.Equal(expected, type.IsSignatureType);
-            }
-        }
-
-        public static IEnumerable<object[]> IsSignatureTypeTestData
-        {
-            get
-            {
-                yield return new object[] { typeof(int), false };
-                yield return new object[] { typeof(int).MakeArrayType(), false };
-                yield return new object[] { typeof(int).MakeArrayType(1), false };
-                yield return new object[] { typeof(int).MakeArrayType(2), false };
-                yield return new object[] { typeof(int).MakeByRefType(), false };
-                yield return new object[] { typeof(int).MakePointerType(), false };
-                yield return new object[] { typeof(List<>).MakeGenericType(typeof(int)), false };
-                yield return new object[] { typeof(List<>).GetGenericArguments()[0], false };
-
-                Type sigType = Type.MakeGenericMethodParameter(2);
-
-                yield return new object[] { sigType, true };
-                yield return new object[] { sigType.MakeArrayType(), true };
-                yield return new object[] { sigType.MakeArrayType(1), true };
-                yield return new object[] { sigType.MakeArrayType(2), true };
-                yield return new object[] { sigType.MakeByRefType(), true };
-                yield return new object[] { sigType.MakePointerType(), true };
-                yield return new object[] { typeof(List<>).MakeGenericType(sigType), true };
-
-                yield return new object[] { Type.MakeGenericSignatureType(typeof(List<>), typeof(int)), true };
-                yield return new object[] { Type.MakeGenericSignatureType(typeof(List<>), sigType), true };
-            }
-        }
-
-        [Fact]
-        public static void GetMethodWithGenericParameterCount()
-        {
-            Type t = typeof(TestClass1);
-            const BindingFlags bf = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
-            Type[] args = { typeof(int) };
-            MethodInfo m;
-
-            Assert.Throws<AmbiguousMatchException>(() => t.GetMethod("Moo", bf, null, args, null));
-
-            for (int genericParameterCount = 0; genericParameterCount < 4; genericParameterCount++)
-            {
-                m = t.GetMethod("Moo", genericParameterCount, bf, null, args, null);
-                Assert.NotNull(m);
-                AssertIsMarked(m, genericParameterCount);
-
-                // Verify that generic parameter count filtering occurs before candidates are passed to the binder.
-                m = t.GetMethod("Moo", genericParameterCount, bf, new InflexibleBinder(genericParameterCount), args, null);
-                Assert.NotNull(m);
-                AssertIsMarked(m, genericParameterCount);
-            }
-
-            m = t.GetMethod("Moo", 4, bf, null, args, null);
-            Assert.Null(m);
-        }
-
-        private sealed class InflexibleBinder : Binder
-        {
-            public InflexibleBinder(int genericParameterCount)
-            {
-                _genericParameterCount = genericParameterCount;
-            }
-
-            public sealed override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture) => throw null;
-            public sealed override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state) => throw null;
-            public sealed override object ChangeType(object value, Type type, CultureInfo culture) => throw null;
-            public sealed override void ReorderArgumentArray(ref object[] args, object state) => throw null;
-
-            public sealed override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
-            {
-                foreach (MethodBase methodBase in match)
-                {
-                    Assert.True(methodBase is MethodInfo methodInfo && methodInfo.GetGenericArguments().Length == _genericParameterCount);
-                }
-                return Type.DefaultBinder.SelectMethod(bindingAttr, match, types, modifiers);
-            }
-
-            public sealed override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers) { throw null; }
-
-            private readonly int _genericParameterCount;
-        }
-
-        [Fact]
-        public static void GetMethodWithNegativeGenericParameterCount()
-        {
-            Type t = typeof(TestClass1);
-            const BindingFlags bf = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
-            Type[] args = { typeof(int) };
-            Assert.Throws<ArgumentException>(() => t.GetMethod("Moo", -1, bf, null, args, null));
-        }
-
-        [Theory]
-        [InlineData(true)]
-        [InlineData(false)]
-        public static void GetMethodOverloadTest(bool exactBinding)
-        {
-            Type t = typeof(TestClass2);
-            BindingFlags bf = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
-            if (exactBinding)
-            {
-                bf |= BindingFlags.ExactBinding;
-            }
-            Type[] args = { Type.MakeGenericMethodParameter(0), Type.MakeGenericMethodParameter(1).MakeArrayType() };
-            MethodInfo moo = t.GetMethod("Moo", 2, bf, null, args, null);
-            AssertIsMarked(moo, 3);
-        }
-
-        [Theory]
-        [InlineData(true)]
-        [InlineData(false)]
-        public static void SignatureTypeComparisonLogicCodeCoverage(bool exactBinding)
-        {
-            Type t = typeof(TestClass3<,>);
-            MethodInfo[] methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
-            BindingFlags bf = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
-            if (exactBinding)
-            {
-                bf |= BindingFlags.ExactBinding;
-            }
-
-            foreach (MethodInfo m in methods)
-            {
-                ParameterInfo[] parameters = m.GetParameters();
-                Type[] sigTypes = new Type[parameters.Length];
-                for (int i = 0; i < sigTypes.Length; i++)
-                {
-                    sigTypes[i] = parameters[i].ParameterType.ToSignatureType();
-                }
-                MethodInfo match = t.GetMethod("Moo", m.GetGenericArguments().Length, bf, null, sigTypes, null);
-                Assert.NotNull(match);
-                Assert.True(m.HasSameMetadataDefinitionAs(match));
-            }
-        }
-
-        [Fact]
-        public static void SigTypeResolutionResilience()
-        {
-            // Make sure the framework can't be tricked into throwing an exception because it tried to look up a nonexistent method generic parameter
-            // or trying to construct a generic type where the constraints don't validate.
-            Type t = typeof(TestClass4<>);
-            Type[] args = { typeof(TestClass4<>).MakeGenericType(Type.MakeGenericMethodParameter(1)), Type.MakeGenericMethodParameter(500) };
-            CountingBinder binder = new CountingBinder();
-            Assert.Null(t.GetMethod("Moo", BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, binder, args, null));
-            Assert.Equal(3, binder.NumCandidatesReceived);
-        }
-
-        private sealed class CountingBinder : Binder
-        {
-            public sealed override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture) => throw null;
-            public sealed override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state) => throw null;
-            public sealed override object ChangeType(object value, Type type, CultureInfo culture) => throw null;
-            public sealed override void ReorderArgumentArray(ref object[] args, object state) => throw null;
-
-            public sealed override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
-            {
-                NumCandidatesReceived += match.Length;
-                return Type.DefaultBinder.SelectMethod(bindingAttr, match, types, modifiers);
-            }
-
-            public sealed override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers) { throw null; }
-
-            public int NumCandidatesReceived { get; private set; }
-        }
-
-        [Theory]
-        [InlineData(0)]
-        [InlineData(3)]
-        [InlineData(400)]
-        [InlineData(int.MaxValue)]
-        public static void MakeGenericMethodParameter(int position)
-        {
-            Type t = Type.MakeGenericMethodParameter(position);
-            Assert.True(t.IsGenericParameter);
-            Assert.False(t.IsGenericTypeParameter);
-            Assert.True(t.IsGenericMethodParameter);
-            Assert.Equal(position, t.GenericParameterPosition);
-            TestSignatureTypeInvariants(t);
-        }
-
-        [Theory]
-        [InlineData(-1)]
-        [InlineData(-5)]
-        [InlineData(int.MinValue)]
-        public static void MakeGenericMethodParameterNegative(int position)
-        {
-            Assert.Throws<ArgumentException>(() => Type.MakeGenericMethodParameter(position));
-        }
-
-        [Fact]
-        public static void MakeSignatureArrayType()
-        {
-            Type t = Type.MakeGenericMethodParameter(5);
-            t = t.MakeArrayType();
-            Assert.True(t.IsArray);
-            Assert.True(t.IsSZArray);
-            Assert.Equal(1, t.GetArrayRank());
-
-            Type et = t.GetElementType();
-            Assert.True(et.IsSignatureType);
-            Assert.True(et.IsGenericParameter);
-            Assert.False(et.IsGenericTypeParameter);
-            Assert.True(et.IsGenericMethodParameter);
-            Assert.Equal(5, et.GenericParameterPosition);
-
-            TestSignatureTypeInvariants(t);
-        }
-
-        [Theory]
-        [InlineData(1)]
-        [InlineData(2)]
-        [InlineData(3)]
-        public static void MakeSignatureMdArrayType(int rank)
-        {
-            Type t = Type.MakeGenericMethodParameter(5);
-            t = t.MakeArrayType(rank);
-            Assert.True(t.IsArray);
-            Assert.True(t.IsVariableBoundArray);
-            Assert.Equal(rank, t.GetArrayRank());
-
-            TestSignatureTypeInvariants(t);
-        }
-
-        [Fact]
-        public static void MakeSignatureByRefType()
-        {
-            Type t = Type.MakeGenericMethodParameter(5);
-            t = t.MakeByRefType();
-            Assert.True(t.IsByRef);
-
-            Type et = t.GetElementType();
-            Assert.True(et.IsSignatureType);
-            Assert.True(et.IsGenericParameter);
-            Assert.False(et.IsGenericTypeParameter);
-            Assert.True(et.IsGenericMethodParameter);
-            Assert.Equal(5, et.GenericParameterPosition);
-
-            TestSignatureTypeInvariants(t);
-        }
-
-        [Fact]
-        public static void MakeSignaturePointerType()
-        {
-            Type t = Type.MakeGenericMethodParameter(5);
-            t = t.MakePointerType();
-            Assert.True(t.IsPointer);
-
-            Type et = t.GetElementType();
-            Assert.True(et.IsSignatureType);
-            Assert.True(et.IsGenericParameter);
-            Assert.False(et.IsGenericTypeParameter);
-            Assert.True(et.IsGenericMethodParameter);
-            Assert.Equal(5, et.GenericParameterPosition);
-
-            TestSignatureTypeInvariants(t);
-        }
-
-        [Theory]
-        [InlineData(typeof(List<>))]
-        [InlineData(typeof(Span<>))]
-        public static void MakeSignatureConstructedGenericType(Type genericTypeDefinition)
-        {
-            Type gmp = Type.MakeGenericMethodParameter(5);
-
-            Type[] testTypes = { genericTypeDefinition.MakeGenericType(gmp), Type.MakeGenericSignatureType(genericTypeDefinition, gmp) };
-            Assert.All(testTypes,
-                (Type t) =>
-                {
-                    Assert.True(t.IsConstructedGenericType);
-                    Assert.Equal(genericTypeDefinition, t.GetGenericTypeDefinition());
-                    Assert.Equal(1, t.GenericTypeArguments.Length);
-
-                    Type et = t.GenericTypeArguments[0];
-                    Assert.True(et.IsSignatureType);
-                    Assert.True(et.IsGenericParameter);
-                    Assert.False(et.IsGenericTypeParameter);
-                    Assert.True(et.IsGenericMethodParameter);
-                    Assert.Equal(5, et.GenericParameterPosition);
-
-                    TestSignatureTypeInvariants(t);
-                });
-        }
-
-        [Fact]
-        public static void MakeGenericSignatureTypeValidation()
-        {
-            AssertExtensions.Throws<ArgumentNullException>("genericTypeDefinition", () => Type.MakeGenericSignatureType(null));
-            AssertExtensions.Throws<ArgumentNullException>("typeArguments", () => Type.MakeGenericSignatureType(typeof(IList<>), typeArguments: null));
-            AssertExtensions.Throws<ArgumentNullException>("typeArguments", () => Type.MakeGenericSignatureType(typeof(IList<>), new Type[] { null }));
-        }
-
-        private static Type ToSignatureType(this Type type)
-        {
-            if (type.IsTypeDefinition)
-                return type;
-            if (type.IsSZArray)
-                return type.GetElementType().ToSignatureType().MakeArrayType();
-            if (type.IsVariableBoundArray)
-                return type.GetElementType().ToSignatureType().MakeArrayType(type.GetArrayRank());
-            if (type.IsByRef)
-                return type.GetElementType().ToSignatureType().MakeByRefType();
-            if (type.IsPointer)
-                return type.GetElementType().ToSignatureType().MakePointerType();
-            if (type.IsConstructedGenericType)
-            {
-                Type[] genericTypeArguments = type.GenericTypeArguments.Select(t => t.ToSignatureType()).ToArray();
-                return type.GetGenericTypeDefinition().MakeGenericType(genericTypeArguments);
-            }
-            if (type.IsGenericTypeParameter)
-                return type;
-            if (type.IsGenericMethodParameter)
-                return Type.MakeGenericMethodParameter(type.GenericParameterPosition);
-
-            throw new Exception("Unknown type flavor.");
-        }
-
-        private static void AssertIsMarked(MemberInfo member, int value)
-        {
-            MarkerAttribute marker = member.GetCustomAttribute<MarkerAttribute>(inherit: false);
-            Assert.NotNull(marker);
-            Assert.Equal(value, marker.Value);
-        }
-
-        [AttributeUsage(AttributeTargets.All, Inherited = false)]
-        private sealed class MarkerAttribute : Attribute
-        {
-            public MarkerAttribute(int value)
-            {
-                Value = value;
-            }
-
-            public int Value { get; }
-        }
-
-        private sealed class TestClass1
-        {
-            [Marker(0)] public static void Moo(int x) { }
-            [Marker(1)] public static void Moo<T1>(int x) { }
-            [Marker(2)] public static void Moo<T1, T2>(int x) { }
-            [Marker(3)] public static void Moo<T1, T2, T3>(int x) {}
-        }
-
-        private class TestClass2
-        {
-            [Marker(0)] public static void Moo(int x, int[] y) { }
-            [Marker(1)] public static void Moo<T>(T x, T[] y) { }
-            [Marker(2)] public static void Moo<T>(int x, int[] y) { }
-            [Marker(3)] public static void Moo<T, U>(T x, U[] y) { }
-            [Marker(4)] public static void Moo<T, U>(int x, int[] y) { }
-        }
-
-        private class TestClass3<T,U>
-        {
-            public static void Moo(T p1, T[] p2, T[,] p3, ref T p4, TestClass3<T, T> p5, ref TestClass3<T, T[]>[,] p6) { }
-            public static void Moo(U p1, U[] p2, U[,] p3, ref U p4, TestClass3<U, U> p5, ref TestClass3<U, U[]>[,] p6) { }
-            public static void Moo<M>(T p1, T[] p2, T[,] p3, ref T p4, TestClass3<T, T> p5, ref TestClass3<T, T[]>[,] p6) { }
-            public static void Moo<M>(U p1, U[] p2, U[,] p3, ref U p4, TestClass3<U, U> p5, ref TestClass3<U, U[]>[,] p6) { }
-            public static void Moo<M>(M p1, M[] p2, M[,] p3, ref M p4, TestClass3<M, M> p5, ref TestClass3<M, M[]>[,] p6) { }
-            public static void Moo<M, N>(T p1, T[] p2, T[,] p3, ref T p4, TestClass3<T, T> p5, ref TestClass3<T, T[]>[,] p6) { }
-            public static void Moo<M, N>(U p1, U[] p2, U[,] p3, ref U p4, TestClass3<U, U> p5, ref TestClass3<U, U[]>[,] p6) { }
-            public static void Moo<M, N>(M p1, M[] p2, M[,] p3, ref M p4, TestClass3<M, M> p5, ref TestClass3<M, M[]>[,] p6) { }
-            public static void Moo<M, N>(N p1, N[] p2, N[,] p3, ref N p4, TestClass3<N, N> p5, ref TestClass3<N, N[]>[,] p6) { }
-        }
-
-        private class TestClass4<T> where T: NoOneSubclasses, new()
-        {
-            public static void Moo<M>(int p1, int p2) where M : NoOneSubclassesThisEither { }
-            public static void Moo<N, O>(TestClass4<N> p1, int p2) where N : NoOneSubclasses, new() { }
-            public static void Moo<N, O>(O p1, int p2) where N : NoOneSubclasses, new() { }
-        }
-
-        private class NoOneSubclasses { }
-        private class NoOneSubclassesThisEither { }
-
-        private static void TestSignatureTypeInvariants(Type type)
-        {
-            Assert.True(type.IsSignatureType);
-            Assert.False(type.IsTypeDefinition);
-            Assert.False(type.IsGenericTypeDefinition);
-            Assert.NotNull(type.Name);
-            Assert.Null(type.FullName);
-            Assert.Null(type.AssemblyQualifiedName);
-            Assert.NotNull(type.ToString());
-            Assert.Equal(MemberTypes.TypeInfo, type.MemberType);
-            Assert.Same(type, type.UnderlyingSystemType);
-
-            // SignatureTypes don't override Equality/GetHashCode at this time, but they don't promise never to do so either.
-            // Thus, we'll only test the most basic behavior.
-            Assert.True(type.Equals((object)type));
-            Assert.True(type.Equals((Type)type));
-            Assert.False(type.Equals((object)null));
-            Assert.False(type.Equals((Type)null));
-            int _ = type.GetHashCode();
-
-            bool categorized = false;
-            if (type.IsArray)
-            {
-                Assert.False(categorized);
-                categorized = true;
-                Assert.True(type.HasElementType);
-                Assert.True(type.IsSZArray != type.IsVariableBoundArray);
-                Assert.Equal(type.GetElementType().ContainsGenericParameters, type.ContainsGenericParameters);
-                string elementTypeName = type.GetElementType().Name;
-                if (type.IsSZArray)
-                {
-                    Assert.Equal(1, type.GetArrayRank());
-
-                    Assert.Equal(elementTypeName + "[]", type.Name);
-                }
-                else
-                {
-                    int rank = type.GetArrayRank();
-                    Assert.True(rank >= 1);
-                    if (rank == 1)
-                    {
-                        Assert.Equal(elementTypeName + "[*]", type.Name);
-                    }
-                    else
-                    {
-                        Assert.Equal(elementTypeName + "[" + new string(',', rank - 1) + "]", type.Name);
-                    }
-                }
-            }
-
-            if (type.IsByRef)
-            {
-                Assert.False(categorized);
-                categorized = true;
-
-                Assert.True(type.HasElementType);
-                Assert.Equal(type.GetElementType().ContainsGenericParameters, type.ContainsGenericParameters);
-                string elementTypeName = type.GetElementType().Name;
-                Assert.Equal(elementTypeName + "&", type.Name);
-            }
-
-            if (type.IsPointer)
-            {
-                Assert.False(categorized);
-                categorized = true;
-
-                Assert.True(type.HasElementType);
-                Assert.Equal(type.GetElementType().ContainsGenericParameters, type.ContainsGenericParameters);
-                string elementTypeName = type.GetElementType().Name;
-                Assert.Equal(elementTypeName + "*", type.Name);
-            }
-
-            if (type.IsConstructedGenericType)
-            {
-                Assert.False(categorized);
-                categorized = true;
-
-                Assert.True(type.IsGenericType);
-                Assert.False(type.HasElementType);
-                Type genericTypeDefinition = type.GetGenericTypeDefinition();
-                Assert.Equal(genericTypeDefinition.IsByRefLike, type.IsByRefLike);
-                Assert.NotNull(genericTypeDefinition);
-                Assert.True(genericTypeDefinition.IsGenericTypeDefinition);
-                Type[] genericTypeArguments = type.GetGenericArguments();
-                Type[] genericTypeArgumentsClone = type.GetGenericArguments();
-                Assert.NotSame(genericTypeArguments, genericTypeArgumentsClone);
-                Type[] genericTypeArgumentsFromProperty = type.GenericTypeArguments;
-                Type[] genericTypeArgumentsFromPropertyClone = type.GenericTypeArguments;
-                Assert.NotSame(genericTypeArgumentsFromProperty, genericTypeArgumentsFromPropertyClone);
-                for (int i = 0; i < genericTypeArguments.Length; i++)
-                {
-                    if (genericTypeArguments[i].IsSignatureType)
-                    {
-                        TestSignatureTypeInvariants(genericTypeArguments[i]);
-                    }
-                }
-                Assert.Equal(genericTypeDefinition.Name, type.Name);
-                Assert.Equal(genericTypeDefinition.Namespace, type.Namespace);
-
-
-                bool containsGenericParameters = false;
-                for (int i = 0; i < genericTypeArguments.Length; i++)
-                {
-                    containsGenericParameters = containsGenericParameters || genericTypeArguments[i].ContainsGenericParameters;
-                }
-                Assert.Equal(containsGenericParameters, type.ContainsGenericParameters);
-            }
-
-            if (type.IsGenericParameter)
-            {
-                Assert.False(categorized);
-                categorized = true;
-
-                Assert.False(type.HasElementType);
-                Assert.True(type.ContainsGenericParameters);
-                Assert.Null(type.Namespace);
-
-                int position = type.GenericParameterPosition;
-                Assert.True(position >= 0);
-
-                if (type.IsGenericTypeParameter)
-                {
-                    throw new Exception("Unexpected: There is no mechanism at this time to create Signature Types of generic parameters on types.");
-                }
-                else
-                {
-                    Assert.True(type.IsGenericMethodParameter);
-                    Assert.Equal("!!" + position, type.Name);
-                }
-            }
-
-            Assert.True(categorized);
-
-            if (type.HasElementType)
-            {
-                TestSignatureTypeInvariants(type.GetElementType());
-                Assert.Equal(type.GetElementType().Namespace, type.Namespace);
-            }
-            else
-            {
-                Assert.Null(type.GetElementType());
-            }
-
-            if (!type.IsConstructedGenericType)
-            {
-                Assert.Throws<InvalidOperationException>(() => type.GetGenericTypeDefinition());
-                Assert.Equal(0, type.GetGenericArguments().Length);
-                Assert.Equal(0, type.GenericTypeArguments.Length);
-                Assert.False(type.IsGenericType);
-                Assert.False(type.IsByRefLike);
-            }
-
-            if (!type.IsArray)
-            {
-                Assert.Throws<ArgumentException>(() => type.GetArrayRank());
-            }
-
-            if (!type.IsGenericParameter)
-            {
-                Assert.False(type.IsGenericTypeParameter);
-                Assert.False(type.IsGenericMethodParameter);
-                Assert.Throws<InvalidOperationException>(() => type.GenericParameterPosition);
-            }
-        }
-    }
-}
index 9ac27116e3e91b6ec2fb228b69aabc3e0e0436d1..1c036611f299b2f3a0740d6c53c918e00b944206 100644 (file)
@@ -2,6 +2,7 @@
 // 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
@@ -42,5 +43,42 @@ 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);
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Reflection/TypeDelegatorTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Reflection/TypeDelegatorTests.netcoreapp.cs
deleted file mode 100644 (file)
index 8009dc9..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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);
-        }
-    }
-}
index c1d141ffe50f51ec3d619d407be556ccb77a56af..66ba84f4353797a2b9d5376380b0e95c7dfe9c59 100644 (file)
@@ -6,7 +6,7 @@ using Xunit;
 
 namespace System.Runtime.CompilerServices.Tests
 {
-    public static partial class AttributesTests
+    public static class AttributesTests
     {
         [Fact]
         public static void AccessedThroughPropertyAttributeTests()
@@ -252,5 +252,33 @@ namespace System.Runtime.CompilerServices.Tests
         {
             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();
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.netcoreapp.cs
deleted file mode 100644 (file)
index 089b81d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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();
-        }
-    }
-}
index c7964cdada13519454c97148515d8273ba6163cc..069826ac6a352d3dd9d4d5c9ed09979cc039c993 100644 (file)
@@ -2,14 +2,17 @@
 // 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()
@@ -318,5 +321,285 @@ namespace System.Runtime.CompilerServices.Tests
                 // 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);
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/ConditionalWeakTableTests.netcoreapp.cs
deleted file mode 100644 (file)
index ca44f62..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-// 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);
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/MethodImplAttributeTests.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/MethodImplAttributeTests.cs
new file mode 100644 (file)
index 0000000..2b091f6
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.Runtime.CompilerServices.Tests
+{
+    public static class MethodImplAttributeTests
+    {
+        [Fact]
+        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
+        public static void AggressiveOptimizationTest()
+        {
+            MethodImplAttributes implAttributes = MethodBase.GetCurrentMethod().MethodImplementationFlags;
+            Assert.Equal(MethodImplAttributes.AggressiveOptimization, implAttributes);
+            Assert.Equal(MethodImplOptions.AggressiveOptimization, (MethodImplOptions)implAttributes);
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/MethodImplAttributeTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/MethodImplAttributeTests.netcoreapp.cs
deleted file mode 100644 (file)
index 2b091f6..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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.Runtime.CompilerServices.Tests
-{
-    public static class MethodImplAttributeTests
-    {
-        [Fact]
-        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
-        public static void AggressiveOptimizationTest()
-        {
-            MethodImplAttributes implAttributes = MethodBase.GetCurrentMethod().MethodImplementationFlags;
-            Assert.Equal(MethodImplAttributes.AggressiveOptimization, implAttributes);
-            Assert.Equal(MethodImplOptions.AggressiveOptimization, (MethodImplOptions)implAttributes);
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeFeatureTests.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeFeatureTests.cs
new file mode 100644 (file)
index 0000000..2177169
--- /dev/null
@@ -0,0 +1,38 @@
+// 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.CompilerServices;
+using Xunit;
+
+namespace System.Runtime.CompilerServices.Tests
+{
+    public static class RuntimeFeatureTests
+    {
+        [Fact]
+        public static void PortablePdb()
+        {
+            Assert.True(RuntimeFeature.IsSupported("PortablePdb"));
+        }
+
+        [Fact]
+        public static void DynamicCode()
+        {
+            Assert.Equal(RuntimeFeature.IsDynamicCodeSupported, RuntimeFeature.IsSupported("IsDynamicCodeSupported"));
+            Assert.Equal(RuntimeFeature.IsDynamicCodeCompiled, RuntimeFeature.IsSupported("IsDynamicCodeCompiled"));
+
+            if (RuntimeFeature.IsDynamicCodeCompiled)
+            {
+                Assert.True(RuntimeFeature.IsDynamicCodeSupported);
+            }
+        }
+
+        [Fact]
+        public static void DynamicCode_Jit()
+        {
+            Assert.True(RuntimeFeature.IsDynamicCodeSupported);
+            Assert.True(RuntimeFeature.IsDynamicCodeCompiled);
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeFeatureTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeFeatureTests.netcoreapp.cs
deleted file mode 100644 (file)
index 36f9f36..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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.CompilerServices;
-using Xunit;
-
-namespace System.Runtime.CompilerServices.Tests
-{
-    public static partial class RuntimeFeatureTests
-    {
-        [Fact]
-        public static void PortablePdb()
-        {
-            Assert.True(RuntimeFeature.IsSupported("PortablePdb"));
-        }
-
-        [Fact]
-        public static void DynamicCode()
-        {
-            Assert.Equal(RuntimeFeature.IsDynamicCodeSupported, RuntimeFeature.IsSupported("IsDynamicCodeSupported"));
-            Assert.Equal(RuntimeFeature.IsDynamicCodeCompiled, RuntimeFeature.IsSupported("IsDynamicCodeCompiled"));
-
-            if (RuntimeFeature.IsDynamicCodeCompiled)
-            {
-                Assert.True(RuntimeFeature.IsDynamicCodeSupported);
-            }
-        }
-
-        [Fact]
-        public static void DynamicCode_Jit()
-        {
-            Assert.True(RuntimeFeature.IsDynamicCodeSupported);
-            Assert.True(RuntimeFeature.IsDynamicCodeCompiled);
-        }
-    }
-}
index 266196a77aeac99fd920d7e6296cc56da5f6a2f3..bd4054da4df0690f4c791273882407c755335260 100644 (file)
@@ -7,11 +7,12 @@ using System.Reflection;
 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()
@@ -178,30 +179,104 @@ namespace System.Runtime.CompilerServices.Tests
             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()
         {
@@ -218,4 +293,24 @@ namespace System.Runtime.CompilerServices.Tests
             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;
+            }
+        }
+    }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeHelpersTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/RuntimeHelpersTests.netcoreapp.cs
deleted file mode 100644 (file)
index 3c71a58..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-// 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;
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Runtime/ExceptionServices/ExceptionDispatchInfoTests.cs b/src/libraries/System.Runtime/tests/System/Runtime/ExceptionServices/ExceptionDispatchInfoTests.cs
new file mode 100644 (file)
index 0000000..de28c30
--- /dev/null
@@ -0,0 +1,73 @@
+// 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.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Text.RegularExpressions;
+using Xunit;
+
+namespace System.Runtime.ExceptionServices.Tests
+{
+    public class ExceptionDispatchInfoTests
+    {
+        [Fact]
+        public static void StaticThrow_NullArgument_ThrowArgumentNullException()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("source", () => ExceptionDispatchInfo.Throw(null));
+        }
+
+        [Fact]
+        public static void StaticThrow_UpdatesStackTraceAppropriately()
+        {
+            const string RethrowMessageSubstring = "End of stack trace";
+            var e = new FormatException();
+            for (int i = 0; i < 3; i++)
+            {
+                Assert.Same(e, Assert.Throws<FormatException>(() => ExceptionDispatchInfo.Throw(e)));
+                Assert.Equal(i, Regex.Matches(e.StackTrace, RethrowMessageSubstring).Count);
+            }
+        }
+
+        [Fact]
+        public static void SetCurrentStackTrace_Invalid_Throws()
+        {
+            Exception e;
+
+            // Null argument
+            e = null;
+            AssertExtensions.Throws<ArgumentNullException>("source", () => ExceptionDispatchInfo.SetCurrentStackTrace(e));
+
+            // Previously set current stack
+            e = new Exception();
+            ExceptionDispatchInfo.SetCurrentStackTrace(e);
+            Assert.Throws<InvalidOperationException>(() => ExceptionDispatchInfo.SetCurrentStackTrace(e));
+
+            // Previously thrown
+            e = new Exception();
+            try { throw e; } catch { }
+            Assert.Throws<InvalidOperationException>(() => ExceptionDispatchInfo.SetCurrentStackTrace(e));
+        }
+
+        [Fact]
+        public static void SetCurrentStackTrace_IncludedInExceptionStackTrace()
+        {
+            Exception e;
+
+            e = new Exception();
+            ABCDEFGHIJKLMNOPQRSTUVWXYZ(e);
+            Assert.Contains(nameof(ABCDEFGHIJKLMNOPQRSTUVWXYZ), e.StackTrace);
+
+            e = new Exception();
+            ABCDEFGHIJKLMNOPQRSTUVWXYZ(e);
+            try { throw e; } catch { }
+            Assert.Contains(nameof(ABCDEFGHIJKLMNOPQRSTUVWXYZ), e.StackTrace);
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
+        private static void ABCDEFGHIJKLMNOPQRSTUVWXYZ(Exception e)
+        {
+            Assert.Same(e, ExceptionDispatchInfo.SetCurrentStackTrace(e));
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Runtime/ExceptionServices/ExceptionDispatchInfoTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Runtime/ExceptionServices/ExceptionDispatchInfoTests.netcoreapp.cs
deleted file mode 100644 (file)
index f9b18bf..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-// 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.ComponentModel;
-using System.Runtime.CompilerServices;
-using System.Text.RegularExpressions;
-using Xunit;
-
-namespace System.Runtime.ExceptionServices.Tests
-{
-    public partial class ExceptionDispatchInfoTests
-    {
-        [Fact]
-        public static void StaticThrow_NullArgument_ThrowArgumentNullException()
-        {
-            AssertExtensions.Throws<ArgumentNullException>("source", () => ExceptionDispatchInfo.Throw(null));
-        }
-
-        [Fact]
-        public static void StaticThrow_UpdatesStackTraceAppropriately()
-        {
-            const string RethrowMessageSubstring = "End of stack trace";
-            var e = new FormatException();
-            for (int i = 0; i < 3; i++)
-            {
-                Assert.Same(e, Assert.Throws<FormatException>(() => ExceptionDispatchInfo.Throw(e)));
-                Assert.Equal(i, Regex.Matches(e.StackTrace, RethrowMessageSubstring).Count);
-            }
-        }
-
-        [Fact]
-        public static void SetCurrentStackTrace_Invalid_Throws()
-        {
-            Exception e;
-
-            // Null argument
-            e = null;
-            AssertExtensions.Throws<ArgumentNullException>("source", () => ExceptionDispatchInfo.SetCurrentStackTrace(e));
-
-            // Previously set current stack
-            e = new Exception();
-            ExceptionDispatchInfo.SetCurrentStackTrace(e);
-            Assert.Throws<InvalidOperationException>(() => ExceptionDispatchInfo.SetCurrentStackTrace(e));
-
-            // Previously thrown
-            e = new Exception();
-            try { throw e; } catch { }
-            Assert.Throws<InvalidOperationException>(() => ExceptionDispatchInfo.SetCurrentStackTrace(e));
-        }
-
-        [Fact]
-        public static void SetCurrentStackTrace_IncludedInExceptionStackTrace()
-        {
-            Exception e;
-
-            e = new Exception();
-            ABCDEFGHIJKLMNOPQRSTUVWXYZ(e);
-            Assert.Contains(nameof(ABCDEFGHIJKLMNOPQRSTUVWXYZ), e.StackTrace);
-
-            e = new Exception();
-            ABCDEFGHIJKLMNOPQRSTUVWXYZ(e);
-            try { throw e; } catch { }
-            Assert.Contains(nameof(ABCDEFGHIJKLMNOPQRSTUVWXYZ), e.StackTrace);
-        }
-
-        [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
-        private static void ABCDEFGHIJKLMNOPQRSTUVWXYZ(Exception e)
-        {
-            Assert.Same(e, ExceptionDispatchInfo.SetCurrentStackTrace(e));
-        }
-    }
-}
index 439b5a23943d55664026494af08db028b195d94d..3256c299a592aea8d0f24794fe53245ad6927c33 100644 (file)
@@ -309,5 +309,104 @@ namespace System.Tests
             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));
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/SByteTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/SByteTests.netcoreapp.cs
deleted file mode 100644 (file)
index 513b9b5..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// 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));
-            }
-        }
-    }
-}
index b7c6bf9655e08440a9bf270227ccc1c1f97d65ab..a030d0c04fa1e249c1437d360f5a747419ea69f5 100644 (file)
@@ -491,5 +491,218 @@ namespace System.Tests
             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));
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/SingleTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/SingleTests.netcoreapp.cs
deleted file mode 100644 (file)
index 22423d4..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-// 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));
-        }
-    }
-}
index d3ef247bb12858865748762fa3fb09fc03655f5b..08bdba56dc90bdefb12305de41e89c017922951f 100644 (file)
@@ -7,7 +7,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class StringComparerTests
+    public class StringComparerTests
     {
         [Fact]
         public void Create_InvalidArguments_Throws()
@@ -109,5 +109,32 @@ namespace System.Tests
             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"));
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/StringComparerTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/StringComparerTests.netcoreapp.cs
deleted file mode 100644 (file)
index a31986c..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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"));
-        }
-    }
-}
index ce4f67216f76072fc6a7179b5a0c321579227acc..82dbbb4486df1f635aabae1b7e54751e36855de3 100644 (file)
@@ -10,7 +10,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class StringGetHashCodeTests
+    public class StringGetHashCodeTests
     {
         /// <summary>
         /// Ensure that hash codes are randomized by getting the hash in two processes
@@ -61,5 +61,44 @@ namespace System.Tests
             () => { 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
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/StringGetHashCodeTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/StringGetHashCodeTests.netcoreapp.cs
deleted file mode 100644 (file)
index f3479d3..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/StringTests.cs b/src/libraries/System.Runtime/tests/System/StringTests.cs
new file mode 100644 (file)
index 0000000..831b716
--- /dev/null
@@ -0,0 +1,1611 @@
+// 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.Reflection.Emit;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+using Microsoft.DotNet.RemoteExecutor;
+using Xunit;
+
+namespace System.Tests
+{
+    public partial class StringTests
+    {
+        [Theory]
+        [InlineData(0, 0)]
+        [InlineData(3, 1)]
+        public static void Ctor_CharSpan_EmptyString(int length, int offset)
+        {
+            Assert.Same(string.Empty, new string(new ReadOnlySpan<char>(new char[length], offset, 0)));
+        }
+
+        [Fact]
+        public static unsafe void Ctor_CharSpan_Empty()
+        {
+            Assert.Same(string.Empty, new string((ReadOnlySpan<char>)null));
+            Assert.Same(string.Empty, new string(ReadOnlySpan<char>.Empty));
+        }
+
+        [Theory]
+        [InlineData(new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\0' }, 0, 8, "abcdefgh")]
+        [InlineData(new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\0', 'i', 'j', 'k' }, 0, 12, "abcdefgh\0ijk")]
+        [InlineData(new char[] { 'a', 'b', 'c' }, 0, 0, "")]
+        [InlineData(new char[] { 'a', 'b', 'c' }, 0, 1, "a")]
+        [InlineData(new char[] { 'a', 'b', 'c' }, 2, 1, "c")]
+        [InlineData(new char[] { '\u8001', '\u8002', '\ufffd', '\u1234', '\ud800', '\udfff' }, 0, 6, "\u8001\u8002\ufffd\u1234\ud800\udfff")]
+        public static void Ctor_CharSpan(char[] valueArray, int startIndex, int length, string expected)
+        {
+            var span = new ReadOnlySpan<char>(valueArray, startIndex, length);
+            Assert.Equal(expected, new string(span));
+        }
+
+        [Fact]
+        public static unsafe void Ctor_CharPtr_DoesNotAccessInvalidPage()
+        {
+            // Allocates a buffer of all 'x' followed by a null terminator,
+            // then attempts to create a string instance from this at various offsets.
+
+            const int MaxCharCount = 128;
+            using BoundedMemory<char> boundedMemory = BoundedMemory.Allocate<char>(MaxCharCount);
+            boundedMemory.Span.Fill('x');
+            boundedMemory.Span[MaxCharCount - 1] = '\0';
+            boundedMemory.MakeReadonly();
+
+            using MemoryHandle memoryHandle = boundedMemory.Memory.Pin();
+
+            for (int i = 0; i < MaxCharCount; i++)
+            {
+                string expectedString = new string('x', MaxCharCount - i - 1);
+                string actualString = new string((char*)memoryHandle.Pointer + i);
+                Assert.Equal(expectedString, actualString);
+            }
+        }
+
+        [ConditionalFact(nameof(IsSimpleActiveCodePage))]
+        public static unsafe void Ctor_SBytePtr_DoesNotAccessInvalidPage()
+        {
+            // Allocates a buffer of all ' ' followed by a null terminator,
+            // then attempts to create a string instance from this at various offsets.
+            // We use U+0020 SPACE instead of any other character because it lives
+            // at offset 0x20 across every supported code page.
+
+            const int MaxByteCount = 128;
+            using BoundedMemory<sbyte> boundedMemory = BoundedMemory.Allocate<sbyte>(MaxByteCount);
+            boundedMemory.Span.Fill((sbyte)' ');
+            boundedMemory.Span[MaxByteCount - 1] = (sbyte)'\0';
+            boundedMemory.MakeReadonly();
+
+            using MemoryHandle memoryHandle = boundedMemory.Memory.Pin();
+
+            for (int i = 0; i < MaxByteCount; i++)
+            {
+                string expectedString = new string(' ', MaxByteCount - i - 1);
+                string actualString = new string((sbyte*)memoryHandle.Pointer + i);
+                Assert.Equal(expectedString, actualString);
+            }
+        }
+
+        [Fact]
+        public static void Create_InvalidArguments_Throw()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("action", () => string.Create(-1, 0, null));
+            AssertExtensions.Throws<ArgumentOutOfRangeException>("length", () => string.Create(-1, 0, (span, state) => { }));
+        }
+
+        [Fact]
+        public static void Create_Length0_ReturnsEmptyString()
+        {
+            bool actionInvoked = false;
+            Assert.Same(string.Empty, string.Create(0, 0, (span, state) => actionInvoked = true));
+            Assert.False(actionInvoked);
+        }
+
+        [Fact]
+        public static void Create_NullState_Allowed()
+        {
+            string result = string.Create(1, (object)null, (span, state) =>
+            {
+                span[0] = 'a';
+                Assert.Null(state);
+            });
+            Assert.Equal("a", result);
+        }
+
+        [Fact]
+        public static void Create_ClearsMemory()
+        {
+            const int Length = 10;
+            string result = string.Create(Length, (object)null, (span, state) =>
+            {
+                for (int i = 0; i < span.Length; i++)
+                {
+                    Assert.Equal('\0', span[i]);
+                }
+            });
+            Assert.Equal(new string('\0', Length), result);
+        }
+
+        [Theory]
+        [InlineData("a")]
+        [InlineData("this is a test")]
+        [InlineData("\0\u8001\u8002\ufffd\u1234\ud800\udfff")]
+        public static void Create_ReturnsExpectedString(string expected)
+        {
+            char[] input = expected.ToCharArray();
+            string result = string.Create(input.Length, input, (span, state) =>
+            {
+                Assert.Same(input, state);
+                for (int i = 0; i < state.Length; i++)
+                {
+                    span[i] = state[i];
+                }
+            });
+            Assert.Equal(expected, result);
+        }
+
+        [Theory]
+        [InlineData("Hello", 'H', true)]
+        [InlineData("Hello", 'Z', false)]
+        [InlineData("Hello", 'e', true)]
+        [InlineData("Hello", 'E', false)]
+        [InlineData("", 'H', false)]
+        public static void Contains(string s, char value, bool expected)
+        {
+            Assert.Equal(expected, s.Contains(value));
+
+            ReadOnlySpan<char> span = s.AsSpan();
+            Assert.Equal(expected, span.Contains(value));
+        }
+
+        [Theory]
+        // CurrentCulture
+        [InlineData("Hello", 'H', StringComparison.CurrentCulture, true)]
+        [InlineData("Hello", 'Z', StringComparison.CurrentCulture, false)]
+        [InlineData("Hello", 'e', StringComparison.CurrentCulture, true)]
+        [InlineData("Hello", 'E', StringComparison.CurrentCulture, false)]
+        [InlineData("", 'H', StringComparison.CurrentCulture, false)]
+        // CurrentCultureIgnoreCase
+        [InlineData("Hello", 'H', StringComparison.CurrentCultureIgnoreCase, true)]
+        [InlineData("Hello", 'Z', StringComparison.CurrentCultureIgnoreCase, false)]
+        [InlineData("Hello", 'e', StringComparison.CurrentCultureIgnoreCase, true)]
+        [InlineData("Hello", 'E', StringComparison.CurrentCultureIgnoreCase, true)]
+        [InlineData("", 'H', StringComparison.CurrentCultureIgnoreCase, false)]
+        // InvariantCulture
+        [InlineData("Hello", 'H', StringComparison.InvariantCulture, true)]
+        [InlineData("Hello", 'Z', StringComparison.InvariantCulture, false)]
+        [InlineData("Hello", 'e', StringComparison.InvariantCulture, true)]
+        [InlineData("Hello", 'E', StringComparison.InvariantCulture, false)]
+        [InlineData("", 'H', StringComparison.InvariantCulture, false)]
+        // InvariantCultureIgnoreCase
+        [InlineData("Hello", 'H', StringComparison.InvariantCultureIgnoreCase, true)]
+        [InlineData("Hello", 'Z', StringComparison.InvariantCultureIgnoreCase, false)]
+        [InlineData("Hello", 'e', StringComparison.InvariantCultureIgnoreCase, true)]
+        [InlineData("Hello", 'E', StringComparison.InvariantCultureIgnoreCase, true)]
+        [InlineData("", 'H', StringComparison.InvariantCultureIgnoreCase, false)]
+        // Ordinal
+        [InlineData("Hello", 'H', StringComparison.Ordinal, true)]
+        [InlineData("Hello", 'Z', StringComparison.Ordinal, false)]
+        [InlineData("Hello", 'e', StringComparison.Ordinal, true)]
+        [InlineData("Hello", 'E', StringComparison.Ordinal, false)]
+        [InlineData("", 'H', StringComparison.Ordinal, false)]
+        // OrdinalIgnoreCase
+        [InlineData("Hello", 'H', StringComparison.OrdinalIgnoreCase, true)]
+        [InlineData("Hello", 'Z', StringComparison.OrdinalIgnoreCase, false)]
+        [InlineData("Hello", 'e', StringComparison.OrdinalIgnoreCase, true)]
+        [InlineData("Hello", 'E', StringComparison.OrdinalIgnoreCase, true)]
+        [InlineData("", 'H', StringComparison.OrdinalIgnoreCase, false)]
+        public static void Contains(string s, char value, StringComparison comparisionType, bool expected)
+        {
+            Assert.Equal(expected, s.Contains(value, comparisionType));
+        }
+
+        [Theory]
+        // CurrentCulture
+        [InlineData("Hello", "ello", StringComparison.CurrentCulture, true)]
+        [InlineData("Hello", "ELL", StringComparison.CurrentCulture, false)]
+        [InlineData("Hello", "ElLo", StringComparison.CurrentCulture, false)]
+        [InlineData("Hello", "Larger Hello", StringComparison.CurrentCulture, false)]
+        [InlineData("Hello", "Goodbye", StringComparison.CurrentCulture, false)]
+        [InlineData("", "", StringComparison.CurrentCulture, true)]
+        [InlineData("", "hello", StringComparison.CurrentCulture, false)]
+        [InlineData("Hello", "", StringComparison.CurrentCulture, true)]
+        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.CurrentCulture, true)]
+        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.CurrentCulture, false)]
+        // CurrentCultureIgnoreCase
+        [InlineData("Hello", "ello", StringComparison.CurrentCultureIgnoreCase, true)]
+        [InlineData("Hello", "ELL", StringComparison.CurrentCultureIgnoreCase, true)]
+        [InlineData("Hello", "ElLo", StringComparison.CurrentCultureIgnoreCase, true)]
+        [InlineData("Hello", "Larger Hello", StringComparison.CurrentCultureIgnoreCase, false)]
+        [InlineData("Hello", "Goodbye", StringComparison.CurrentCultureIgnoreCase, false)]
+        [InlineData("", "", StringComparison.CurrentCultureIgnoreCase, true)]
+        [InlineData("", "hello", StringComparison.CurrentCultureIgnoreCase, false)]
+        [InlineData("Hello", "", StringComparison.CurrentCultureIgnoreCase, true)]
+        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.CurrentCultureIgnoreCase, true)]
+        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.CurrentCultureIgnoreCase, true)]
+        // InvariantCulture
+        [InlineData("Hello", "ello", StringComparison.InvariantCulture, true)]
+        [InlineData("Hello", "ELL", StringComparison.InvariantCulture, false)]
+        [InlineData("Hello", "ElLo", StringComparison.InvariantCulture, false)]
+        [InlineData("Hello", "Larger Hello", StringComparison.InvariantCulture, false)]
+        [InlineData("Hello", "Goodbye", StringComparison.InvariantCulture, false)]
+        [InlineData("", "", StringComparison.InvariantCulture, true)]
+        [InlineData("", "hello", StringComparison.InvariantCulture, false)]
+        [InlineData("Hello", "", StringComparison.InvariantCulture, true)]
+        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.InvariantCulture, true)]
+        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.InvariantCulture, false)]
+        // InvariantCultureIgnoreCase
+        [InlineData("Hello", "ello", StringComparison.InvariantCultureIgnoreCase, true)]
+        [InlineData("Hello", "ELL", StringComparison.InvariantCultureIgnoreCase, true)]
+        [InlineData("Hello", "ElLo", StringComparison.InvariantCultureIgnoreCase, true)]
+        [InlineData("Hello", "Larger Hello", StringComparison.InvariantCultureIgnoreCase, false)]
+        [InlineData("Hello", "Goodbye", StringComparison.InvariantCultureIgnoreCase, false)]
+        [InlineData("", "", StringComparison.InvariantCultureIgnoreCase, true)]
+        [InlineData("", "hello", StringComparison.InvariantCultureIgnoreCase, false)]
+        [InlineData("Hello", "", StringComparison.InvariantCultureIgnoreCase, true)]
+        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.InvariantCultureIgnoreCase, true)]
+        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.InvariantCultureIgnoreCase, true)]
+        // Ordinal
+        [InlineData("Hello", "ello", StringComparison.Ordinal, true)]
+        [InlineData("Hello", "ELL", StringComparison.Ordinal, false)]
+        [InlineData("Hello", "ElLo", StringComparison.Ordinal, false)]
+        [InlineData("Hello", "Larger Hello", StringComparison.Ordinal, false)]
+        [InlineData("Hello", "Goodbye", StringComparison.Ordinal, false)]
+        [InlineData("", "", StringComparison.Ordinal, true)]
+        [InlineData("", "hello", StringComparison.Ordinal, false)]
+        [InlineData("Hello", "", StringComparison.Ordinal, true)]
+        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.Ordinal, false)]
+        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.Ordinal, false)]
+        // OrdinalIgnoreCase
+        [InlineData("Hello", "ello", StringComparison.OrdinalIgnoreCase, true)]
+        [InlineData("Hello", "ELL", StringComparison.OrdinalIgnoreCase, true)]
+        [InlineData("Hello", "ElLo", StringComparison.OrdinalIgnoreCase, true)]
+        [InlineData("Hello", "Larger Hello", StringComparison.OrdinalIgnoreCase, false)]
+        [InlineData("Hello", "Goodbye", StringComparison.OrdinalIgnoreCase, false)]
+        [InlineData("", "", StringComparison.OrdinalIgnoreCase, true)]
+        [InlineData("", "hello", StringComparison.OrdinalIgnoreCase, false)]
+        [InlineData("Hello", "", StringComparison.OrdinalIgnoreCase, true)]
+        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.OrdinalIgnoreCase, false)]
+        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.OrdinalIgnoreCase, false)]
+        public static void Contains(string s, string value, StringComparison comparisonType, bool expected)
+        {
+            Assert.Equal(expected, s.Contains(value, comparisonType));
+            Assert.Equal(expected, s.AsSpan().Contains(value, comparisonType));
+        }
+
+        [Fact]
+        public static void Contains_StringComparison_TurkishI()
+        {
+            const string Source = "\u0069\u0130";
+
+            using (new ThreadCultureChange("tr-TR"))
+            {
+                Assert.True(Source.Contains("\u0069\u0069", StringComparison.CurrentCultureIgnoreCase));
+                Assert.True(Source.AsSpan().Contains("\u0069\u0069", StringComparison.CurrentCultureIgnoreCase));
+            }
+
+            using (new ThreadCultureChange("en-US"))
+            {
+                Assert.False(Source.Contains("\u0069\u0069", StringComparison.CurrentCultureIgnoreCase));
+                Assert.False(Source.AsSpan().Contains("\u0069\u0069", StringComparison.CurrentCultureIgnoreCase));
+            }
+        }
+
+        [Fact]
+        public static void Contains_Match_Char()
+        {
+            Assert.False("".Contains('a'));
+            Assert.False("".AsSpan().Contains('a'));
+
+            // Use a long-enough string to incur vectorization code
+            const int max = 250;
+
+            for (var length = 1; length < max; length++)
+            {
+                char[] ca = new char[length];
+                for (int i = 0; i < length; i++)
+                {
+                    ca[i] = (char)(i + 1);
+                }
+
+                var span = new Span<char>(ca);
+                var ros = new ReadOnlySpan<char>(ca);
+                var str = new string(ca);
+
+                for (var targetIndex = 0; targetIndex < length; targetIndex++)
+                {
+                    char target = ca[targetIndex];
+
+                    // Span
+                    bool found = span.Contains(target);
+                    Assert.True(found);
+
+                    // ReadOnlySpan
+                    found = ros.Contains(target);
+                    Assert.True(found);
+
+                    // String
+                    found = str.Contains(target);
+                    Assert.True(found);
+                }
+            }
+        }
+
+        [Fact]
+        public static void Contains_ZeroLength_Char()
+        {
+            // Span
+            var span = new Span<char>(Array.Empty<char>());
+            bool found = span.Contains((char)0);
+            Assert.False(found);
+
+            span = Span<char>.Empty;
+            found = span.Contains((char)0);
+            Assert.False(found);
+
+            // ReadOnlySpan
+            var ros = new ReadOnlySpan<char>(Array.Empty<char>());
+            found = ros.Contains((char)0);
+            Assert.False(found);
+
+            ros = ReadOnlySpan<char>.Empty;
+            found = ros.Contains((char)0);
+            Assert.False(found);
+
+            // String
+            found = string.Empty.Contains((char)0);
+            Assert.False(found);
+        }
+
+        [Fact]
+        public static void Contains_MultipleMatches_Char()
+        {
+            for (int length = 2; length < 32; length++)
+            {
+                var ca = new char[length];
+                for (int i = 0; i < length; i++)
+                {
+                    ca[i] = (char)(i + 1);
+                }
+
+                ca[length - 1] = (char)200;
+                ca[length - 2] = (char)200;
+
+                // Span
+                var span = new Span<char>(ca);
+                bool found = span.Contains((char)200);
+                Assert.True(found);
+
+                // ReadOnlySpan
+                var ros = new ReadOnlySpan<char>(ca);
+                found = ros.Contains((char)200);
+                Assert.True(found);
+
+                // String
+                var str = new string(ca);
+                found = str.Contains((char)200);
+                Assert.True(found);
+            }
+        }
+
+        [Fact]
+        public static void Contains_EnsureNoChecksGoOutOfRange_Char()
+        {
+            for (int length = 0; length < 100; length++)
+            {
+                var ca = new char[length + 2];
+                ca[0] = '9';
+                ca[length + 1] = '9';
+
+                // Span
+                var span = new Span<char>(ca, 1, length);
+                bool found = span.Contains('9');
+                Assert.False(found);
+
+                // ReadOnlySpan
+                var ros = new ReadOnlySpan<char>(ca, 1, length);
+                found = ros.Contains('9');
+                Assert.False(found);
+
+                // String
+                var str = new string(ca, 1, length);
+                found = str.Contains('9');
+                Assert.False(found);
+            }
+        }
+
+        [Theory]
+        [InlineData(StringComparison.CurrentCulture)]
+        [InlineData(StringComparison.CurrentCultureIgnoreCase)]
+        [InlineData(StringComparison.InvariantCulture)]
+        [InlineData(StringComparison.InvariantCultureIgnoreCase)]
+        [InlineData(StringComparison.Ordinal)]
+        [InlineData(StringComparison.OrdinalIgnoreCase)]
+        public static void Contains_NullValue_ThrowsArgumentNullException(StringComparison comparisonType)
+        {
+            AssertExtensions.Throws<ArgumentNullException>("value", () => "foo".Contains(null, comparisonType));
+        }
+
+        [Theory]
+        [InlineData(StringComparison.CurrentCulture - 1)]
+        [InlineData(StringComparison.OrdinalIgnoreCase + 1)]
+        public static void Contains_InvalidComparisonType_ThrowsArgumentOutOfRangeException(StringComparison comparisonType)
+        {
+            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "ab".Contains("a", comparisonType));
+        }
+
+        [Theory]
+        [InlineData("Hello", 'o', true)]
+        [InlineData("Hello", 'O', false)]
+        [InlineData("o", 'o', true)]
+        [InlineData("o", 'O', false)]
+        [InlineData("Hello", 'e', false)]
+        [InlineData("Hello", '\0', false)]
+        [InlineData("", '\0', false)]
+        [InlineData("\0", '\0', true)]
+        [InlineData("", 'a', false)]
+        [InlineData("abcdefghijklmnopqrstuvwxyz", 'z', true)]
+        public static void EndsWith(string s, char value, bool expected)
+        {
+            Assert.Equal(expected, s.EndsWith(value));
+        }
+
+        [Theory]
+        [InlineData(new char[0], new int[0])] // empty
+        [InlineData(new char[] { 'x', 'y', 'z' }, new int[] { 'x', 'y', 'z' })]
+        [InlineData(new char[] { 'x', '\uD86D', '\uDF54', 'y' }, new int[] { 'x', 0x2B754, 'y' })] // valid surrogate pair
+        [InlineData(new char[] { 'x', '\uD86D', 'y' }, new int[] { 'x', 0xFFFD, 'y' })] // standalone high surrogate
+        [InlineData(new char[] { 'x', '\uDF54', 'y' }, new int[] { 'x', 0xFFFD, 'y' })] // standalone low surrogate
+        [InlineData(new char[] { 'x', '\uD86D' }, new int[] { 'x', 0xFFFD })] // standalone high surrogate at end of string
+        [InlineData(new char[] { 'x', '\uDF54' }, new int[] { 'x', 0xFFFD })] // standalone low surrogate at end of string
+        [InlineData(new char[] { 'x', '\uD86D', '\uD86D', 'y' }, new int[] { 'x', 0xFFFD, 0xFFFD, 'y' })] // two high surrogates should be two replacement chars
+        [InlineData(new char[] { 'x', '\uFFFD', 'y' }, new int[] { 'x', 0xFFFD, 'y' })] // literal U+FFFD
+        public static void EnumerateRunes(char[] chars, int[] expected)
+        {
+            // Test data is smuggled as char[] instead of straight-up string since the test framework
+            // doesn't like invalid UTF-16 literals.
+
+            string asString = new string(chars);
+
+            // First, use a straight-up foreach keyword to ensure pattern matching works as expected
+
+            List<int> enumeratedScalarValues = new List<int>();
+            foreach (Rune rune in asString.EnumerateRunes())
+            {
+                enumeratedScalarValues.Add(rune.Value);
+            }
+            Assert.Equal(expected, enumeratedScalarValues.ToArray());
+
+            // Then use LINQ to ensure IEnumerator<...> works as expected
+
+            int[] enumeratedValues = new string(chars).EnumerateRunes().Select(r => r.Value).ToArray();
+            Assert.Equal(expected, enumeratedValues);
+        }
+
+        [Theory]
+        [InlineData("Hello", 'H', true)]
+        [InlineData("Hello", 'h', false)]
+        [InlineData("H", 'H', true)]
+        [InlineData("H", 'h', false)]
+        [InlineData("Hello", 'e', false)]
+        [InlineData("Hello", '\0', false)]
+        [InlineData("", '\0', false)]
+        [InlineData("\0", '\0', true)]
+        [InlineData("", 'a', false)]
+        [InlineData("abcdefghijklmnopqrstuvwxyz", 'a', true)]
+        public static void StartsWith(string s, char value, bool expected)
+        {
+            Assert.Equal(expected, s.StartsWith(value));
+        }
+
+        public static IEnumerable<object[]> Join_Char_StringArray_TestData()
+        {
+            yield return new object[] { '|', new string[0], 0, 0, "" };
+            yield return new object[] { '|', new string[] { "a" }, 0, 1, "a" };
+            yield return new object[] { '|', new string[] { "a", "b", "c" }, 0, 3, "a|b|c" };
+            yield return new object[] { '|', new string[] { "a", "b", "c" }, 0, 2, "a|b" };
+            yield return new object[] { '|', new string[] { "a", "b", "c" }, 1, 1, "b" };
+            yield return new object[] { '|', new string[] { "a", "b", "c" }, 1, 2, "b|c" };
+            yield return new object[] { '|', new string[] { "a", "b", "c" }, 3, 0, "" };
+            yield return new object[] { '|', new string[] { "a", "b", "c" }, 0, 0, "" };
+            yield return new object[] { '|', new string[] { "", "", "" }, 0, 3, "||" };
+            yield return new object[] { '|', new string[] { null, null, null }, 0, 3, "||" };
+        }
+
+        [Theory]
+        [MemberData(nameof(Join_Char_StringArray_TestData))]
+        public static void Join_Char_StringArray(char separator, string[] values, int startIndex, int count, string expected)
+        {
+            if (startIndex == 0 && count == values.Length)
+            {
+                Assert.Equal(expected, string.Join(separator, values));
+                Assert.Equal(expected, string.Join(separator, (IEnumerable<string>)values));
+                Assert.Equal(expected, string.Join(separator, (object[])values));
+                Assert.Equal(expected, string.Join(separator, (IEnumerable<object>)values));
+            }
+
+            Assert.Equal(expected, string.Join(separator, values, startIndex, count));
+            Assert.Equal(expected, string.Join(separator.ToString(), values, startIndex, count));
+        }
+
+        public static IEnumerable<object[]> Join_Char_ObjectArray_TestData()
+        {
+            yield return new object[] { '|', new object[0], "" };
+            yield return new object[] { '|', new object[] { 1 }, "1" };
+            yield return new object[] { '|', new object[] { 1, 2, 3 }, "1|2|3" };
+            yield return new object[] { '|', new object[] { new ObjectWithNullToString(), 2, new ObjectWithNullToString() }, "|2|" };
+            yield return new object[] { '|', new object[] { "1", null, "3" }, "1||3" };
+            yield return new object[] { '|', new object[] { "", "", "" }, "||" };
+            yield return new object[] { '|', new object[] { "", null, "" }, "||" };
+            yield return new object[] { '|', new object[] { null, null, null }, "||" };
+        }
+
+        [Theory]
+        [MemberData(nameof(Join_Char_ObjectArray_TestData))]
+        public static void Join_Char_ObjectArray(char separator, object[] values, string expected)
+        {
+            Assert.Equal(expected, string.Join(separator, values));
+            Assert.Equal(expected, string.Join(separator, (IEnumerable<object>)values));
+        }
+
+        [Fact]
+        public static void Join_Char_NullValues_ThrowsArgumentNullException()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("value", () => string.Join('|', (string[])null));
+            AssertExtensions.Throws<ArgumentNullException>("value", () => string.Join('|', (string[])null, 0, 0));
+            AssertExtensions.Throws<ArgumentNullException>("values", () => string.Join('|', (object[])null));
+            AssertExtensions.Throws<ArgumentNullException>("values", () => string.Join('|', (IEnumerable<object>)null));
+        }
+
+        [Fact]
+        public static void Join_Char_NegativeStartIndex_ThrowsArgumentOutOfRangeException()
+        {
+            AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => string.Join('|', new string[] { "Foo" }, -1, 0));
+        }
+
+        [Fact]
+        public static void Join_Char_NegativeCount_ThrowsArgumentOutOfRangeException()
+        {
+            AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => string.Join('|', new string[] { "Foo" }, 0, -1));
+        }
+
+        [Theory]
+        [InlineData(2, 1)]
+        [InlineData(2, 0)]
+        [InlineData(1, 2)]
+        [InlineData(1, 1)]
+        [InlineData(0, 2)]
+        [InlineData(-1, 0)]
+        public static void Join_Char_InvalidStartIndexCount_ThrowsArgumentOutOfRangeException(int startIndex, int count)
+        {
+            AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => string.Join('|', new string[] { "Foo" }, startIndex, count));
+        }
+
+        public static IEnumerable<object[]> Replace_StringComparison_TestData()
+        {
+            yield return new object[] { "abc", "abc", "def", StringComparison.CurrentCulture, "def" };
+            yield return new object[] { "abc", "ABC", "def", StringComparison.CurrentCulture, "abc" };
+            yield return new object[] { "abc", "abc", "", StringComparison.CurrentCulture, "" };
+            yield return new object[] { "abc", "b", "LONG", StringComparison.CurrentCulture, "aLONGc" };
+            yield return new object[] { "abc", "b", "d", StringComparison.CurrentCulture, "adc" };
+            yield return new object[] { "abc", "b", null, StringComparison.CurrentCulture, "ac" };
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.CurrentCulture, "def" };
+
+            yield return new object[] { "abc", "abc", "def", StringComparison.CurrentCultureIgnoreCase, "def" };
+            yield return new object[] { "abc", "ABC", "def", StringComparison.CurrentCultureIgnoreCase, "def" };
+            yield return new object[] { "abc", "abc", "", StringComparison.CurrentCultureIgnoreCase, "" };
+            yield return new object[] { "abc", "b", "LONG", StringComparison.CurrentCultureIgnoreCase, "aLONGc" };
+            yield return new object[] { "abc", "b", "d", StringComparison.CurrentCultureIgnoreCase, "adc" };
+            yield return new object[] { "abc", "b", null, StringComparison.CurrentCultureIgnoreCase, "ac" };
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.CurrentCultureIgnoreCase, "def" };
+
+            yield return new object[] { "abc", "abc", "def", StringComparison.Ordinal, "def" };
+            yield return new object[] { "abc", "ABC", "def", StringComparison.Ordinal, "abc" };
+            yield return new object[] { "abc", "abc", "", StringComparison.Ordinal, "" };
+            yield return new object[] { "abc", "b", "LONG", StringComparison.Ordinal, "aLONGc" };
+            yield return new object[] { "abc", "b", "d", StringComparison.Ordinal, "adc" };
+            yield return new object[] { "abc", "b", null, StringComparison.Ordinal, "ac" };
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.Ordinal, "abc" };
+
+            yield return new object[] { "abc", "abc", "def", StringComparison.OrdinalIgnoreCase, "def" };
+            yield return new object[] { "abc", "ABC", "def", StringComparison.OrdinalIgnoreCase, "def" };
+            yield return new object[] { "abc", "abc", "", StringComparison.OrdinalIgnoreCase, "" };
+            yield return new object[] { "abc", "b", "LONG", StringComparison.OrdinalIgnoreCase, "aLONGc" };
+            yield return new object[] { "abc", "b", "d", StringComparison.OrdinalIgnoreCase, "adc" };
+            yield return new object[] { "abc", "b", null, StringComparison.OrdinalIgnoreCase, "ac" };
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.OrdinalIgnoreCase, "abc" };
+
+            yield return new object[] { "abc", "abc", "def", StringComparison.InvariantCulture, "def" };
+            yield return new object[] { "abc", "ABC", "def", StringComparison.InvariantCulture, "abc" };
+            yield return new object[] { "abc", "abc", "", StringComparison.InvariantCulture, "" };
+            yield return new object[] { "abc", "b", "LONG", StringComparison.InvariantCulture, "aLONGc" };
+            yield return new object[] { "abc", "b", "d", StringComparison.InvariantCulture, "adc" };
+            yield return new object[] { "abc", "b", null, StringComparison.InvariantCulture, "ac" };
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.InvariantCulture, "def" };
+
+            yield return new object[] { "abc", "abc", "def", StringComparison.InvariantCultureIgnoreCase, "def" };
+            yield return new object[] { "abc", "ABC", "def", StringComparison.InvariantCultureIgnoreCase, "def" };
+            yield return new object[] { "abc", "abc", "", StringComparison.InvariantCultureIgnoreCase, "" };
+            yield return new object[] { "abc", "b", "LONG", StringComparison.InvariantCultureIgnoreCase, "aLONGc" };
+            yield return new object[] { "abc", "b", "d", StringComparison.InvariantCultureIgnoreCase, "adc" };
+            yield return new object[] { "abc", "b", null, StringComparison.InvariantCultureIgnoreCase, "ac" };
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.InvariantCultureIgnoreCase, "def" };
+
+            string turkishSource = "\u0069\u0130";
+
+            yield return new object[] { turkishSource, "\u0069", "a", StringComparison.Ordinal, "a\u0130" };
+            yield return new object[] { turkishSource, "\u0069", "a", StringComparison.OrdinalIgnoreCase, "a\u0130" };
+            yield return new object[] { turkishSource, "\u0130", "a", StringComparison.Ordinal, "\u0069a" };
+            yield return new object[] { turkishSource, "\u0130", "a", StringComparison.OrdinalIgnoreCase, "\u0069a" };
+
+            yield return new object[] { turkishSource, "\u0069", "a", StringComparison.InvariantCulture, "a\u0130" };
+            yield return new object[] { turkishSource, "\u0069", "a", StringComparison.InvariantCultureIgnoreCase, "a\u0130" };
+            yield return new object[] { turkishSource, "\u0130", "a", StringComparison.InvariantCulture, "\u0069a" };
+            yield return new object[] { turkishSource, "\u0130", "a", StringComparison.InvariantCultureIgnoreCase, "\u0069a" };
+        }
+
+        [Theory]
+        [MemberData(nameof(Replace_StringComparison_TestData))]
+        public void Replace_StringComparison_ReturnsExpected(string original, string oldValue, string newValue, StringComparison comparisonType, string expected)
+        {
+            Assert.Equal(expected, original.Replace(oldValue, newValue, comparisonType));
+        }
+
+        [Fact]
+        public void Replace_StringComparison_TurkishI()
+        {
+            const string Source = "\u0069\u0130";
+
+            using (new ThreadCultureChange("tr-TR"))
+            {
+                Assert.True("\u0069".Equals("\u0130", StringComparison.CurrentCultureIgnoreCase));
+
+                Assert.Equal("a\u0130", Source.Replace("\u0069", "a", StringComparison.CurrentCulture));
+                Assert.Equal("aa", Source.Replace("\u0069", "a", StringComparison.CurrentCultureIgnoreCase));
+                Assert.Equal("\u0069a", Source.Replace("\u0130", "a", StringComparison.CurrentCulture));
+                Assert.Equal("aa", Source.Replace("\u0130", "a", StringComparison.CurrentCultureIgnoreCase));
+            }
+
+            using (new ThreadCultureChange("en-US"))
+            {
+                Assert.False("\u0069".Equals("\u0130", StringComparison.CurrentCultureIgnoreCase));
+
+                Assert.Equal("a\u0130", Source.Replace("\u0069", "a", StringComparison.CurrentCulture));
+                Assert.Equal("a\u0130", Source.Replace("\u0069", "a", StringComparison.CurrentCultureIgnoreCase));
+                Assert.Equal("\u0069a", Source.Replace("\u0130", "a", StringComparison.CurrentCulture));
+                Assert.Equal("\u0069a", Source.Replace("\u0130", "a", StringComparison.CurrentCultureIgnoreCase));
+            }
+        }
+
+        public static IEnumerable<object[]> Replace_StringComparisonCulture_TestData()
+        {
+            yield return new object[] { "abc", "abc", "def", false, null, "def" };
+            yield return new object[] { "abc", "ABC", "def", false, null, "abc" };
+            yield return new object[] { "abc", "abc", "def", false, CultureInfo.InvariantCulture, "def" };
+            yield return new object[] { "abc", "ABC", "def", false, CultureInfo.InvariantCulture, "abc" };
+
+            yield return new object[] { "abc", "abc", "def", true, null, "def" };
+            yield return new object[] { "abc", "ABC", "def", true, null, "def" };
+            yield return new object[] { "abc", "abc", "def", true, CultureInfo.InvariantCulture, "def" };
+            yield return new object[] { "abc", "ABC", "def", true, CultureInfo.InvariantCulture, "def" };
+
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", false, null, "def" };
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", true, null, "def" };
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", false, CultureInfo.InvariantCulture, "def" };
+            yield return new object[] { "abc", "abc" + SoftHyphen, "def", true, CultureInfo.InvariantCulture, "def" };
+
+            yield return new object[] { "\u0069\u0130", "\u0069", "a", false, new CultureInfo("tr-TR"), "a\u0130" };
+            yield return new object[] { "\u0069\u0130", "\u0069", "a", true, new CultureInfo("tr-TR"), "aa" };
+            yield return new object[] { "\u0069\u0130", "\u0069", "a", false, CultureInfo.InvariantCulture, "a\u0130" };
+            yield return new object[] { "\u0069\u0130", "\u0069", "a", true, CultureInfo.InvariantCulture, "a\u0130" };
+        }
+
+        [Theory]
+        [MemberData(nameof(Replace_StringComparisonCulture_TestData))]
+        public void Replace_StringComparisonCulture_ReturnsExpected(string original, string oldValue, string newValue, bool ignoreCase, CultureInfo culture, string expected)
+        {
+            Assert.Equal(expected, original.Replace(oldValue, newValue, ignoreCase, culture));
+            if (culture == null)
+            {
+                Assert.Equal(expected, original.Replace(oldValue, newValue, ignoreCase, CultureInfo.CurrentCulture));
+            }
+        }
+
+        [Fact]
+        public void Replace_StringComparison_NullOldValue_ThrowsArgumentException()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("oldValue", () => "abc".Replace(null, "def", StringComparison.CurrentCulture));
+            AssertExtensions.Throws<ArgumentNullException>("oldValue", () => "abc".Replace(null, "def", true, CultureInfo.CurrentCulture));
+        }
+
+        [Fact]
+        public void Replace_StringComparison_EmptyOldValue_ThrowsArgumentException()
+        {
+            AssertExtensions.Throws<ArgumentException>("oldValue", () => "abc".Replace("", "def", StringComparison.CurrentCulture));
+            AssertExtensions.Throws<ArgumentException>("oldValue", () => "abc".Replace("", "def", true, CultureInfo.CurrentCulture));
+        }
+
+        [Theory]
+        [InlineData(StringComparison.CurrentCulture - 1)]
+        [InlineData(StringComparison.OrdinalIgnoreCase + 1)]
+        public void Replace_NoSuchStringComparison_ThrowsArgumentException(StringComparison comparisonType)
+        {
+            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "abc".Replace("abc", "def", comparisonType));
+        }
+
+
+        private static readonly StringComparison[] StringComparisons = (StringComparison[])Enum.GetValues(typeof(StringComparison));
+
+        [Fact]
+        public static void GetHashCode_OfSpan_EmbeddedNull_ReturnsDifferentHashCodes()
+        {
+            Assert.NotEqual(string.GetHashCode("\0AAAAAAAAA".AsSpan()), string.GetHashCode("\0BBBBBBBBBBBB".AsSpan()));
+        }
+
+        [Fact]
+        public static void GetHashCode_OfSpan_MatchesOfString()
+        {
+            // parameterless should be ordinal only
+            Assert.Equal("abc".GetHashCode(), string.GetHashCode("abc".AsSpan()));
+            Assert.NotEqual("abc".GetHashCode(), string.GetHashCode("ABC".AsSpan())); // case differences
+        }
+
+        [Fact]
+        public static void GetHashCode_CompareInfo()
+        {
+            // ordinal
+            Assert.Equal("abc".GetHashCode(), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("abc", CompareOptions.Ordinal));
+            Assert.NotEqual("abc".GetHashCode(), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("ABC", CompareOptions.Ordinal));
+
+            // ordinal ignore case
+            Assert.Equal("abc".GetHashCode(StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("abc", CompareOptions.OrdinalIgnoreCase));
+            Assert.Equal("abc".GetHashCode(StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("ABC", CompareOptions.OrdinalIgnoreCase));
+
+            // culture-aware
+            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.CurrentCulture), CultureInfo.CurrentCulture.CompareInfo.GetHashCode("aeiXXabc", CompareOptions.None));
+            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.CurrentCultureIgnoreCase), CultureInfo.CurrentCulture.CompareInfo.GetHashCode("aeiXXabc", CompareOptions.IgnoreCase));
+
+            // invariant culture
+            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.InvariantCulture), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("aeiXXabc", CompareOptions.None));
+            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.InvariantCultureIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("aeiXXabc", CompareOptions.IgnoreCase));
+        }
+
+        [Fact]
+        public static void GetHashCode_CompareInfo_OfSpan()
+        {
+            // ordinal
+            Assert.Equal("abc".GetHashCode(), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("abc".AsSpan(), CompareOptions.Ordinal));
+            Assert.NotEqual("abc".GetHashCode(), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("ABC".AsSpan(), CompareOptions.Ordinal));
+
+            // ordinal ignore case
+            Assert.Equal("abc".GetHashCode(StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("abc".AsSpan(), CompareOptions.OrdinalIgnoreCase));
+            Assert.Equal("abc".GetHashCode(StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("ABC".AsSpan(), CompareOptions.OrdinalIgnoreCase));
+
+            // culture-aware
+            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.CurrentCulture), CultureInfo.CurrentCulture.CompareInfo.GetHashCode("aeiXXabc".AsSpan(), CompareOptions.None));
+            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.CurrentCultureIgnoreCase), CultureInfo.CurrentCulture.CompareInfo.GetHashCode("aeiXXabc".AsSpan(), CompareOptions.IgnoreCase));
+
+            // invariant culture
+            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.InvariantCulture), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("aeiXXabc".AsSpan(), CompareOptions.None));
+            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.InvariantCultureIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("aeiXXabc".AsSpan(), CompareOptions.IgnoreCase));
+        }
+
+        public static IEnumerable<object[]> GetHashCode_StringComparison_Data => StringComparisons.Select(value => new object[] { value });
+
+        [Theory]
+        [MemberData(nameof(GetHashCode_StringComparison_Data))]
+        public static void GetHashCode_StringComparison(StringComparison comparisonType)
+        {
+            int hashCodeFromStringComparer = StringComparer.FromComparison(comparisonType).GetHashCode("abc");
+            int hashCodeFromStringGetHashCode = "abc".GetHashCode(comparisonType);
+            int hashCodeFromStringGetHashCodeOfSpan = string.GetHashCode("abc".AsSpan(), comparisonType);
+
+            Assert.Equal(hashCodeFromStringComparer, hashCodeFromStringGetHashCode);
+            Assert.Equal(hashCodeFromStringComparer, hashCodeFromStringGetHashCodeOfSpan);
+        }
+
+        public static IEnumerable<object[]> GetHashCode_NoSuchStringComparison_ThrowsArgumentException_Data => new[]
+        {
+            new object[] { StringComparisons.Min() - 1 },
+            new object[] { StringComparisons.Max() + 1 },
+        };
+
+        [Theory]
+        [MemberData(nameof(GetHashCode_NoSuchStringComparison_ThrowsArgumentException_Data))]
+        public static void GetHashCode_NoSuchStringComparison_ThrowsArgumentException(StringComparison comparisonType)
+        {
+            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "abc".GetHashCode(comparisonType));
+            AssertExtensions.Throws<ArgumentException>("comparisonType", () => string.GetHashCode("abc".AsSpan(), comparisonType));
+        }
+
+        [Theory]
+        [InlineData("")] // empty string
+        [InlineData("hello")] // non-empty string
+        public static unsafe void GetPinnableReference_ReturnsSameAsGCHandleAndLegacyFixed(string input)
+        {
+            Assert.NotNull(input); // test shouldn't have null input
+
+            // First, ensure the value pointed to by GetPinnableReference is correct.
+            // It should point to the first character (or the null terminator for empty inputs).
+
+            ref readonly char rChar = ref input.GetPinnableReference();
+            Assert.Equal((input.Length > 0) ? input[0] : '\0', rChar);
+
+            // Next, ensure that GetPinnableReference() and GCHandle.AddrOfPinnedObject agree
+            // on the address being returned.
+
+            GCHandle gcHandle = GCHandle.Alloc(input, GCHandleType.Pinned);
+            try
+            {
+                Assert.Equal((IntPtr)Unsafe.AsPointer(ref Unsafe.AsRef(in rChar)), gcHandle.AddrOfPinnedObject());
+            }
+            finally
+            {
+                gcHandle.Free();
+            }
+
+            // Next, ensure that GetPinnableReference matches the string projected as a ROS<char>.
+
+            Assert.True(Unsafe.AreSame(ref Unsafe.AsRef(in rChar), ref MemoryMarshal.GetReference((ReadOnlySpan<char>)input)));
+
+            // Finally, ensure that GetPinnableReference matches the legacy 'fixed' keyword.
+
+            DynamicMethod dynamicMethod = new DynamicMethod("tester", typeof(bool), new[] { typeof(string) });
+            ILGenerator ilGen = dynamicMethod.GetILGenerator();
+            LocalBuilder pinnedLocal = ilGen.DeclareLocal(typeof(object), pinned: true);
+
+            ilGen.Emit(OpCodes.Ldarg_0); // load 'input' and pin it
+            ilGen.Emit(OpCodes.Stloc, pinnedLocal);
+
+            ilGen.Emit(OpCodes.Ldloc, pinnedLocal); // get the address of field 0 from pinned 'input'
+            ilGen.Emit(OpCodes.Conv_I);
+
+            ilGen.Emit(OpCodes.Call, typeof(RuntimeHelpers).GetProperty("OffsetToStringData").GetMethod); // get pointer to start of string data
+            ilGen.Emit(OpCodes.Add);
+
+            ilGen.Emit(OpCodes.Ldarg_0); // get value of input.GetPinnableReference()
+            ilGen.Emit(OpCodes.Callvirt, typeof(string).GetMethod("GetPinnableReference"));
+
+            // At this point, the top of the evaluation stack is traditional (fixed char* = input) and input.GetPinnableReference().
+            // Compare for equality and return.
+
+            ilGen.Emit(OpCodes.Ceq);
+            ilGen.Emit(OpCodes.Ret);
+
+            Assert.True((bool)dynamicMethod.Invoke(null, new[] { input }));
+        }
+
+        [Fact]
+        public static unsafe void GetPinnableReference_WithNullInput_ThrowsNullRef()
+        {
+            // This test uses an explicit call instead of the normal callvirt that C# would emit.
+            // This allows us to make sure the NullReferenceException is coming from *within*
+            // the GetPinnableReference method rather than on the call site to that method.
+
+            DynamicMethod dynamicMethod = new DynamicMethod("tester", typeof(void), Type.EmptyTypes);
+            ILGenerator ilGen = dynamicMethod.GetILGenerator();
+
+            ilGen.Emit(OpCodes.Ldnull);
+            ilGen.Emit(OpCodes.Call, typeof(string).GetMethod("GetPinnableReference"));
+            ilGen.Emit(OpCodes.Pop);
+            ilGen.Emit(OpCodes.Ret);
+
+            Action del = (Action)dynamicMethod.CreateDelegate(typeof(Action));
+
+            Assert.NotNull(del);
+            Assert.Throws<NullReferenceException>(del);
+        }
+
+        [Theory]
+        [InlineData("")]
+        [InlineData("a")]
+        [InlineData("\0")]
+        [InlineData("abc")]
+        public static unsafe void ImplicitCast_ResultingSpanMatches(string s)
+        {
+            ReadOnlySpan<char> span = s;
+            Assert.Equal(s.Length, span.Length);
+            fixed (char* stringPtr = s)
+            fixed (char* spanPtr = &MemoryMarshal.GetReference(span))
+            {
+                Assert.Equal((IntPtr)stringPtr, (IntPtr)spanPtr);
+            }
+        }
+
+        [Fact]
+        public static void ImplicitCast_NullString_ReturnsDefaultSpan()
+        {
+            ReadOnlySpan<char> span = (string)null;
+            Assert.True(span == default);
+        }
+
+        [Theory]
+        [InlineData("Hello", 'l', StringComparison.Ordinal, 2)]
+        [InlineData("Hello", 'x', StringComparison.Ordinal, -1)]
+        [InlineData("Hello", 'h', StringComparison.Ordinal, -1)]
+        [InlineData("Hello", 'o', StringComparison.Ordinal, 4)]
+        [InlineData("Hello", 'h', StringComparison.OrdinalIgnoreCase, 0)]
+        [InlineData("HelLo", 'L', StringComparison.OrdinalIgnoreCase, 2)]
+        [InlineData("HelLo", 'L', StringComparison.Ordinal, 3)]
+        [InlineData("HelLo", '\0', StringComparison.Ordinal, -1)]
+        [InlineData("!@#$%", '%', StringComparison.Ordinal, 4)]
+        [InlineData("!@#$", '!', StringComparison.Ordinal, 0)]
+        [InlineData("!@#$", '@', StringComparison.Ordinal, 1)]
+        [InlineData("!@#$%", '%', StringComparison.OrdinalIgnoreCase, 4)]
+        [InlineData("!@#$", '!', StringComparison.OrdinalIgnoreCase, 0)]
+        [InlineData("!@#$", '@', StringComparison.OrdinalIgnoreCase, 1)]
+        [InlineData("_____________\u807f", '\u007f', StringComparison.Ordinal, -1)]
+        [InlineData("_____________\u807f__", '\u007f', StringComparison.Ordinal, -1)]
+        [InlineData("_____________\u807f\u007f_", '\u007f', StringComparison.Ordinal, 14)]
+        [InlineData("__\u807f_______________", '\u007f', StringComparison.Ordinal, -1)]
+        [InlineData("__\u807f___\u007f___________", '\u007f', StringComparison.Ordinal, 6)]
+        [InlineData("_____________\u807f", '\u007f', StringComparison.OrdinalIgnoreCase, -1)]
+        [InlineData("_____________\u807f__", '\u007f', StringComparison.OrdinalIgnoreCase, -1)]
+        [InlineData("_____________\u807f\u007f_", '\u007f', StringComparison.OrdinalIgnoreCase, 14)]
+        [InlineData("__\u807f_______________", '\u007f', StringComparison.OrdinalIgnoreCase, -1)]
+        [InlineData("__\u807f___\u007f___________", '\u007f', StringComparison.OrdinalIgnoreCase, 6)]
+        public static void IndexOf_SingleLetter(string s, char target, StringComparison stringComparison, int expected)
+        {
+            Assert.Equal(expected, s.IndexOf(target, stringComparison));
+            var charArray = new char[1];
+            charArray[0] = target;
+            Assert.Equal(expected, s.AsSpan().IndexOf(charArray, stringComparison));
+        }
+
+        [Fact]
+        public static void IndexOf_TurkishI_TurkishCulture_Char()
+        {
+            using (new ThreadCultureChange("tr-TR"))
+            {
+                string s = "Turkish I \u0131s TROUBL\u0130NG!";
+                char value = '\u0130';
+                Assert.Equal(19, s.IndexOf(value));
+                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(4, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+                Assert.Equal(19, s.IndexOf(value, StringComparison.Ordinal));
+                Assert.Equal(19, s.IndexOf(value, StringComparison.OrdinalIgnoreCase));
+
+                ReadOnlySpan<char> span = s.AsSpan();
+                Assert.Equal(19, span.IndexOf(new char[] { value }, StringComparison.CurrentCulture));
+                Assert.Equal(4, span.IndexOf(new char[] { value }, StringComparison.CurrentCultureIgnoreCase));
+                Assert.Equal(19, span.IndexOf(new char[] { value }, StringComparison.Ordinal));
+                Assert.Equal(19, span.IndexOf(new char[] { value }, StringComparison.OrdinalIgnoreCase));
+
+                value = '\u0131';
+                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(8, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+                Assert.Equal(10, s.IndexOf(value, StringComparison.Ordinal));
+                Assert.Equal(10, s.IndexOf(value, StringComparison.OrdinalIgnoreCase));
+
+                Assert.Equal(10, span.IndexOf(new char[] { value }, StringComparison.CurrentCulture));
+                Assert.Equal(8, span.IndexOf(new char[] { value }, StringComparison.CurrentCultureIgnoreCase));
+                Assert.Equal(10, span.IndexOf(new char[] { value }, StringComparison.Ordinal));
+                Assert.Equal(10, span.IndexOf(new char[] { value }, StringComparison.OrdinalIgnoreCase));
+            }
+        }
+
+        [Fact]
+        public static void IndexOf_TurkishI_InvariantCulture_Char()
+        {
+            using (new ThreadCultureChange(CultureInfo.InvariantCulture))
+            {
+                string s = "Turkish I \u0131s TROUBL\u0130NG!";
+                char value = '\u0130';
+
+                Assert.Equal(19, s.IndexOf(value));
+                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+
+                value = '\u0131';
+                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+            }
+        }
+
+        [Fact]
+        public static void IndexOf_TurkishI_EnglishUSCulture_Char()
+        {
+            using (new ThreadCultureChange("en-US"))
+            {
+                string s = "Turkish I \u0131s TROUBL\u0130NG!";
+                char value = '\u0130';
+
+                Assert.Equal(19, s.IndexOf(value));
+                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+
+                value = '\u0131';
+                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+            }
+        }
+
+        [Fact]
+        public static void IndexOf_EquivalentDiacritics_EnglishUSCulture_Char()
+        {
+            string s = "Exhibit a\u0300\u00C0";
+            char value = '\u00C0';
+
+            using (new ThreadCultureChange("en-US"))
+            {
+                Assert.Equal(10, s.IndexOf(value));
+                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(8, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+                Assert.Equal(10, s.IndexOf(value, StringComparison.Ordinal));
+                Assert.Equal(10, s.IndexOf(value, StringComparison.OrdinalIgnoreCase));
+            }
+        }
+
+        [Fact]
+        public static void IndexOf_EquivalentDiacritics_InvariantCulture_Char()
+        {
+            string s = "Exhibit a\u0300\u00C0";
+            char value = '\u00C0';
+
+            using (new ThreadCultureChange(CultureInfo.InvariantCulture))
+            {
+                Assert.Equal(10, s.IndexOf(value));
+                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(8, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+            }
+        }
+
+        [Fact]
+        public static void IndexOf_CyrillicE_EnglishUSCulture_Char()
+        {
+            string s = "Foo\u0400Bar";
+            char value = '\u0400';
+
+            using (new ThreadCultureChange("en-US"))
+            {
+                Assert.Equal(3, s.IndexOf(value));
+                Assert.Equal(3, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(3, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+                Assert.Equal(3, s.IndexOf(value, StringComparison.Ordinal));
+                Assert.Equal(3, s.IndexOf(value, StringComparison.OrdinalIgnoreCase));
+            }
+        }
+
+        [Fact]
+        public static void IndexOf_CyrillicE_InvariantCulture_Char()
+        {
+            string s = "Foo\u0400Bar";
+            char value = '\u0400';
+
+            using (new ThreadCultureChange(CultureInfo.InvariantCulture))
+            {
+                Assert.Equal(3, s.IndexOf(value));
+                Assert.Equal(3, s.IndexOf(value, StringComparison.CurrentCulture));
+                Assert.Equal(3, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
+            }
+        }
+
+        [Fact]
+        public static void IndexOf_Invalid_Char()
+        {
+            // Invalid comparison type
+            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "foo".IndexOf('o', StringComparison.CurrentCulture - 1));
+            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "foo".IndexOf('o', StringComparison.OrdinalIgnoreCase + 1));
+        }
+
+        [Theory]
+        [MemberData(nameof(Concat_Strings_2_3_4_TestData))]
+        public static void Concat_Spans(string[] values, string expected)
+        {
+            Assert.InRange(values.Length, 2, 4);
+
+            string result =
+                values.Length == 2 ? string.Concat(values[0].AsSpan(), values[1].AsSpan()) :
+                values.Length == 3 ? string.Concat(values[0].AsSpan(), values[1].AsSpan(), values[2].AsSpan()) :
+                string.Concat(values[0].AsSpan(), values[1].AsSpan(), values[2].AsSpan(), values[3].AsSpan());
+
+            if (result.Length == 0)
+            {
+                Assert.Same(string.Empty, result);
+            }
+
+            Assert.Equal(expected, result);
+        }
+
+        [Fact]
+        public static void IndexerUsingIndexTest()
+        {
+            Index index;
+            string s = "0123456789ABCDEF";
+
+            for (int i = 0; i < s.Length; i++)
+            {
+                index = Index.FromStart(i);
+                Assert.Equal(s[i], s[index]);
+
+                index = Index.FromEnd(i + 1);
+                Assert.Equal(s[s.Length - i - 1], s[index]);
+            }
+
+            index = Index.FromStart(s.Length + 1);
+            char c;
+            Assert.Throws<IndexOutOfRangeException>(() => c = s[index]);
+
+            index = Index.FromEnd(s.Length + 1);
+            Assert.Throws<IndexOutOfRangeException>(() => c = s[index]);
+        }
+
+        [Fact]
+        public static void IndexerUsingRangeTest()
+        {
+            Range range;
+            string s = "0123456789ABCDEF";
+
+            for (int i = 0; i < s.Length; i++)
+            {
+                range = new Range(Index.FromStart(0), Index.FromStart(i));
+                Assert.Equal(s.Substring(0, i), s[range]);
+
+                range = new Range(Index.FromEnd(s.Length), Index.FromEnd(i));
+                Assert.Equal(s.Substring(0, s.Length - i), s[range]);
+            }
+
+            range = new Range(Index.FromStart(s.Length - 2), Index.FromStart(s.Length + 1));
+            string s1;
+            Assert.Throws<ArgumentOutOfRangeException>(() => s1 = s[range]);
+
+            range = new Range(Index.FromEnd(s.Length + 1), Index.FromEnd(0));
+            Assert.Throws<ArgumentOutOfRangeException>(() => s1 = s[range]);
+        }
+
+        [Fact]
+        public static void SubstringUsingIndexTest()
+        {
+            string s = "0123456789ABCDEF";
+
+            for (int i = 0; i < s.Length; i++)
+            {
+                Assert.Equal(s.Substring(i), s[i..]);
+                Assert.Equal(s.Substring(s.Length - i - 1), s[^(i + 1)..]);
+            }
+
+            // String.Substring allows the string length as a valid input.
+            Assert.Equal(s.Substring(s.Length), s[s.Length..]);
+
+            Assert.Throws<ArgumentOutOfRangeException>(() => s[(s.Length + 1)..]);
+            Assert.Throws<ArgumentOutOfRangeException>(() => s[^(s.Length + 1)..]);
+        }
+
+        [Fact]
+        public static void SubstringUsingRangeTest()
+        {
+            string s = "0123456789ABCDEF";
+            Range range;
+
+            for (int i = 0; i < s.Length; i++)
+            {
+                range = new Range(Index.FromStart(0), Index.FromStart(i));
+                Assert.Equal(s.Substring(0, i), s[range]);
+
+                range = new Range(Index.FromEnd(s.Length), Index.FromEnd(i));
+                Assert.Equal(s.Substring(0, s.Length - i), s[range]);
+            }
+
+            range = new Range(Index.FromStart(s.Length - 2), Index.FromStart(s.Length + 1));
+            string s1;
+            Assert.Throws<ArgumentOutOfRangeException>(() => s1 = s[range]);
+
+            range = new Range(Index.FromEnd(s.Length + 1), Index.FromEnd(0));
+            Assert.Throws<ArgumentOutOfRangeException>(() => s1 = s[range]);
+        }
+
+        /// <summary>
+        /// Returns true only if U+0020 SPACE is represented as the single byte 0x20 in the active code page.
+        /// </summary>
+        public static unsafe bool IsSimpleActiveCodePage
+        {
+            get
+            {
+                IntPtr pAnsiStr = IntPtr.Zero;
+                try
+                {
+                    pAnsiStr = Marshal.StringToHGlobalAnsi(" ");
+                    return ((byte*)pAnsiStr)[0] == (byte)' ' && ((byte*)pAnsiStr)[1] == (byte)'\0';
+                }
+                finally
+                {
+                    if (pAnsiStr != IntPtr.Zero)
+                    {
+                        Marshal.FreeHGlobal(pAnsiStr);
+                    }
+                }
+            }
+        }
+
+        [Theory]
+        [InlineData("  Hello  ", "Hello")]
+        [InlineData("      \t      ", "")]
+        [InlineData("", "")]
+        [InlineData("      ", "")]
+        public static void Trim_Memory(string s, string expected)
+        {
+            Assert.Equal(expected, s.AsSpan().Trim().ToString()); // ReadOnlySpan
+            Assert.Equal(expected, new Span<char>(s.ToCharArray()).Trim().ToString());
+            Assert.Equal(expected, new Memory<char>(s.ToCharArray()).Trim().ToString());
+            Assert.Equal(expected, s.AsMemory().Trim().ToString()); // ReadOnlyMemory
+        }
+
+        [Theory]
+        [InlineData("  Hello  ", "  Hello")]
+        [InlineData("      \t      ", "")]
+        [InlineData("", "")]
+        [InlineData("      ", "")]
+        public static void TrimEnd_Memory(string s, string expected)
+        {
+            Assert.Equal(expected, s.AsSpan().TrimEnd().ToString()); // ReadOnlySpan
+            Assert.Equal(expected, new Span<char>(s.ToCharArray()).TrimEnd().ToString());
+            Assert.Equal(expected, new Memory<char>(s.ToCharArray()).TrimEnd().ToString());
+            Assert.Equal(expected, s.AsMemory().TrimEnd().ToString()); // ReadOnlyMemory
+        }
+
+        [Theory]
+        [InlineData("  Hello  ", "Hello  ")]
+        [InlineData("      \t      ", "")]
+        [InlineData("", "")]
+        [InlineData("      ", "")]
+        public static void TrimStart_Memory(string s, string expected)
+        {
+            Assert.Equal(expected, s.AsSpan().TrimStart().ToString()); // ReadOnlySpan
+            Assert.Equal(expected, new Span<char>(s.ToCharArray()).TrimStart().ToString());
+            Assert.Equal(expected, new Memory<char>(s.ToCharArray()).TrimStart().ToString());
+            Assert.Equal(expected, s.AsMemory().TrimStart().ToString()); // ReadOnlyMemory
+        }
+
+        [Fact]
+        public static void ZeroLengthTrim_Memory()
+        {
+            string s1 = string.Empty;
+
+            ReadOnlySpan<char> ros = s1.AsSpan();
+            Assert.True(ros.SequenceEqual(ros.Trim()));
+            Assert.True(ros.SequenceEqual(ros.TrimStart()));
+            Assert.True(ros.SequenceEqual(ros.TrimEnd()));
+
+            Span<char> span = new Span<char>(s1.ToCharArray());
+            Assert.True(span.SequenceEqual(span.Trim()));
+            Assert.True(span.SequenceEqual(span.TrimStart()));
+            Assert.True(span.SequenceEqual(span.TrimEnd()));
+
+            Memory<char> mem = new Memory<char>(s1.ToCharArray());
+            Assert.True(mem.Span.SequenceEqual(mem.Trim().Span));
+            Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
+            Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
+
+            ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(s1.ToCharArray());
+            Assert.True(rom.Span.SequenceEqual(rom.Trim().Span));
+            Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
+            Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
+        }
+
+        [Fact]
+        public static void NoWhiteSpaceTrim_Memory()
+        {
+            for (int length = 0; length < 32; length++)
+            {
+                char[] a = new char[length];
+                for (int i = 0; i < length; i++)
+                {
+                    a[i] = 'a';
+                }
+                string s1 = new string(a);
+
+                ReadOnlySpan<char> ros = s1.AsSpan();
+                Assert.True(ros.SequenceEqual(ros.Trim()));
+                Assert.True(ros.SequenceEqual(ros.TrimStart()));
+                Assert.True(ros.SequenceEqual(ros.TrimEnd()));
+
+                Span<char> span = new Span<char>(a);
+                Assert.True(span.SequenceEqual(span.Trim()));
+                Assert.True(span.SequenceEqual(span.TrimStart()));
+                Assert.True(span.SequenceEqual(span.TrimEnd()));
+
+                Memory<char> mem = new Memory<char>(a);
+                Assert.True(mem.Span.SequenceEqual(mem.Trim().Span));
+                Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
+                Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
+
+                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
+                Assert.True(rom.Span.SequenceEqual(rom.Trim().Span));
+                Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
+                Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
+            }
+        }
+
+        [Fact]
+        public static void OnlyWhiteSpaceTrim_Memory()
+        {
+            for (int length = 0; length < 32; length++)
+            {
+                char[] a = new char[length];
+                for (int i = 0; i < length; i++)
+                {
+                    a[i] = ' ';
+                }
+                string s1 = new string(a);
+
+                ReadOnlySpan<char> ros = new ReadOnlySpan<char>(a);
+                Assert.True(ReadOnlySpan<char>.Empty.SequenceEqual(ros.Trim()));
+                Assert.True(ReadOnlySpan<char>.Empty.SequenceEqual(ros.TrimStart()));
+                Assert.True(ReadOnlySpan<char>.Empty.SequenceEqual(ros.TrimEnd()));
+
+                Span<char> span = new Span<char>(a);
+                Assert.True(Span<char>.Empty.SequenceEqual(span.Trim()));
+                Assert.True(Span<char>.Empty.SequenceEqual(span.TrimStart()));
+                Assert.True(Span<char>.Empty.SequenceEqual(span.TrimEnd()));
+
+                Memory<char> mem = new Memory<char>(a);
+                Assert.True(Memory<char>.Empty.Span.SequenceEqual(mem.Trim().Span));
+                Assert.True(Memory<char>.Empty.Span.SequenceEqual(mem.TrimStart().Span));
+                Assert.True(Memory<char>.Empty.Span.SequenceEqual(mem.TrimEnd().Span));
+
+                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
+                Assert.True(ReadOnlyMemory<char>.Empty.Span.SequenceEqual(rom.Trim().Span));
+                Assert.True(ReadOnlyMemory<char>.Empty.Span.SequenceEqual(rom.TrimStart().Span));
+                Assert.True(ReadOnlyMemory<char>.Empty.Span.SequenceEqual(rom.TrimEnd().Span));
+            }
+        }
+
+        [Fact]
+        public static void WhiteSpaceAtStartTrim_Memory()
+        {
+            for (int length = 2; length < 32; length++)
+            {
+                char[] a = new char[length];
+                for (int i = 0; i < length; i++)
+                {
+                    a[i] = 'a';
+                }
+                a[0] = ' ';
+                string s1 = new string(a);
+
+                ReadOnlySpan<char> ros = s1.AsSpan();
+                Assert.True(ros.Slice(1).SequenceEqual(ros.Trim()));
+                Assert.True(ros.Slice(1).SequenceEqual(ros.TrimStart()));
+                Assert.True(ros.SequenceEqual(ros.TrimEnd()));
+
+                Span<char> span = new Span<char>(a);
+                Assert.True(span.Slice(1).SequenceEqual(span.Trim()));
+                Assert.True(span.Slice(1).SequenceEqual(span.TrimStart()));
+                Assert.True(span.SequenceEqual(span.TrimEnd()));
+
+                Memory<char> mem = new Memory<char>(a);
+                Assert.True(mem.Slice(1).Span.SequenceEqual(mem.Trim().Span));
+                Assert.True(mem.Slice(1).Span.SequenceEqual(mem.TrimStart().Span));
+                Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
+
+                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
+                Assert.True(rom.Slice(1).Span.SequenceEqual(rom.Trim().Span));
+                Assert.True(rom.Slice(1).Span.SequenceEqual(rom.TrimStart().Span));
+                Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
+            }
+        }
+
+        [Fact]
+        public static void WhiteSpaceAtEndTrim_Memory()
+        {
+            for (int length = 2; length < 32; length++)
+            {
+                char[] a = new char[length];
+                for (int i = 0; i < length; i++)
+                {
+                    a[i] = 'a';
+                }
+                a[length - 1] = ' ';
+                string s1 = new string(a);
+
+                ReadOnlySpan<char> ros = s1.AsSpan();
+                Assert.True(ros.Slice(0, length - 1).SequenceEqual(ros.Trim()));
+                Assert.True(ros.SequenceEqual(ros.TrimStart()));
+                Assert.True(ros.Slice(0, length - 1).SequenceEqual(ros.TrimEnd()));
+
+                Span<char> span = new Span<char>(a);
+                Assert.True(span.Slice(0, length - 1).SequenceEqual(span.Trim()));
+                Assert.True(span.SequenceEqual(span.TrimStart()));
+                Assert.True(span.Slice(0, length - 1).SequenceEqual(span.TrimEnd()));
+
+                Memory<char> mem = new Memory<char>(a);
+                Assert.True(mem.Slice(0, length - 1).Span.SequenceEqual(mem.Trim().Span));
+                Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
+                Assert.True(mem.Slice(0, length - 1).Span.SequenceEqual(mem.TrimEnd().Span));
+
+                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
+                Assert.True(rom.Slice(0, length - 1).Span.SequenceEqual(rom.Trim().Span));
+                Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
+                Assert.True(rom.Slice(0, length - 1).Span.SequenceEqual(rom.TrimEnd().Span));
+            }
+        }
+
+        [Fact]
+        public static void WhiteSpaceAtStartAndEndTrim_Memory()
+        {
+            for (int length = 3; length < 32; length++)
+            {
+                char[] a = new char[length];
+                for (int i = 0; i < length; i++)
+                {
+                    a[i] = 'a';
+                }
+                a[0] = ' ';
+                a[length - 1] = ' ';
+                string s1 = new string(a);
+
+                ReadOnlySpan<char> ros = s1.AsSpan();
+                Assert.True(ros.Slice(1, length - 2).SequenceEqual(ros.Trim()));
+                Assert.True(ros.Slice(1).SequenceEqual(ros.TrimStart()));
+                Assert.True(ros.Slice(0, length - 1).SequenceEqual(ros.TrimEnd()));
+
+                Span<char> span = new Span<char>(a);
+                Assert.True(span.Slice(1, length - 2).SequenceEqual(span.Trim()));
+                Assert.True(span.Slice(1).SequenceEqual(span.TrimStart()));
+                Assert.True(span.Slice(0, length - 1).SequenceEqual(span.TrimEnd()));
+
+                Memory<char> mem = new Memory<char>(a);
+                Assert.True(mem.Slice(1, length - 2).Span.SequenceEqual(mem.Trim().Span));
+                Assert.True(mem.Slice(1).Span.SequenceEqual(mem.TrimStart().Span));
+                Assert.True(mem.Slice(0, length - 1).Span.SequenceEqual(mem.TrimEnd().Span));
+
+                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
+                Assert.True(rom.Slice(1, length - 2).Span.SequenceEqual(rom.Trim().Span));
+                Assert.True(rom.Slice(1).Span.SequenceEqual(rom.TrimStart().Span));
+                Assert.True(rom.Slice(0, length - 1).Span.SequenceEqual(rom.TrimEnd().Span));
+            }
+        }
+
+        [Fact]
+        public static void WhiteSpaceInMiddleTrim_Memory()
+        {
+            for (int length = 3; length < 32; length++)
+            {
+                char[] a = new char[length];
+                for (int i = 0; i < length; i++)
+                {
+                    a[i] = 'a';
+                }
+                a[1] = ' ';
+                string s1 = new string(a);
+
+                ReadOnlySpan<char> ros = s1.AsSpan();
+                Assert.True(ros.SequenceEqual(ros.Trim()));
+                Assert.True(ros.SequenceEqual(ros.TrimStart()));
+                Assert.True(ros.SequenceEqual(ros.TrimEnd()));
+
+                Span<char> span = new Span<char>(a);
+                Assert.True(span.SequenceEqual(span.Trim()));
+                Assert.True(span.SequenceEqual(span.TrimStart()));
+                Assert.True(span.SequenceEqual(span.TrimEnd()));
+
+                Memory<char> mem = new Memory<char>(a);
+                Assert.True(mem.Span.SequenceEqual(mem.Trim().Span));
+                Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
+                Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
+
+                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
+                Assert.True(rom.Span.SequenceEqual(rom.Trim().Span));
+                Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
+                Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
+            }
+        }
+
+        [Fact]
+        public static void TrimWhiteSpaceMultipleTimes_Memory()
+        {
+            for (int length = 3; length < 32; length++)
+            {
+                char[] a = new char[length];
+                for (int i = 0; i < length; i++)
+                {
+                    a[i] = 'a';
+                }
+                a[0] = ' ';
+                a[length - 1] = ' ';
+                string s1 = new string(a);
+
+                // ReadOnlySpan
+                {
+                    ReadOnlySpan<char> ros = s1.AsSpan();
+                    ReadOnlySpan<char> trimResult = ros.Trim();
+                    ReadOnlySpan<char> trimStartResult = ros.TrimStart();
+                    ReadOnlySpan<char> trimEndResult = ros.TrimEnd();
+                    Assert.True(ros.Slice(1, length - 2).SequenceEqual(trimResult));
+                    Assert.True(ros.Slice(1).SequenceEqual(trimStartResult));
+                    Assert.True(ros.Slice(0, length - 1).SequenceEqual(trimEndResult));
+
+                    // 2nd attempt should do nothing
+                    Assert.True(trimResult.SequenceEqual(trimResult.Trim()));
+                    Assert.True(trimStartResult.SequenceEqual(trimStartResult.TrimStart()));
+                    Assert.True(trimEndResult.SequenceEqual(trimEndResult.TrimEnd()));
+                }
+
+                // Span
+                {
+                    Span<char> span = new Span<char>(a);
+                    Span<char> trimResult = span.Trim();
+                    Span<char> trimStartResult = span.TrimStart();
+                    Span<char> trimEndResult = span.TrimEnd();
+                    Assert.True(span.Slice(1, length - 2).SequenceEqual(trimResult));
+                    Assert.True(span.Slice(1).SequenceEqual(trimStartResult));
+                    Assert.True(span.Slice(0, length - 1).SequenceEqual(trimEndResult));
+
+                    // 2nd attempt should do nothing
+                    Assert.True(trimResult.SequenceEqual(trimResult.Trim()));
+                    Assert.True(trimStartResult.SequenceEqual(trimStartResult.TrimStart()));
+                    Assert.True(trimEndResult.SequenceEqual(trimEndResult.TrimEnd()));
+                }
+
+                // Memory
+                {
+                    Memory<char> mem = new Memory<char>(a);
+                    Memory<char> trimResult = mem.Trim();
+                    Memory<char> trimStartResult = mem.TrimStart();
+                    Memory<char> trimEndResult = mem.TrimEnd();
+                    Assert.True(mem.Slice(1, length - 2).Span.SequenceEqual(trimResult.Span));
+                    Assert.True(mem.Slice(1).Span.SequenceEqual(trimStartResult.Span));
+                    Assert.True(mem.Slice(0, length - 1).Span.SequenceEqual(trimEndResult.Span));
+
+                    // 2nd attempt should do nothing
+                    Assert.True(trimResult.Span.SequenceEqual(trimResult.Trim().Span));
+                    Assert.True(trimStartResult.Span.SequenceEqual(trimStartResult.TrimStart().Span));
+                    Assert.True(trimEndResult.Span.SequenceEqual(trimEndResult.TrimEnd().Span));
+                }
+
+                // ReadOnlyMemory
+                {
+                    ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
+                    ReadOnlyMemory<char> trimResult = rom.Trim();
+                    ReadOnlyMemory<char> trimStartResult = rom.TrimStart();
+                    ReadOnlyMemory<char> trimEndResult = rom.TrimEnd();
+                    Assert.True(rom.Slice(1, length - 2).Span.SequenceEqual(trimResult.Span));
+                    Assert.True(rom.Slice(1).Span.SequenceEqual(trimStartResult.Span));
+                    Assert.True(rom.Slice(0, length - 1).Span.SequenceEqual(trimEndResult.Span));
+
+                    // 2nd attempt should do nothing
+                    Assert.True(trimResult.Span.SequenceEqual(trimResult.Trim().Span));
+                    Assert.True(trimStartResult.Span.SequenceEqual(trimStartResult.TrimStart().Span));
+                    Assert.True(trimEndResult.Span.SequenceEqual(trimEndResult.TrimEnd().Span));
+                }
+            }
+        }
+
+        [Fact]
+        public static void MakeSureNoTrimChecksGoOutOfRange_Memory()
+        {
+            for (int length = 3; length < 64; length++)
+            {
+                char[] first = new char[length];
+                first[0] = ' ';
+                first[length - 1] = ' ';
+                string s1 = new string(first, 1, length - 2);
+
+                ReadOnlySpan<char> ros = s1.AsSpan();
+                Assert.True(ros.SequenceEqual(ros.Trim()));
+                Assert.True(ros.SequenceEqual(ros.TrimStart()));
+                Assert.True(ros.SequenceEqual(ros.TrimEnd()));
+
+                Span<char> span = new Span<char>(s1.ToCharArray());
+                Assert.True(span.SequenceEqual(span.Trim()));
+                Assert.True(span.SequenceEqual(span.TrimStart()));
+                Assert.True(span.SequenceEqual(span.TrimEnd()));
+
+                Memory<char> mem = new Memory<char>(s1.ToCharArray());
+                Assert.True(mem.Span.SequenceEqual(mem.Trim().Span));
+                Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
+                Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
+
+                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(s1.ToCharArray());
+                Assert.True(rom.Span.SequenceEqual(rom.Trim().Span));
+                Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
+                Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/StringTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/StringTests.netcoreapp.cs
deleted file mode 100644 (file)
index 831b716..0000000
+++ /dev/null
@@ -1,1611 +0,0 @@
-// 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.Reflection.Emit;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Text;
-using Microsoft.DotNet.RemoteExecutor;
-using Xunit;
-
-namespace System.Tests
-{
-    public partial class StringTests
-    {
-        [Theory]
-        [InlineData(0, 0)]
-        [InlineData(3, 1)]
-        public static void Ctor_CharSpan_EmptyString(int length, int offset)
-        {
-            Assert.Same(string.Empty, new string(new ReadOnlySpan<char>(new char[length], offset, 0)));
-        }
-
-        [Fact]
-        public static unsafe void Ctor_CharSpan_Empty()
-        {
-            Assert.Same(string.Empty, new string((ReadOnlySpan<char>)null));
-            Assert.Same(string.Empty, new string(ReadOnlySpan<char>.Empty));
-        }
-
-        [Theory]
-        [InlineData(new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\0' }, 0, 8, "abcdefgh")]
-        [InlineData(new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\0', 'i', 'j', 'k' }, 0, 12, "abcdefgh\0ijk")]
-        [InlineData(new char[] { 'a', 'b', 'c' }, 0, 0, "")]
-        [InlineData(new char[] { 'a', 'b', 'c' }, 0, 1, "a")]
-        [InlineData(new char[] { 'a', 'b', 'c' }, 2, 1, "c")]
-        [InlineData(new char[] { '\u8001', '\u8002', '\ufffd', '\u1234', '\ud800', '\udfff' }, 0, 6, "\u8001\u8002\ufffd\u1234\ud800\udfff")]
-        public static void Ctor_CharSpan(char[] valueArray, int startIndex, int length, string expected)
-        {
-            var span = new ReadOnlySpan<char>(valueArray, startIndex, length);
-            Assert.Equal(expected, new string(span));
-        }
-
-        [Fact]
-        public static unsafe void Ctor_CharPtr_DoesNotAccessInvalidPage()
-        {
-            // Allocates a buffer of all 'x' followed by a null terminator,
-            // then attempts to create a string instance from this at various offsets.
-
-            const int MaxCharCount = 128;
-            using BoundedMemory<char> boundedMemory = BoundedMemory.Allocate<char>(MaxCharCount);
-            boundedMemory.Span.Fill('x');
-            boundedMemory.Span[MaxCharCount - 1] = '\0';
-            boundedMemory.MakeReadonly();
-
-            using MemoryHandle memoryHandle = boundedMemory.Memory.Pin();
-
-            for (int i = 0; i < MaxCharCount; i++)
-            {
-                string expectedString = new string('x', MaxCharCount - i - 1);
-                string actualString = new string((char*)memoryHandle.Pointer + i);
-                Assert.Equal(expectedString, actualString);
-            }
-        }
-
-        [ConditionalFact(nameof(IsSimpleActiveCodePage))]
-        public static unsafe void Ctor_SBytePtr_DoesNotAccessInvalidPage()
-        {
-            // Allocates a buffer of all ' ' followed by a null terminator,
-            // then attempts to create a string instance from this at various offsets.
-            // We use U+0020 SPACE instead of any other character because it lives
-            // at offset 0x20 across every supported code page.
-
-            const int MaxByteCount = 128;
-            using BoundedMemory<sbyte> boundedMemory = BoundedMemory.Allocate<sbyte>(MaxByteCount);
-            boundedMemory.Span.Fill((sbyte)' ');
-            boundedMemory.Span[MaxByteCount - 1] = (sbyte)'\0';
-            boundedMemory.MakeReadonly();
-
-            using MemoryHandle memoryHandle = boundedMemory.Memory.Pin();
-
-            for (int i = 0; i < MaxByteCount; i++)
-            {
-                string expectedString = new string(' ', MaxByteCount - i - 1);
-                string actualString = new string((sbyte*)memoryHandle.Pointer + i);
-                Assert.Equal(expectedString, actualString);
-            }
-        }
-
-        [Fact]
-        public static void Create_InvalidArguments_Throw()
-        {
-            AssertExtensions.Throws<ArgumentNullException>("action", () => string.Create(-1, 0, null));
-            AssertExtensions.Throws<ArgumentOutOfRangeException>("length", () => string.Create(-1, 0, (span, state) => { }));
-        }
-
-        [Fact]
-        public static void Create_Length0_ReturnsEmptyString()
-        {
-            bool actionInvoked = false;
-            Assert.Same(string.Empty, string.Create(0, 0, (span, state) => actionInvoked = true));
-            Assert.False(actionInvoked);
-        }
-
-        [Fact]
-        public static void Create_NullState_Allowed()
-        {
-            string result = string.Create(1, (object)null, (span, state) =>
-            {
-                span[0] = 'a';
-                Assert.Null(state);
-            });
-            Assert.Equal("a", result);
-        }
-
-        [Fact]
-        public static void Create_ClearsMemory()
-        {
-            const int Length = 10;
-            string result = string.Create(Length, (object)null, (span, state) =>
-            {
-                for (int i = 0; i < span.Length; i++)
-                {
-                    Assert.Equal('\0', span[i]);
-                }
-            });
-            Assert.Equal(new string('\0', Length), result);
-        }
-
-        [Theory]
-        [InlineData("a")]
-        [InlineData("this is a test")]
-        [InlineData("\0\u8001\u8002\ufffd\u1234\ud800\udfff")]
-        public static void Create_ReturnsExpectedString(string expected)
-        {
-            char[] input = expected.ToCharArray();
-            string result = string.Create(input.Length, input, (span, state) =>
-            {
-                Assert.Same(input, state);
-                for (int i = 0; i < state.Length; i++)
-                {
-                    span[i] = state[i];
-                }
-            });
-            Assert.Equal(expected, result);
-        }
-
-        [Theory]
-        [InlineData("Hello", 'H', true)]
-        [InlineData("Hello", 'Z', false)]
-        [InlineData("Hello", 'e', true)]
-        [InlineData("Hello", 'E', false)]
-        [InlineData("", 'H', false)]
-        public static void Contains(string s, char value, bool expected)
-        {
-            Assert.Equal(expected, s.Contains(value));
-
-            ReadOnlySpan<char> span = s.AsSpan();
-            Assert.Equal(expected, span.Contains(value));
-        }
-
-        [Theory]
-        // CurrentCulture
-        [InlineData("Hello", 'H', StringComparison.CurrentCulture, true)]
-        [InlineData("Hello", 'Z', StringComparison.CurrentCulture, false)]
-        [InlineData("Hello", 'e', StringComparison.CurrentCulture, true)]
-        [InlineData("Hello", 'E', StringComparison.CurrentCulture, false)]
-        [InlineData("", 'H', StringComparison.CurrentCulture, false)]
-        // CurrentCultureIgnoreCase
-        [InlineData("Hello", 'H', StringComparison.CurrentCultureIgnoreCase, true)]
-        [InlineData("Hello", 'Z', StringComparison.CurrentCultureIgnoreCase, false)]
-        [InlineData("Hello", 'e', StringComparison.CurrentCultureIgnoreCase, true)]
-        [InlineData("Hello", 'E', StringComparison.CurrentCultureIgnoreCase, true)]
-        [InlineData("", 'H', StringComparison.CurrentCultureIgnoreCase, false)]
-        // InvariantCulture
-        [InlineData("Hello", 'H', StringComparison.InvariantCulture, true)]
-        [InlineData("Hello", 'Z', StringComparison.InvariantCulture, false)]
-        [InlineData("Hello", 'e', StringComparison.InvariantCulture, true)]
-        [InlineData("Hello", 'E', StringComparison.InvariantCulture, false)]
-        [InlineData("", 'H', StringComparison.InvariantCulture, false)]
-        // InvariantCultureIgnoreCase
-        [InlineData("Hello", 'H', StringComparison.InvariantCultureIgnoreCase, true)]
-        [InlineData("Hello", 'Z', StringComparison.InvariantCultureIgnoreCase, false)]
-        [InlineData("Hello", 'e', StringComparison.InvariantCultureIgnoreCase, true)]
-        [InlineData("Hello", 'E', StringComparison.InvariantCultureIgnoreCase, true)]
-        [InlineData("", 'H', StringComparison.InvariantCultureIgnoreCase, false)]
-        // Ordinal
-        [InlineData("Hello", 'H', StringComparison.Ordinal, true)]
-        [InlineData("Hello", 'Z', StringComparison.Ordinal, false)]
-        [InlineData("Hello", 'e', StringComparison.Ordinal, true)]
-        [InlineData("Hello", 'E', StringComparison.Ordinal, false)]
-        [InlineData("", 'H', StringComparison.Ordinal, false)]
-        // OrdinalIgnoreCase
-        [InlineData("Hello", 'H', StringComparison.OrdinalIgnoreCase, true)]
-        [InlineData("Hello", 'Z', StringComparison.OrdinalIgnoreCase, false)]
-        [InlineData("Hello", 'e', StringComparison.OrdinalIgnoreCase, true)]
-        [InlineData("Hello", 'E', StringComparison.OrdinalIgnoreCase, true)]
-        [InlineData("", 'H', StringComparison.OrdinalIgnoreCase, false)]
-        public static void Contains(string s, char value, StringComparison comparisionType, bool expected)
-        {
-            Assert.Equal(expected, s.Contains(value, comparisionType));
-        }
-
-        [Theory]
-        // CurrentCulture
-        [InlineData("Hello", "ello", StringComparison.CurrentCulture, true)]
-        [InlineData("Hello", "ELL", StringComparison.CurrentCulture, false)]
-        [InlineData("Hello", "ElLo", StringComparison.CurrentCulture, false)]
-        [InlineData("Hello", "Larger Hello", StringComparison.CurrentCulture, false)]
-        [InlineData("Hello", "Goodbye", StringComparison.CurrentCulture, false)]
-        [InlineData("", "", StringComparison.CurrentCulture, true)]
-        [InlineData("", "hello", StringComparison.CurrentCulture, false)]
-        [InlineData("Hello", "", StringComparison.CurrentCulture, true)]
-        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.CurrentCulture, true)]
-        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.CurrentCulture, false)]
-        // CurrentCultureIgnoreCase
-        [InlineData("Hello", "ello", StringComparison.CurrentCultureIgnoreCase, true)]
-        [InlineData("Hello", "ELL", StringComparison.CurrentCultureIgnoreCase, true)]
-        [InlineData("Hello", "ElLo", StringComparison.CurrentCultureIgnoreCase, true)]
-        [InlineData("Hello", "Larger Hello", StringComparison.CurrentCultureIgnoreCase, false)]
-        [InlineData("Hello", "Goodbye", StringComparison.CurrentCultureIgnoreCase, false)]
-        [InlineData("", "", StringComparison.CurrentCultureIgnoreCase, true)]
-        [InlineData("", "hello", StringComparison.CurrentCultureIgnoreCase, false)]
-        [InlineData("Hello", "", StringComparison.CurrentCultureIgnoreCase, true)]
-        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.CurrentCultureIgnoreCase, true)]
-        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.CurrentCultureIgnoreCase, true)]
-        // InvariantCulture
-        [InlineData("Hello", "ello", StringComparison.InvariantCulture, true)]
-        [InlineData("Hello", "ELL", StringComparison.InvariantCulture, false)]
-        [InlineData("Hello", "ElLo", StringComparison.InvariantCulture, false)]
-        [InlineData("Hello", "Larger Hello", StringComparison.InvariantCulture, false)]
-        [InlineData("Hello", "Goodbye", StringComparison.InvariantCulture, false)]
-        [InlineData("", "", StringComparison.InvariantCulture, true)]
-        [InlineData("", "hello", StringComparison.InvariantCulture, false)]
-        [InlineData("Hello", "", StringComparison.InvariantCulture, true)]
-        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.InvariantCulture, true)]
-        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.InvariantCulture, false)]
-        // InvariantCultureIgnoreCase
-        [InlineData("Hello", "ello", StringComparison.InvariantCultureIgnoreCase, true)]
-        [InlineData("Hello", "ELL", StringComparison.InvariantCultureIgnoreCase, true)]
-        [InlineData("Hello", "ElLo", StringComparison.InvariantCultureIgnoreCase, true)]
-        [InlineData("Hello", "Larger Hello", StringComparison.InvariantCultureIgnoreCase, false)]
-        [InlineData("Hello", "Goodbye", StringComparison.InvariantCultureIgnoreCase, false)]
-        [InlineData("", "", StringComparison.InvariantCultureIgnoreCase, true)]
-        [InlineData("", "hello", StringComparison.InvariantCultureIgnoreCase, false)]
-        [InlineData("Hello", "", StringComparison.InvariantCultureIgnoreCase, true)]
-        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.InvariantCultureIgnoreCase, true)]
-        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.InvariantCultureIgnoreCase, true)]
-        // Ordinal
-        [InlineData("Hello", "ello", StringComparison.Ordinal, true)]
-        [InlineData("Hello", "ELL", StringComparison.Ordinal, false)]
-        [InlineData("Hello", "ElLo", StringComparison.Ordinal, false)]
-        [InlineData("Hello", "Larger Hello", StringComparison.Ordinal, false)]
-        [InlineData("Hello", "Goodbye", StringComparison.Ordinal, false)]
-        [InlineData("", "", StringComparison.Ordinal, true)]
-        [InlineData("", "hello", StringComparison.Ordinal, false)]
-        [InlineData("Hello", "", StringComparison.Ordinal, true)]
-        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.Ordinal, false)]
-        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.Ordinal, false)]
-        // OrdinalIgnoreCase
-        [InlineData("Hello", "ello", StringComparison.OrdinalIgnoreCase, true)]
-        [InlineData("Hello", "ELL", StringComparison.OrdinalIgnoreCase, true)]
-        [InlineData("Hello", "ElLo", StringComparison.OrdinalIgnoreCase, true)]
-        [InlineData("Hello", "Larger Hello", StringComparison.OrdinalIgnoreCase, false)]
-        [InlineData("Hello", "Goodbye", StringComparison.OrdinalIgnoreCase, false)]
-        [InlineData("", "", StringComparison.OrdinalIgnoreCase, true)]
-        [InlineData("", "hello", StringComparison.OrdinalIgnoreCase, false)]
-        [InlineData("Hello", "", StringComparison.OrdinalIgnoreCase, true)]
-        [InlineData("Hello", "ell" + SoftHyphen, StringComparison.OrdinalIgnoreCase, false)]
-        [InlineData("Hello", "Ell" + SoftHyphen, StringComparison.OrdinalIgnoreCase, false)]
-        public static void Contains(string s, string value, StringComparison comparisonType, bool expected)
-        {
-            Assert.Equal(expected, s.Contains(value, comparisonType));
-            Assert.Equal(expected, s.AsSpan().Contains(value, comparisonType));
-        }
-
-        [Fact]
-        public static void Contains_StringComparison_TurkishI()
-        {
-            const string Source = "\u0069\u0130";
-
-            using (new ThreadCultureChange("tr-TR"))
-            {
-                Assert.True(Source.Contains("\u0069\u0069", StringComparison.CurrentCultureIgnoreCase));
-                Assert.True(Source.AsSpan().Contains("\u0069\u0069", StringComparison.CurrentCultureIgnoreCase));
-            }
-
-            using (new ThreadCultureChange("en-US"))
-            {
-                Assert.False(Source.Contains("\u0069\u0069", StringComparison.CurrentCultureIgnoreCase));
-                Assert.False(Source.AsSpan().Contains("\u0069\u0069", StringComparison.CurrentCultureIgnoreCase));
-            }
-        }
-
-        [Fact]
-        public static void Contains_Match_Char()
-        {
-            Assert.False("".Contains('a'));
-            Assert.False("".AsSpan().Contains('a'));
-
-            // Use a long-enough string to incur vectorization code
-            const int max = 250;
-
-            for (var length = 1; length < max; length++)
-            {
-                char[] ca = new char[length];
-                for (int i = 0; i < length; i++)
-                {
-                    ca[i] = (char)(i + 1);
-                }
-
-                var span = new Span<char>(ca);
-                var ros = new ReadOnlySpan<char>(ca);
-                var str = new string(ca);
-
-                for (var targetIndex = 0; targetIndex < length; targetIndex++)
-                {
-                    char target = ca[targetIndex];
-
-                    // Span
-                    bool found = span.Contains(target);
-                    Assert.True(found);
-
-                    // ReadOnlySpan
-                    found = ros.Contains(target);
-                    Assert.True(found);
-
-                    // String
-                    found = str.Contains(target);
-                    Assert.True(found);
-                }
-            }
-        }
-
-        [Fact]
-        public static void Contains_ZeroLength_Char()
-        {
-            // Span
-            var span = new Span<char>(Array.Empty<char>());
-            bool found = span.Contains((char)0);
-            Assert.False(found);
-
-            span = Span<char>.Empty;
-            found = span.Contains((char)0);
-            Assert.False(found);
-
-            // ReadOnlySpan
-            var ros = new ReadOnlySpan<char>(Array.Empty<char>());
-            found = ros.Contains((char)0);
-            Assert.False(found);
-
-            ros = ReadOnlySpan<char>.Empty;
-            found = ros.Contains((char)0);
-            Assert.False(found);
-
-            // String
-            found = string.Empty.Contains((char)0);
-            Assert.False(found);
-        }
-
-        [Fact]
-        public static void Contains_MultipleMatches_Char()
-        {
-            for (int length = 2; length < 32; length++)
-            {
-                var ca = new char[length];
-                for (int i = 0; i < length; i++)
-                {
-                    ca[i] = (char)(i + 1);
-                }
-
-                ca[length - 1] = (char)200;
-                ca[length - 2] = (char)200;
-
-                // Span
-                var span = new Span<char>(ca);
-                bool found = span.Contains((char)200);
-                Assert.True(found);
-
-                // ReadOnlySpan
-                var ros = new ReadOnlySpan<char>(ca);
-                found = ros.Contains((char)200);
-                Assert.True(found);
-
-                // String
-                var str = new string(ca);
-                found = str.Contains((char)200);
-                Assert.True(found);
-            }
-        }
-
-        [Fact]
-        public static void Contains_EnsureNoChecksGoOutOfRange_Char()
-        {
-            for (int length = 0; length < 100; length++)
-            {
-                var ca = new char[length + 2];
-                ca[0] = '9';
-                ca[length + 1] = '9';
-
-                // Span
-                var span = new Span<char>(ca, 1, length);
-                bool found = span.Contains('9');
-                Assert.False(found);
-
-                // ReadOnlySpan
-                var ros = new ReadOnlySpan<char>(ca, 1, length);
-                found = ros.Contains('9');
-                Assert.False(found);
-
-                // String
-                var str = new string(ca, 1, length);
-                found = str.Contains('9');
-                Assert.False(found);
-            }
-        }
-
-        [Theory]
-        [InlineData(StringComparison.CurrentCulture)]
-        [InlineData(StringComparison.CurrentCultureIgnoreCase)]
-        [InlineData(StringComparison.InvariantCulture)]
-        [InlineData(StringComparison.InvariantCultureIgnoreCase)]
-        [InlineData(StringComparison.Ordinal)]
-        [InlineData(StringComparison.OrdinalIgnoreCase)]
-        public static void Contains_NullValue_ThrowsArgumentNullException(StringComparison comparisonType)
-        {
-            AssertExtensions.Throws<ArgumentNullException>("value", () => "foo".Contains(null, comparisonType));
-        }
-
-        [Theory]
-        [InlineData(StringComparison.CurrentCulture - 1)]
-        [InlineData(StringComparison.OrdinalIgnoreCase + 1)]
-        public static void Contains_InvalidComparisonType_ThrowsArgumentOutOfRangeException(StringComparison comparisonType)
-        {
-            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "ab".Contains("a", comparisonType));
-        }
-
-        [Theory]
-        [InlineData("Hello", 'o', true)]
-        [InlineData("Hello", 'O', false)]
-        [InlineData("o", 'o', true)]
-        [InlineData("o", 'O', false)]
-        [InlineData("Hello", 'e', false)]
-        [InlineData("Hello", '\0', false)]
-        [InlineData("", '\0', false)]
-        [InlineData("\0", '\0', true)]
-        [InlineData("", 'a', false)]
-        [InlineData("abcdefghijklmnopqrstuvwxyz", 'z', true)]
-        public static void EndsWith(string s, char value, bool expected)
-        {
-            Assert.Equal(expected, s.EndsWith(value));
-        }
-
-        [Theory]
-        [InlineData(new char[0], new int[0])] // empty
-        [InlineData(new char[] { 'x', 'y', 'z' }, new int[] { 'x', 'y', 'z' })]
-        [InlineData(new char[] { 'x', '\uD86D', '\uDF54', 'y' }, new int[] { 'x', 0x2B754, 'y' })] // valid surrogate pair
-        [InlineData(new char[] { 'x', '\uD86D', 'y' }, new int[] { 'x', 0xFFFD, 'y' })] // standalone high surrogate
-        [InlineData(new char[] { 'x', '\uDF54', 'y' }, new int[] { 'x', 0xFFFD, 'y' })] // standalone low surrogate
-        [InlineData(new char[] { 'x', '\uD86D' }, new int[] { 'x', 0xFFFD })] // standalone high surrogate at end of string
-        [InlineData(new char[] { 'x', '\uDF54' }, new int[] { 'x', 0xFFFD })] // standalone low surrogate at end of string
-        [InlineData(new char[] { 'x', '\uD86D', '\uD86D', 'y' }, new int[] { 'x', 0xFFFD, 0xFFFD, 'y' })] // two high surrogates should be two replacement chars
-        [InlineData(new char[] { 'x', '\uFFFD', 'y' }, new int[] { 'x', 0xFFFD, 'y' })] // literal U+FFFD
-        public static void EnumerateRunes(char[] chars, int[] expected)
-        {
-            // Test data is smuggled as char[] instead of straight-up string since the test framework
-            // doesn't like invalid UTF-16 literals.
-
-            string asString = new string(chars);
-
-            // First, use a straight-up foreach keyword to ensure pattern matching works as expected
-
-            List<int> enumeratedScalarValues = new List<int>();
-            foreach (Rune rune in asString.EnumerateRunes())
-            {
-                enumeratedScalarValues.Add(rune.Value);
-            }
-            Assert.Equal(expected, enumeratedScalarValues.ToArray());
-
-            // Then use LINQ to ensure IEnumerator<...> works as expected
-
-            int[] enumeratedValues = new string(chars).EnumerateRunes().Select(r => r.Value).ToArray();
-            Assert.Equal(expected, enumeratedValues);
-        }
-
-        [Theory]
-        [InlineData("Hello", 'H', true)]
-        [InlineData("Hello", 'h', false)]
-        [InlineData("H", 'H', true)]
-        [InlineData("H", 'h', false)]
-        [InlineData("Hello", 'e', false)]
-        [InlineData("Hello", '\0', false)]
-        [InlineData("", '\0', false)]
-        [InlineData("\0", '\0', true)]
-        [InlineData("", 'a', false)]
-        [InlineData("abcdefghijklmnopqrstuvwxyz", 'a', true)]
-        public static void StartsWith(string s, char value, bool expected)
-        {
-            Assert.Equal(expected, s.StartsWith(value));
-        }
-
-        public static IEnumerable<object[]> Join_Char_StringArray_TestData()
-        {
-            yield return new object[] { '|', new string[0], 0, 0, "" };
-            yield return new object[] { '|', new string[] { "a" }, 0, 1, "a" };
-            yield return new object[] { '|', new string[] { "a", "b", "c" }, 0, 3, "a|b|c" };
-            yield return new object[] { '|', new string[] { "a", "b", "c" }, 0, 2, "a|b" };
-            yield return new object[] { '|', new string[] { "a", "b", "c" }, 1, 1, "b" };
-            yield return new object[] { '|', new string[] { "a", "b", "c" }, 1, 2, "b|c" };
-            yield return new object[] { '|', new string[] { "a", "b", "c" }, 3, 0, "" };
-            yield return new object[] { '|', new string[] { "a", "b", "c" }, 0, 0, "" };
-            yield return new object[] { '|', new string[] { "", "", "" }, 0, 3, "||" };
-            yield return new object[] { '|', new string[] { null, null, null }, 0, 3, "||" };
-        }
-
-        [Theory]
-        [MemberData(nameof(Join_Char_StringArray_TestData))]
-        public static void Join_Char_StringArray(char separator, string[] values, int startIndex, int count, string expected)
-        {
-            if (startIndex == 0 && count == values.Length)
-            {
-                Assert.Equal(expected, string.Join(separator, values));
-                Assert.Equal(expected, string.Join(separator, (IEnumerable<string>)values));
-                Assert.Equal(expected, string.Join(separator, (object[])values));
-                Assert.Equal(expected, string.Join(separator, (IEnumerable<object>)values));
-            }
-
-            Assert.Equal(expected, string.Join(separator, values, startIndex, count));
-            Assert.Equal(expected, string.Join(separator.ToString(), values, startIndex, count));
-        }
-
-        public static IEnumerable<object[]> Join_Char_ObjectArray_TestData()
-        {
-            yield return new object[] { '|', new object[0], "" };
-            yield return new object[] { '|', new object[] { 1 }, "1" };
-            yield return new object[] { '|', new object[] { 1, 2, 3 }, "1|2|3" };
-            yield return new object[] { '|', new object[] { new ObjectWithNullToString(), 2, new ObjectWithNullToString() }, "|2|" };
-            yield return new object[] { '|', new object[] { "1", null, "3" }, "1||3" };
-            yield return new object[] { '|', new object[] { "", "", "" }, "||" };
-            yield return new object[] { '|', new object[] { "", null, "" }, "||" };
-            yield return new object[] { '|', new object[] { null, null, null }, "||" };
-        }
-
-        [Theory]
-        [MemberData(nameof(Join_Char_ObjectArray_TestData))]
-        public static void Join_Char_ObjectArray(char separator, object[] values, string expected)
-        {
-            Assert.Equal(expected, string.Join(separator, values));
-            Assert.Equal(expected, string.Join(separator, (IEnumerable<object>)values));
-        }
-
-        [Fact]
-        public static void Join_Char_NullValues_ThrowsArgumentNullException()
-        {
-            AssertExtensions.Throws<ArgumentNullException>("value", () => string.Join('|', (string[])null));
-            AssertExtensions.Throws<ArgumentNullException>("value", () => string.Join('|', (string[])null, 0, 0));
-            AssertExtensions.Throws<ArgumentNullException>("values", () => string.Join('|', (object[])null));
-            AssertExtensions.Throws<ArgumentNullException>("values", () => string.Join('|', (IEnumerable<object>)null));
-        }
-
-        [Fact]
-        public static void Join_Char_NegativeStartIndex_ThrowsArgumentOutOfRangeException()
-        {
-            AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => string.Join('|', new string[] { "Foo" }, -1, 0));
-        }
-
-        [Fact]
-        public static void Join_Char_NegativeCount_ThrowsArgumentOutOfRangeException()
-        {
-            AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => string.Join('|', new string[] { "Foo" }, 0, -1));
-        }
-
-        [Theory]
-        [InlineData(2, 1)]
-        [InlineData(2, 0)]
-        [InlineData(1, 2)]
-        [InlineData(1, 1)]
-        [InlineData(0, 2)]
-        [InlineData(-1, 0)]
-        public static void Join_Char_InvalidStartIndexCount_ThrowsArgumentOutOfRangeException(int startIndex, int count)
-        {
-            AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => string.Join('|', new string[] { "Foo" }, startIndex, count));
-        }
-
-        public static IEnumerable<object[]> Replace_StringComparison_TestData()
-        {
-            yield return new object[] { "abc", "abc", "def", StringComparison.CurrentCulture, "def" };
-            yield return new object[] { "abc", "ABC", "def", StringComparison.CurrentCulture, "abc" };
-            yield return new object[] { "abc", "abc", "", StringComparison.CurrentCulture, "" };
-            yield return new object[] { "abc", "b", "LONG", StringComparison.CurrentCulture, "aLONGc" };
-            yield return new object[] { "abc", "b", "d", StringComparison.CurrentCulture, "adc" };
-            yield return new object[] { "abc", "b", null, StringComparison.CurrentCulture, "ac" };
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.CurrentCulture, "def" };
-
-            yield return new object[] { "abc", "abc", "def", StringComparison.CurrentCultureIgnoreCase, "def" };
-            yield return new object[] { "abc", "ABC", "def", StringComparison.CurrentCultureIgnoreCase, "def" };
-            yield return new object[] { "abc", "abc", "", StringComparison.CurrentCultureIgnoreCase, "" };
-            yield return new object[] { "abc", "b", "LONG", StringComparison.CurrentCultureIgnoreCase, "aLONGc" };
-            yield return new object[] { "abc", "b", "d", StringComparison.CurrentCultureIgnoreCase, "adc" };
-            yield return new object[] { "abc", "b", null, StringComparison.CurrentCultureIgnoreCase, "ac" };
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.CurrentCultureIgnoreCase, "def" };
-
-            yield return new object[] { "abc", "abc", "def", StringComparison.Ordinal, "def" };
-            yield return new object[] { "abc", "ABC", "def", StringComparison.Ordinal, "abc" };
-            yield return new object[] { "abc", "abc", "", StringComparison.Ordinal, "" };
-            yield return new object[] { "abc", "b", "LONG", StringComparison.Ordinal, "aLONGc" };
-            yield return new object[] { "abc", "b", "d", StringComparison.Ordinal, "adc" };
-            yield return new object[] { "abc", "b", null, StringComparison.Ordinal, "ac" };
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.Ordinal, "abc" };
-
-            yield return new object[] { "abc", "abc", "def", StringComparison.OrdinalIgnoreCase, "def" };
-            yield return new object[] { "abc", "ABC", "def", StringComparison.OrdinalIgnoreCase, "def" };
-            yield return new object[] { "abc", "abc", "", StringComparison.OrdinalIgnoreCase, "" };
-            yield return new object[] { "abc", "b", "LONG", StringComparison.OrdinalIgnoreCase, "aLONGc" };
-            yield return new object[] { "abc", "b", "d", StringComparison.OrdinalIgnoreCase, "adc" };
-            yield return new object[] { "abc", "b", null, StringComparison.OrdinalIgnoreCase, "ac" };
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.OrdinalIgnoreCase, "abc" };
-
-            yield return new object[] { "abc", "abc", "def", StringComparison.InvariantCulture, "def" };
-            yield return new object[] { "abc", "ABC", "def", StringComparison.InvariantCulture, "abc" };
-            yield return new object[] { "abc", "abc", "", StringComparison.InvariantCulture, "" };
-            yield return new object[] { "abc", "b", "LONG", StringComparison.InvariantCulture, "aLONGc" };
-            yield return new object[] { "abc", "b", "d", StringComparison.InvariantCulture, "adc" };
-            yield return new object[] { "abc", "b", null, StringComparison.InvariantCulture, "ac" };
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.InvariantCulture, "def" };
-
-            yield return new object[] { "abc", "abc", "def", StringComparison.InvariantCultureIgnoreCase, "def" };
-            yield return new object[] { "abc", "ABC", "def", StringComparison.InvariantCultureIgnoreCase, "def" };
-            yield return new object[] { "abc", "abc", "", StringComparison.InvariantCultureIgnoreCase, "" };
-            yield return new object[] { "abc", "b", "LONG", StringComparison.InvariantCultureIgnoreCase, "aLONGc" };
-            yield return new object[] { "abc", "b", "d", StringComparison.InvariantCultureIgnoreCase, "adc" };
-            yield return new object[] { "abc", "b", null, StringComparison.InvariantCultureIgnoreCase, "ac" };
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", StringComparison.InvariantCultureIgnoreCase, "def" };
-
-            string turkishSource = "\u0069\u0130";
-
-            yield return new object[] { turkishSource, "\u0069", "a", StringComparison.Ordinal, "a\u0130" };
-            yield return new object[] { turkishSource, "\u0069", "a", StringComparison.OrdinalIgnoreCase, "a\u0130" };
-            yield return new object[] { turkishSource, "\u0130", "a", StringComparison.Ordinal, "\u0069a" };
-            yield return new object[] { turkishSource, "\u0130", "a", StringComparison.OrdinalIgnoreCase, "\u0069a" };
-
-            yield return new object[] { turkishSource, "\u0069", "a", StringComparison.InvariantCulture, "a\u0130" };
-            yield return new object[] { turkishSource, "\u0069", "a", StringComparison.InvariantCultureIgnoreCase, "a\u0130" };
-            yield return new object[] { turkishSource, "\u0130", "a", StringComparison.InvariantCulture, "\u0069a" };
-            yield return new object[] { turkishSource, "\u0130", "a", StringComparison.InvariantCultureIgnoreCase, "\u0069a" };
-        }
-
-        [Theory]
-        [MemberData(nameof(Replace_StringComparison_TestData))]
-        public void Replace_StringComparison_ReturnsExpected(string original, string oldValue, string newValue, StringComparison comparisonType, string expected)
-        {
-            Assert.Equal(expected, original.Replace(oldValue, newValue, comparisonType));
-        }
-
-        [Fact]
-        public void Replace_StringComparison_TurkishI()
-        {
-            const string Source = "\u0069\u0130";
-
-            using (new ThreadCultureChange("tr-TR"))
-            {
-                Assert.True("\u0069".Equals("\u0130", StringComparison.CurrentCultureIgnoreCase));
-
-                Assert.Equal("a\u0130", Source.Replace("\u0069", "a", StringComparison.CurrentCulture));
-                Assert.Equal("aa", Source.Replace("\u0069", "a", StringComparison.CurrentCultureIgnoreCase));
-                Assert.Equal("\u0069a", Source.Replace("\u0130", "a", StringComparison.CurrentCulture));
-                Assert.Equal("aa", Source.Replace("\u0130", "a", StringComparison.CurrentCultureIgnoreCase));
-            }
-
-            using (new ThreadCultureChange("en-US"))
-            {
-                Assert.False("\u0069".Equals("\u0130", StringComparison.CurrentCultureIgnoreCase));
-
-                Assert.Equal("a\u0130", Source.Replace("\u0069", "a", StringComparison.CurrentCulture));
-                Assert.Equal("a\u0130", Source.Replace("\u0069", "a", StringComparison.CurrentCultureIgnoreCase));
-                Assert.Equal("\u0069a", Source.Replace("\u0130", "a", StringComparison.CurrentCulture));
-                Assert.Equal("\u0069a", Source.Replace("\u0130", "a", StringComparison.CurrentCultureIgnoreCase));
-            }
-        }
-
-        public static IEnumerable<object[]> Replace_StringComparisonCulture_TestData()
-        {
-            yield return new object[] { "abc", "abc", "def", false, null, "def" };
-            yield return new object[] { "abc", "ABC", "def", false, null, "abc" };
-            yield return new object[] { "abc", "abc", "def", false, CultureInfo.InvariantCulture, "def" };
-            yield return new object[] { "abc", "ABC", "def", false, CultureInfo.InvariantCulture, "abc" };
-
-            yield return new object[] { "abc", "abc", "def", true, null, "def" };
-            yield return new object[] { "abc", "ABC", "def", true, null, "def" };
-            yield return new object[] { "abc", "abc", "def", true, CultureInfo.InvariantCulture, "def" };
-            yield return new object[] { "abc", "ABC", "def", true, CultureInfo.InvariantCulture, "def" };
-
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", false, null, "def" };
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", true, null, "def" };
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", false, CultureInfo.InvariantCulture, "def" };
-            yield return new object[] { "abc", "abc" + SoftHyphen, "def", true, CultureInfo.InvariantCulture, "def" };
-
-            yield return new object[] { "\u0069\u0130", "\u0069", "a", false, new CultureInfo("tr-TR"), "a\u0130" };
-            yield return new object[] { "\u0069\u0130", "\u0069", "a", true, new CultureInfo("tr-TR"), "aa" };
-            yield return new object[] { "\u0069\u0130", "\u0069", "a", false, CultureInfo.InvariantCulture, "a\u0130" };
-            yield return new object[] { "\u0069\u0130", "\u0069", "a", true, CultureInfo.InvariantCulture, "a\u0130" };
-        }
-
-        [Theory]
-        [MemberData(nameof(Replace_StringComparisonCulture_TestData))]
-        public void Replace_StringComparisonCulture_ReturnsExpected(string original, string oldValue, string newValue, bool ignoreCase, CultureInfo culture, string expected)
-        {
-            Assert.Equal(expected, original.Replace(oldValue, newValue, ignoreCase, culture));
-            if (culture == null)
-            {
-                Assert.Equal(expected, original.Replace(oldValue, newValue, ignoreCase, CultureInfo.CurrentCulture));
-            }
-        }
-
-        [Fact]
-        public void Replace_StringComparison_NullOldValue_ThrowsArgumentException()
-        {
-            AssertExtensions.Throws<ArgumentNullException>("oldValue", () => "abc".Replace(null, "def", StringComparison.CurrentCulture));
-            AssertExtensions.Throws<ArgumentNullException>("oldValue", () => "abc".Replace(null, "def", true, CultureInfo.CurrentCulture));
-        }
-
-        [Fact]
-        public void Replace_StringComparison_EmptyOldValue_ThrowsArgumentException()
-        {
-            AssertExtensions.Throws<ArgumentException>("oldValue", () => "abc".Replace("", "def", StringComparison.CurrentCulture));
-            AssertExtensions.Throws<ArgumentException>("oldValue", () => "abc".Replace("", "def", true, CultureInfo.CurrentCulture));
-        }
-
-        [Theory]
-        [InlineData(StringComparison.CurrentCulture - 1)]
-        [InlineData(StringComparison.OrdinalIgnoreCase + 1)]
-        public void Replace_NoSuchStringComparison_ThrowsArgumentException(StringComparison comparisonType)
-        {
-            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "abc".Replace("abc", "def", comparisonType));
-        }
-
-
-        private static readonly StringComparison[] StringComparisons = (StringComparison[])Enum.GetValues(typeof(StringComparison));
-
-        [Fact]
-        public static void GetHashCode_OfSpan_EmbeddedNull_ReturnsDifferentHashCodes()
-        {
-            Assert.NotEqual(string.GetHashCode("\0AAAAAAAAA".AsSpan()), string.GetHashCode("\0BBBBBBBBBBBB".AsSpan()));
-        }
-
-        [Fact]
-        public static void GetHashCode_OfSpan_MatchesOfString()
-        {
-            // parameterless should be ordinal only
-            Assert.Equal("abc".GetHashCode(), string.GetHashCode("abc".AsSpan()));
-            Assert.NotEqual("abc".GetHashCode(), string.GetHashCode("ABC".AsSpan())); // case differences
-        }
-
-        [Fact]
-        public static void GetHashCode_CompareInfo()
-        {
-            // ordinal
-            Assert.Equal("abc".GetHashCode(), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("abc", CompareOptions.Ordinal));
-            Assert.NotEqual("abc".GetHashCode(), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("ABC", CompareOptions.Ordinal));
-
-            // ordinal ignore case
-            Assert.Equal("abc".GetHashCode(StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("abc", CompareOptions.OrdinalIgnoreCase));
-            Assert.Equal("abc".GetHashCode(StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("ABC", CompareOptions.OrdinalIgnoreCase));
-
-            // culture-aware
-            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.CurrentCulture), CultureInfo.CurrentCulture.CompareInfo.GetHashCode("aeiXXabc", CompareOptions.None));
-            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.CurrentCultureIgnoreCase), CultureInfo.CurrentCulture.CompareInfo.GetHashCode("aeiXXabc", CompareOptions.IgnoreCase));
-
-            // invariant culture
-            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.InvariantCulture), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("aeiXXabc", CompareOptions.None));
-            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.InvariantCultureIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("aeiXXabc", CompareOptions.IgnoreCase));
-        }
-
-        [Fact]
-        public static void GetHashCode_CompareInfo_OfSpan()
-        {
-            // ordinal
-            Assert.Equal("abc".GetHashCode(), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("abc".AsSpan(), CompareOptions.Ordinal));
-            Assert.NotEqual("abc".GetHashCode(), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("ABC".AsSpan(), CompareOptions.Ordinal));
-
-            // ordinal ignore case
-            Assert.Equal("abc".GetHashCode(StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("abc".AsSpan(), CompareOptions.OrdinalIgnoreCase));
-            Assert.Equal("abc".GetHashCode(StringComparison.OrdinalIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("ABC".AsSpan(), CompareOptions.OrdinalIgnoreCase));
-
-            // culture-aware
-            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.CurrentCulture), CultureInfo.CurrentCulture.CompareInfo.GetHashCode("aeiXXabc".AsSpan(), CompareOptions.None));
-            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.CurrentCultureIgnoreCase), CultureInfo.CurrentCulture.CompareInfo.GetHashCode("aeiXXabc".AsSpan(), CompareOptions.IgnoreCase));
-
-            // invariant culture
-            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.InvariantCulture), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("aeiXXabc".AsSpan(), CompareOptions.None));
-            Assert.Equal("aeiXXabc".GetHashCode(StringComparison.InvariantCultureIgnoreCase), CultureInfo.InvariantCulture.CompareInfo.GetHashCode("aeiXXabc".AsSpan(), CompareOptions.IgnoreCase));
-        }
-
-        public static IEnumerable<object[]> GetHashCode_StringComparison_Data => StringComparisons.Select(value => new object[] { value });
-
-        [Theory]
-        [MemberData(nameof(GetHashCode_StringComparison_Data))]
-        public static void GetHashCode_StringComparison(StringComparison comparisonType)
-        {
-            int hashCodeFromStringComparer = StringComparer.FromComparison(comparisonType).GetHashCode("abc");
-            int hashCodeFromStringGetHashCode = "abc".GetHashCode(comparisonType);
-            int hashCodeFromStringGetHashCodeOfSpan = string.GetHashCode("abc".AsSpan(), comparisonType);
-
-            Assert.Equal(hashCodeFromStringComparer, hashCodeFromStringGetHashCode);
-            Assert.Equal(hashCodeFromStringComparer, hashCodeFromStringGetHashCodeOfSpan);
-        }
-
-        public static IEnumerable<object[]> GetHashCode_NoSuchStringComparison_ThrowsArgumentException_Data => new[]
-        {
-            new object[] { StringComparisons.Min() - 1 },
-            new object[] { StringComparisons.Max() + 1 },
-        };
-
-        [Theory]
-        [MemberData(nameof(GetHashCode_NoSuchStringComparison_ThrowsArgumentException_Data))]
-        public static void GetHashCode_NoSuchStringComparison_ThrowsArgumentException(StringComparison comparisonType)
-        {
-            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "abc".GetHashCode(comparisonType));
-            AssertExtensions.Throws<ArgumentException>("comparisonType", () => string.GetHashCode("abc".AsSpan(), comparisonType));
-        }
-
-        [Theory]
-        [InlineData("")] // empty string
-        [InlineData("hello")] // non-empty string
-        public static unsafe void GetPinnableReference_ReturnsSameAsGCHandleAndLegacyFixed(string input)
-        {
-            Assert.NotNull(input); // test shouldn't have null input
-
-            // First, ensure the value pointed to by GetPinnableReference is correct.
-            // It should point to the first character (or the null terminator for empty inputs).
-
-            ref readonly char rChar = ref input.GetPinnableReference();
-            Assert.Equal((input.Length > 0) ? input[0] : '\0', rChar);
-
-            // Next, ensure that GetPinnableReference() and GCHandle.AddrOfPinnedObject agree
-            // on the address being returned.
-
-            GCHandle gcHandle = GCHandle.Alloc(input, GCHandleType.Pinned);
-            try
-            {
-                Assert.Equal((IntPtr)Unsafe.AsPointer(ref Unsafe.AsRef(in rChar)), gcHandle.AddrOfPinnedObject());
-            }
-            finally
-            {
-                gcHandle.Free();
-            }
-
-            // Next, ensure that GetPinnableReference matches the string projected as a ROS<char>.
-
-            Assert.True(Unsafe.AreSame(ref Unsafe.AsRef(in rChar), ref MemoryMarshal.GetReference((ReadOnlySpan<char>)input)));
-
-            // Finally, ensure that GetPinnableReference matches the legacy 'fixed' keyword.
-
-            DynamicMethod dynamicMethod = new DynamicMethod("tester", typeof(bool), new[] { typeof(string) });
-            ILGenerator ilGen = dynamicMethod.GetILGenerator();
-            LocalBuilder pinnedLocal = ilGen.DeclareLocal(typeof(object), pinned: true);
-
-            ilGen.Emit(OpCodes.Ldarg_0); // load 'input' and pin it
-            ilGen.Emit(OpCodes.Stloc, pinnedLocal);
-
-            ilGen.Emit(OpCodes.Ldloc, pinnedLocal); // get the address of field 0 from pinned 'input'
-            ilGen.Emit(OpCodes.Conv_I);
-
-            ilGen.Emit(OpCodes.Call, typeof(RuntimeHelpers).GetProperty("OffsetToStringData").GetMethod); // get pointer to start of string data
-            ilGen.Emit(OpCodes.Add);
-
-            ilGen.Emit(OpCodes.Ldarg_0); // get value of input.GetPinnableReference()
-            ilGen.Emit(OpCodes.Callvirt, typeof(string).GetMethod("GetPinnableReference"));
-
-            // At this point, the top of the evaluation stack is traditional (fixed char* = input) and input.GetPinnableReference().
-            // Compare for equality and return.
-
-            ilGen.Emit(OpCodes.Ceq);
-            ilGen.Emit(OpCodes.Ret);
-
-            Assert.True((bool)dynamicMethod.Invoke(null, new[] { input }));
-        }
-
-        [Fact]
-        public static unsafe void GetPinnableReference_WithNullInput_ThrowsNullRef()
-        {
-            // This test uses an explicit call instead of the normal callvirt that C# would emit.
-            // This allows us to make sure the NullReferenceException is coming from *within*
-            // the GetPinnableReference method rather than on the call site to that method.
-
-            DynamicMethod dynamicMethod = new DynamicMethod("tester", typeof(void), Type.EmptyTypes);
-            ILGenerator ilGen = dynamicMethod.GetILGenerator();
-
-            ilGen.Emit(OpCodes.Ldnull);
-            ilGen.Emit(OpCodes.Call, typeof(string).GetMethod("GetPinnableReference"));
-            ilGen.Emit(OpCodes.Pop);
-            ilGen.Emit(OpCodes.Ret);
-
-            Action del = (Action)dynamicMethod.CreateDelegate(typeof(Action));
-
-            Assert.NotNull(del);
-            Assert.Throws<NullReferenceException>(del);
-        }
-
-        [Theory]
-        [InlineData("")]
-        [InlineData("a")]
-        [InlineData("\0")]
-        [InlineData("abc")]
-        public static unsafe void ImplicitCast_ResultingSpanMatches(string s)
-        {
-            ReadOnlySpan<char> span = s;
-            Assert.Equal(s.Length, span.Length);
-            fixed (char* stringPtr = s)
-            fixed (char* spanPtr = &MemoryMarshal.GetReference(span))
-            {
-                Assert.Equal((IntPtr)stringPtr, (IntPtr)spanPtr);
-            }
-        }
-
-        [Fact]
-        public static void ImplicitCast_NullString_ReturnsDefaultSpan()
-        {
-            ReadOnlySpan<char> span = (string)null;
-            Assert.True(span == default);
-        }
-
-        [Theory]
-        [InlineData("Hello", 'l', StringComparison.Ordinal, 2)]
-        [InlineData("Hello", 'x', StringComparison.Ordinal, -1)]
-        [InlineData("Hello", 'h', StringComparison.Ordinal, -1)]
-        [InlineData("Hello", 'o', StringComparison.Ordinal, 4)]
-        [InlineData("Hello", 'h', StringComparison.OrdinalIgnoreCase, 0)]
-        [InlineData("HelLo", 'L', StringComparison.OrdinalIgnoreCase, 2)]
-        [InlineData("HelLo", 'L', StringComparison.Ordinal, 3)]
-        [InlineData("HelLo", '\0', StringComparison.Ordinal, -1)]
-        [InlineData("!@#$%", '%', StringComparison.Ordinal, 4)]
-        [InlineData("!@#$", '!', StringComparison.Ordinal, 0)]
-        [InlineData("!@#$", '@', StringComparison.Ordinal, 1)]
-        [InlineData("!@#$%", '%', StringComparison.OrdinalIgnoreCase, 4)]
-        [InlineData("!@#$", '!', StringComparison.OrdinalIgnoreCase, 0)]
-        [InlineData("!@#$", '@', StringComparison.OrdinalIgnoreCase, 1)]
-        [InlineData("_____________\u807f", '\u007f', StringComparison.Ordinal, -1)]
-        [InlineData("_____________\u807f__", '\u007f', StringComparison.Ordinal, -1)]
-        [InlineData("_____________\u807f\u007f_", '\u007f', StringComparison.Ordinal, 14)]
-        [InlineData("__\u807f_______________", '\u007f', StringComparison.Ordinal, -1)]
-        [InlineData("__\u807f___\u007f___________", '\u007f', StringComparison.Ordinal, 6)]
-        [InlineData("_____________\u807f", '\u007f', StringComparison.OrdinalIgnoreCase, -1)]
-        [InlineData("_____________\u807f__", '\u007f', StringComparison.OrdinalIgnoreCase, -1)]
-        [InlineData("_____________\u807f\u007f_", '\u007f', StringComparison.OrdinalIgnoreCase, 14)]
-        [InlineData("__\u807f_______________", '\u007f', StringComparison.OrdinalIgnoreCase, -1)]
-        [InlineData("__\u807f___\u007f___________", '\u007f', StringComparison.OrdinalIgnoreCase, 6)]
-        public static void IndexOf_SingleLetter(string s, char target, StringComparison stringComparison, int expected)
-        {
-            Assert.Equal(expected, s.IndexOf(target, stringComparison));
-            var charArray = new char[1];
-            charArray[0] = target;
-            Assert.Equal(expected, s.AsSpan().IndexOf(charArray, stringComparison));
-        }
-
-        [Fact]
-        public static void IndexOf_TurkishI_TurkishCulture_Char()
-        {
-            using (new ThreadCultureChange("tr-TR"))
-            {
-                string s = "Turkish I \u0131s TROUBL\u0130NG!";
-                char value = '\u0130';
-                Assert.Equal(19, s.IndexOf(value));
-                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(4, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-                Assert.Equal(19, s.IndexOf(value, StringComparison.Ordinal));
-                Assert.Equal(19, s.IndexOf(value, StringComparison.OrdinalIgnoreCase));
-
-                ReadOnlySpan<char> span = s.AsSpan();
-                Assert.Equal(19, span.IndexOf(new char[] { value }, StringComparison.CurrentCulture));
-                Assert.Equal(4, span.IndexOf(new char[] { value }, StringComparison.CurrentCultureIgnoreCase));
-                Assert.Equal(19, span.IndexOf(new char[] { value }, StringComparison.Ordinal));
-                Assert.Equal(19, span.IndexOf(new char[] { value }, StringComparison.OrdinalIgnoreCase));
-
-                value = '\u0131';
-                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(8, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-                Assert.Equal(10, s.IndexOf(value, StringComparison.Ordinal));
-                Assert.Equal(10, s.IndexOf(value, StringComparison.OrdinalIgnoreCase));
-
-                Assert.Equal(10, span.IndexOf(new char[] { value }, StringComparison.CurrentCulture));
-                Assert.Equal(8, span.IndexOf(new char[] { value }, StringComparison.CurrentCultureIgnoreCase));
-                Assert.Equal(10, span.IndexOf(new char[] { value }, StringComparison.Ordinal));
-                Assert.Equal(10, span.IndexOf(new char[] { value }, StringComparison.OrdinalIgnoreCase));
-            }
-        }
-
-        [Fact]
-        public static void IndexOf_TurkishI_InvariantCulture_Char()
-        {
-            using (new ThreadCultureChange(CultureInfo.InvariantCulture))
-            {
-                string s = "Turkish I \u0131s TROUBL\u0130NG!";
-                char value = '\u0130';
-
-                Assert.Equal(19, s.IndexOf(value));
-                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-
-                value = '\u0131';
-                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-            }
-        }
-
-        [Fact]
-        public static void IndexOf_TurkishI_EnglishUSCulture_Char()
-        {
-            using (new ThreadCultureChange("en-US"))
-            {
-                string s = "Turkish I \u0131s TROUBL\u0130NG!";
-                char value = '\u0130';
-
-                Assert.Equal(19, s.IndexOf(value));
-                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(19, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-
-                value = '\u0131';
-                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-            }
-        }
-
-        [Fact]
-        public static void IndexOf_EquivalentDiacritics_EnglishUSCulture_Char()
-        {
-            string s = "Exhibit a\u0300\u00C0";
-            char value = '\u00C0';
-
-            using (new ThreadCultureChange("en-US"))
-            {
-                Assert.Equal(10, s.IndexOf(value));
-                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(8, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-                Assert.Equal(10, s.IndexOf(value, StringComparison.Ordinal));
-                Assert.Equal(10, s.IndexOf(value, StringComparison.OrdinalIgnoreCase));
-            }
-        }
-
-        [Fact]
-        public static void IndexOf_EquivalentDiacritics_InvariantCulture_Char()
-        {
-            string s = "Exhibit a\u0300\u00C0";
-            char value = '\u00C0';
-
-            using (new ThreadCultureChange(CultureInfo.InvariantCulture))
-            {
-                Assert.Equal(10, s.IndexOf(value));
-                Assert.Equal(10, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(8, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-            }
-        }
-
-        [Fact]
-        public static void IndexOf_CyrillicE_EnglishUSCulture_Char()
-        {
-            string s = "Foo\u0400Bar";
-            char value = '\u0400';
-
-            using (new ThreadCultureChange("en-US"))
-            {
-                Assert.Equal(3, s.IndexOf(value));
-                Assert.Equal(3, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(3, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-                Assert.Equal(3, s.IndexOf(value, StringComparison.Ordinal));
-                Assert.Equal(3, s.IndexOf(value, StringComparison.OrdinalIgnoreCase));
-            }
-        }
-
-        [Fact]
-        public static void IndexOf_CyrillicE_InvariantCulture_Char()
-        {
-            string s = "Foo\u0400Bar";
-            char value = '\u0400';
-
-            using (new ThreadCultureChange(CultureInfo.InvariantCulture))
-            {
-                Assert.Equal(3, s.IndexOf(value));
-                Assert.Equal(3, s.IndexOf(value, StringComparison.CurrentCulture));
-                Assert.Equal(3, s.IndexOf(value, StringComparison.CurrentCultureIgnoreCase));
-            }
-        }
-
-        [Fact]
-        public static void IndexOf_Invalid_Char()
-        {
-            // Invalid comparison type
-            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "foo".IndexOf('o', StringComparison.CurrentCulture - 1));
-            AssertExtensions.Throws<ArgumentException>("comparisonType", () => "foo".IndexOf('o', StringComparison.OrdinalIgnoreCase + 1));
-        }
-
-        [Theory]
-        [MemberData(nameof(Concat_Strings_2_3_4_TestData))]
-        public static void Concat_Spans(string[] values, string expected)
-        {
-            Assert.InRange(values.Length, 2, 4);
-
-            string result =
-                values.Length == 2 ? string.Concat(values[0].AsSpan(), values[1].AsSpan()) :
-                values.Length == 3 ? string.Concat(values[0].AsSpan(), values[1].AsSpan(), values[2].AsSpan()) :
-                string.Concat(values[0].AsSpan(), values[1].AsSpan(), values[2].AsSpan(), values[3].AsSpan());
-
-            if (result.Length == 0)
-            {
-                Assert.Same(string.Empty, result);
-            }
-
-            Assert.Equal(expected, result);
-        }
-
-        [Fact]
-        public static void IndexerUsingIndexTest()
-        {
-            Index index;
-            string s = "0123456789ABCDEF";
-
-            for (int i = 0; i < s.Length; i++)
-            {
-                index = Index.FromStart(i);
-                Assert.Equal(s[i], s[index]);
-
-                index = Index.FromEnd(i + 1);
-                Assert.Equal(s[s.Length - i - 1], s[index]);
-            }
-
-            index = Index.FromStart(s.Length + 1);
-            char c;
-            Assert.Throws<IndexOutOfRangeException>(() => c = s[index]);
-
-            index = Index.FromEnd(s.Length + 1);
-            Assert.Throws<IndexOutOfRangeException>(() => c = s[index]);
-        }
-
-        [Fact]
-        public static void IndexerUsingRangeTest()
-        {
-            Range range;
-            string s = "0123456789ABCDEF";
-
-            for (int i = 0; i < s.Length; i++)
-            {
-                range = new Range(Index.FromStart(0), Index.FromStart(i));
-                Assert.Equal(s.Substring(0, i), s[range]);
-
-                range = new Range(Index.FromEnd(s.Length), Index.FromEnd(i));
-                Assert.Equal(s.Substring(0, s.Length - i), s[range]);
-            }
-
-            range = new Range(Index.FromStart(s.Length - 2), Index.FromStart(s.Length + 1));
-            string s1;
-            Assert.Throws<ArgumentOutOfRangeException>(() => s1 = s[range]);
-
-            range = new Range(Index.FromEnd(s.Length + 1), Index.FromEnd(0));
-            Assert.Throws<ArgumentOutOfRangeException>(() => s1 = s[range]);
-        }
-
-        [Fact]
-        public static void SubstringUsingIndexTest()
-        {
-            string s = "0123456789ABCDEF";
-
-            for (int i = 0; i < s.Length; i++)
-            {
-                Assert.Equal(s.Substring(i), s[i..]);
-                Assert.Equal(s.Substring(s.Length - i - 1), s[^(i + 1)..]);
-            }
-
-            // String.Substring allows the string length as a valid input.
-            Assert.Equal(s.Substring(s.Length), s[s.Length..]);
-
-            Assert.Throws<ArgumentOutOfRangeException>(() => s[(s.Length + 1)..]);
-            Assert.Throws<ArgumentOutOfRangeException>(() => s[^(s.Length + 1)..]);
-        }
-
-        [Fact]
-        public static void SubstringUsingRangeTest()
-        {
-            string s = "0123456789ABCDEF";
-            Range range;
-
-            for (int i = 0; i < s.Length; i++)
-            {
-                range = new Range(Index.FromStart(0), Index.FromStart(i));
-                Assert.Equal(s.Substring(0, i), s[range]);
-
-                range = new Range(Index.FromEnd(s.Length), Index.FromEnd(i));
-                Assert.Equal(s.Substring(0, s.Length - i), s[range]);
-            }
-
-            range = new Range(Index.FromStart(s.Length - 2), Index.FromStart(s.Length + 1));
-            string s1;
-            Assert.Throws<ArgumentOutOfRangeException>(() => s1 = s[range]);
-
-            range = new Range(Index.FromEnd(s.Length + 1), Index.FromEnd(0));
-            Assert.Throws<ArgumentOutOfRangeException>(() => s1 = s[range]);
-        }
-
-        /// <summary>
-        /// Returns true only if U+0020 SPACE is represented as the single byte 0x20 in the active code page.
-        /// </summary>
-        public static unsafe bool IsSimpleActiveCodePage
-        {
-            get
-            {
-                IntPtr pAnsiStr = IntPtr.Zero;
-                try
-                {
-                    pAnsiStr = Marshal.StringToHGlobalAnsi(" ");
-                    return ((byte*)pAnsiStr)[0] == (byte)' ' && ((byte*)pAnsiStr)[1] == (byte)'\0';
-                }
-                finally
-                {
-                    if (pAnsiStr != IntPtr.Zero)
-                    {
-                        Marshal.FreeHGlobal(pAnsiStr);
-                    }
-                }
-            }
-        }
-
-        [Theory]
-        [InlineData("  Hello  ", "Hello")]
-        [InlineData("      \t      ", "")]
-        [InlineData("", "")]
-        [InlineData("      ", "")]
-        public static void Trim_Memory(string s, string expected)
-        {
-            Assert.Equal(expected, s.AsSpan().Trim().ToString()); // ReadOnlySpan
-            Assert.Equal(expected, new Span<char>(s.ToCharArray()).Trim().ToString());
-            Assert.Equal(expected, new Memory<char>(s.ToCharArray()).Trim().ToString());
-            Assert.Equal(expected, s.AsMemory().Trim().ToString()); // ReadOnlyMemory
-        }
-
-        [Theory]
-        [InlineData("  Hello  ", "  Hello")]
-        [InlineData("      \t      ", "")]
-        [InlineData("", "")]
-        [InlineData("      ", "")]
-        public static void TrimEnd_Memory(string s, string expected)
-        {
-            Assert.Equal(expected, s.AsSpan().TrimEnd().ToString()); // ReadOnlySpan
-            Assert.Equal(expected, new Span<char>(s.ToCharArray()).TrimEnd().ToString());
-            Assert.Equal(expected, new Memory<char>(s.ToCharArray()).TrimEnd().ToString());
-            Assert.Equal(expected, s.AsMemory().TrimEnd().ToString()); // ReadOnlyMemory
-        }
-
-        [Theory]
-        [InlineData("  Hello  ", "Hello  ")]
-        [InlineData("      \t      ", "")]
-        [InlineData("", "")]
-        [InlineData("      ", "")]
-        public static void TrimStart_Memory(string s, string expected)
-        {
-            Assert.Equal(expected, s.AsSpan().TrimStart().ToString()); // ReadOnlySpan
-            Assert.Equal(expected, new Span<char>(s.ToCharArray()).TrimStart().ToString());
-            Assert.Equal(expected, new Memory<char>(s.ToCharArray()).TrimStart().ToString());
-            Assert.Equal(expected, s.AsMemory().TrimStart().ToString()); // ReadOnlyMemory
-        }
-
-        [Fact]
-        public static void ZeroLengthTrim_Memory()
-        {
-            string s1 = string.Empty;
-
-            ReadOnlySpan<char> ros = s1.AsSpan();
-            Assert.True(ros.SequenceEqual(ros.Trim()));
-            Assert.True(ros.SequenceEqual(ros.TrimStart()));
-            Assert.True(ros.SequenceEqual(ros.TrimEnd()));
-
-            Span<char> span = new Span<char>(s1.ToCharArray());
-            Assert.True(span.SequenceEqual(span.Trim()));
-            Assert.True(span.SequenceEqual(span.TrimStart()));
-            Assert.True(span.SequenceEqual(span.TrimEnd()));
-
-            Memory<char> mem = new Memory<char>(s1.ToCharArray());
-            Assert.True(mem.Span.SequenceEqual(mem.Trim().Span));
-            Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
-            Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
-
-            ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(s1.ToCharArray());
-            Assert.True(rom.Span.SequenceEqual(rom.Trim().Span));
-            Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
-            Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
-        }
-
-        [Fact]
-        public static void NoWhiteSpaceTrim_Memory()
-        {
-            for (int length = 0; length < 32; length++)
-            {
-                char[] a = new char[length];
-                for (int i = 0; i < length; i++)
-                {
-                    a[i] = 'a';
-                }
-                string s1 = new string(a);
-
-                ReadOnlySpan<char> ros = s1.AsSpan();
-                Assert.True(ros.SequenceEqual(ros.Trim()));
-                Assert.True(ros.SequenceEqual(ros.TrimStart()));
-                Assert.True(ros.SequenceEqual(ros.TrimEnd()));
-
-                Span<char> span = new Span<char>(a);
-                Assert.True(span.SequenceEqual(span.Trim()));
-                Assert.True(span.SequenceEqual(span.TrimStart()));
-                Assert.True(span.SequenceEqual(span.TrimEnd()));
-
-                Memory<char> mem = new Memory<char>(a);
-                Assert.True(mem.Span.SequenceEqual(mem.Trim().Span));
-                Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
-                Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
-
-                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
-                Assert.True(rom.Span.SequenceEqual(rom.Trim().Span));
-                Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
-                Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
-            }
-        }
-
-        [Fact]
-        public static void OnlyWhiteSpaceTrim_Memory()
-        {
-            for (int length = 0; length < 32; length++)
-            {
-                char[] a = new char[length];
-                for (int i = 0; i < length; i++)
-                {
-                    a[i] = ' ';
-                }
-                string s1 = new string(a);
-
-                ReadOnlySpan<char> ros = new ReadOnlySpan<char>(a);
-                Assert.True(ReadOnlySpan<char>.Empty.SequenceEqual(ros.Trim()));
-                Assert.True(ReadOnlySpan<char>.Empty.SequenceEqual(ros.TrimStart()));
-                Assert.True(ReadOnlySpan<char>.Empty.SequenceEqual(ros.TrimEnd()));
-
-                Span<char> span = new Span<char>(a);
-                Assert.True(Span<char>.Empty.SequenceEqual(span.Trim()));
-                Assert.True(Span<char>.Empty.SequenceEqual(span.TrimStart()));
-                Assert.True(Span<char>.Empty.SequenceEqual(span.TrimEnd()));
-
-                Memory<char> mem = new Memory<char>(a);
-                Assert.True(Memory<char>.Empty.Span.SequenceEqual(mem.Trim().Span));
-                Assert.True(Memory<char>.Empty.Span.SequenceEqual(mem.TrimStart().Span));
-                Assert.True(Memory<char>.Empty.Span.SequenceEqual(mem.TrimEnd().Span));
-
-                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
-                Assert.True(ReadOnlyMemory<char>.Empty.Span.SequenceEqual(rom.Trim().Span));
-                Assert.True(ReadOnlyMemory<char>.Empty.Span.SequenceEqual(rom.TrimStart().Span));
-                Assert.True(ReadOnlyMemory<char>.Empty.Span.SequenceEqual(rom.TrimEnd().Span));
-            }
-        }
-
-        [Fact]
-        public static void WhiteSpaceAtStartTrim_Memory()
-        {
-            for (int length = 2; length < 32; length++)
-            {
-                char[] a = new char[length];
-                for (int i = 0; i < length; i++)
-                {
-                    a[i] = 'a';
-                }
-                a[0] = ' ';
-                string s1 = new string(a);
-
-                ReadOnlySpan<char> ros = s1.AsSpan();
-                Assert.True(ros.Slice(1).SequenceEqual(ros.Trim()));
-                Assert.True(ros.Slice(1).SequenceEqual(ros.TrimStart()));
-                Assert.True(ros.SequenceEqual(ros.TrimEnd()));
-
-                Span<char> span = new Span<char>(a);
-                Assert.True(span.Slice(1).SequenceEqual(span.Trim()));
-                Assert.True(span.Slice(1).SequenceEqual(span.TrimStart()));
-                Assert.True(span.SequenceEqual(span.TrimEnd()));
-
-                Memory<char> mem = new Memory<char>(a);
-                Assert.True(mem.Slice(1).Span.SequenceEqual(mem.Trim().Span));
-                Assert.True(mem.Slice(1).Span.SequenceEqual(mem.TrimStart().Span));
-                Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
-
-                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
-                Assert.True(rom.Slice(1).Span.SequenceEqual(rom.Trim().Span));
-                Assert.True(rom.Slice(1).Span.SequenceEqual(rom.TrimStart().Span));
-                Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
-            }
-        }
-
-        [Fact]
-        public static void WhiteSpaceAtEndTrim_Memory()
-        {
-            for (int length = 2; length < 32; length++)
-            {
-                char[] a = new char[length];
-                for (int i = 0; i < length; i++)
-                {
-                    a[i] = 'a';
-                }
-                a[length - 1] = ' ';
-                string s1 = new string(a);
-
-                ReadOnlySpan<char> ros = s1.AsSpan();
-                Assert.True(ros.Slice(0, length - 1).SequenceEqual(ros.Trim()));
-                Assert.True(ros.SequenceEqual(ros.TrimStart()));
-                Assert.True(ros.Slice(0, length - 1).SequenceEqual(ros.TrimEnd()));
-
-                Span<char> span = new Span<char>(a);
-                Assert.True(span.Slice(0, length - 1).SequenceEqual(span.Trim()));
-                Assert.True(span.SequenceEqual(span.TrimStart()));
-                Assert.True(span.Slice(0, length - 1).SequenceEqual(span.TrimEnd()));
-
-                Memory<char> mem = new Memory<char>(a);
-                Assert.True(mem.Slice(0, length - 1).Span.SequenceEqual(mem.Trim().Span));
-                Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
-                Assert.True(mem.Slice(0, length - 1).Span.SequenceEqual(mem.TrimEnd().Span));
-
-                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
-                Assert.True(rom.Slice(0, length - 1).Span.SequenceEqual(rom.Trim().Span));
-                Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
-                Assert.True(rom.Slice(0, length - 1).Span.SequenceEqual(rom.TrimEnd().Span));
-            }
-        }
-
-        [Fact]
-        public static void WhiteSpaceAtStartAndEndTrim_Memory()
-        {
-            for (int length = 3; length < 32; length++)
-            {
-                char[] a = new char[length];
-                for (int i = 0; i < length; i++)
-                {
-                    a[i] = 'a';
-                }
-                a[0] = ' ';
-                a[length - 1] = ' ';
-                string s1 = new string(a);
-
-                ReadOnlySpan<char> ros = s1.AsSpan();
-                Assert.True(ros.Slice(1, length - 2).SequenceEqual(ros.Trim()));
-                Assert.True(ros.Slice(1).SequenceEqual(ros.TrimStart()));
-                Assert.True(ros.Slice(0, length - 1).SequenceEqual(ros.TrimEnd()));
-
-                Span<char> span = new Span<char>(a);
-                Assert.True(span.Slice(1, length - 2).SequenceEqual(span.Trim()));
-                Assert.True(span.Slice(1).SequenceEqual(span.TrimStart()));
-                Assert.True(span.Slice(0, length - 1).SequenceEqual(span.TrimEnd()));
-
-                Memory<char> mem = new Memory<char>(a);
-                Assert.True(mem.Slice(1, length - 2).Span.SequenceEqual(mem.Trim().Span));
-                Assert.True(mem.Slice(1).Span.SequenceEqual(mem.TrimStart().Span));
-                Assert.True(mem.Slice(0, length - 1).Span.SequenceEqual(mem.TrimEnd().Span));
-
-                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
-                Assert.True(rom.Slice(1, length - 2).Span.SequenceEqual(rom.Trim().Span));
-                Assert.True(rom.Slice(1).Span.SequenceEqual(rom.TrimStart().Span));
-                Assert.True(rom.Slice(0, length - 1).Span.SequenceEqual(rom.TrimEnd().Span));
-            }
-        }
-
-        [Fact]
-        public static void WhiteSpaceInMiddleTrim_Memory()
-        {
-            for (int length = 3; length < 32; length++)
-            {
-                char[] a = new char[length];
-                for (int i = 0; i < length; i++)
-                {
-                    a[i] = 'a';
-                }
-                a[1] = ' ';
-                string s1 = new string(a);
-
-                ReadOnlySpan<char> ros = s1.AsSpan();
-                Assert.True(ros.SequenceEqual(ros.Trim()));
-                Assert.True(ros.SequenceEqual(ros.TrimStart()));
-                Assert.True(ros.SequenceEqual(ros.TrimEnd()));
-
-                Span<char> span = new Span<char>(a);
-                Assert.True(span.SequenceEqual(span.Trim()));
-                Assert.True(span.SequenceEqual(span.TrimStart()));
-                Assert.True(span.SequenceEqual(span.TrimEnd()));
-
-                Memory<char> mem = new Memory<char>(a);
-                Assert.True(mem.Span.SequenceEqual(mem.Trim().Span));
-                Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
-                Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
-
-                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
-                Assert.True(rom.Span.SequenceEqual(rom.Trim().Span));
-                Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
-                Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
-            }
-        }
-
-        [Fact]
-        public static void TrimWhiteSpaceMultipleTimes_Memory()
-        {
-            for (int length = 3; length < 32; length++)
-            {
-                char[] a = new char[length];
-                for (int i = 0; i < length; i++)
-                {
-                    a[i] = 'a';
-                }
-                a[0] = ' ';
-                a[length - 1] = ' ';
-                string s1 = new string(a);
-
-                // ReadOnlySpan
-                {
-                    ReadOnlySpan<char> ros = s1.AsSpan();
-                    ReadOnlySpan<char> trimResult = ros.Trim();
-                    ReadOnlySpan<char> trimStartResult = ros.TrimStart();
-                    ReadOnlySpan<char> trimEndResult = ros.TrimEnd();
-                    Assert.True(ros.Slice(1, length - 2).SequenceEqual(trimResult));
-                    Assert.True(ros.Slice(1).SequenceEqual(trimStartResult));
-                    Assert.True(ros.Slice(0, length - 1).SequenceEqual(trimEndResult));
-
-                    // 2nd attempt should do nothing
-                    Assert.True(trimResult.SequenceEqual(trimResult.Trim()));
-                    Assert.True(trimStartResult.SequenceEqual(trimStartResult.TrimStart()));
-                    Assert.True(trimEndResult.SequenceEqual(trimEndResult.TrimEnd()));
-                }
-
-                // Span
-                {
-                    Span<char> span = new Span<char>(a);
-                    Span<char> trimResult = span.Trim();
-                    Span<char> trimStartResult = span.TrimStart();
-                    Span<char> trimEndResult = span.TrimEnd();
-                    Assert.True(span.Slice(1, length - 2).SequenceEqual(trimResult));
-                    Assert.True(span.Slice(1).SequenceEqual(trimStartResult));
-                    Assert.True(span.Slice(0, length - 1).SequenceEqual(trimEndResult));
-
-                    // 2nd attempt should do nothing
-                    Assert.True(trimResult.SequenceEqual(trimResult.Trim()));
-                    Assert.True(trimStartResult.SequenceEqual(trimStartResult.TrimStart()));
-                    Assert.True(trimEndResult.SequenceEqual(trimEndResult.TrimEnd()));
-                }
-
-                // Memory
-                {
-                    Memory<char> mem = new Memory<char>(a);
-                    Memory<char> trimResult = mem.Trim();
-                    Memory<char> trimStartResult = mem.TrimStart();
-                    Memory<char> trimEndResult = mem.TrimEnd();
-                    Assert.True(mem.Slice(1, length - 2).Span.SequenceEqual(trimResult.Span));
-                    Assert.True(mem.Slice(1).Span.SequenceEqual(trimStartResult.Span));
-                    Assert.True(mem.Slice(0, length - 1).Span.SequenceEqual(trimEndResult.Span));
-
-                    // 2nd attempt should do nothing
-                    Assert.True(trimResult.Span.SequenceEqual(trimResult.Trim().Span));
-                    Assert.True(trimStartResult.Span.SequenceEqual(trimStartResult.TrimStart().Span));
-                    Assert.True(trimEndResult.Span.SequenceEqual(trimEndResult.TrimEnd().Span));
-                }
-
-                // ReadOnlyMemory
-                {
-                    ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(a);
-                    ReadOnlyMemory<char> trimResult = rom.Trim();
-                    ReadOnlyMemory<char> trimStartResult = rom.TrimStart();
-                    ReadOnlyMemory<char> trimEndResult = rom.TrimEnd();
-                    Assert.True(rom.Slice(1, length - 2).Span.SequenceEqual(trimResult.Span));
-                    Assert.True(rom.Slice(1).Span.SequenceEqual(trimStartResult.Span));
-                    Assert.True(rom.Slice(0, length - 1).Span.SequenceEqual(trimEndResult.Span));
-
-                    // 2nd attempt should do nothing
-                    Assert.True(trimResult.Span.SequenceEqual(trimResult.Trim().Span));
-                    Assert.True(trimStartResult.Span.SequenceEqual(trimStartResult.TrimStart().Span));
-                    Assert.True(trimEndResult.Span.SequenceEqual(trimEndResult.TrimEnd().Span));
-                }
-            }
-        }
-
-        [Fact]
-        public static void MakeSureNoTrimChecksGoOutOfRange_Memory()
-        {
-            for (int length = 3; length < 64; length++)
-            {
-                char[] first = new char[length];
-                first[0] = ' ';
-                first[length - 1] = ' ';
-                string s1 = new string(first, 1, length - 2);
-
-                ReadOnlySpan<char> ros = s1.AsSpan();
-                Assert.True(ros.SequenceEqual(ros.Trim()));
-                Assert.True(ros.SequenceEqual(ros.TrimStart()));
-                Assert.True(ros.SequenceEqual(ros.TrimEnd()));
-
-                Span<char> span = new Span<char>(s1.ToCharArray());
-                Assert.True(span.SequenceEqual(span.Trim()));
-                Assert.True(span.SequenceEqual(span.TrimStart()));
-                Assert.True(span.SequenceEqual(span.TrimEnd()));
-
-                Memory<char> mem = new Memory<char>(s1.ToCharArray());
-                Assert.True(mem.Span.SequenceEqual(mem.Trim().Span));
-                Assert.True(mem.Span.SequenceEqual(mem.TrimStart().Span));
-                Assert.True(mem.Span.SequenceEqual(mem.TrimEnd().Span));
-
-                ReadOnlyMemory<char> rom = new ReadOnlyMemory<char>(s1.ToCharArray());
-                Assert.True(rom.Span.SequenceEqual(rom.Trim().Span));
-                Assert.True(rom.Span.SequenceEqual(rom.TrimStart().Span));
-                Assert.True(rom.Span.SequenceEqual(rom.TrimEnd().Span));
-            }
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Text/ASCIIUtilityTests.cs b/src/libraries/System.Runtime/tests/System/Text/ASCIIUtilityTests.cs
new file mode 100644 (file)
index 0000000..d224888
--- /dev/null
@@ -0,0 +1,460 @@
+// 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.Numerics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using Xunit;
+
+namespace System.Text.Tests
+{
+    // Since many of the methods we'll be testing are internal, we'll need to invoke
+    // them via reflection.
+    public static unsafe class AsciiUtilityTests
+    {
+        private const int SizeOfVector128 = 128 / 8;
+
+        // The delegate definitions and members below provide us access to CoreLib's internals.
+        // We use UIntPtr instead of nuint everywhere here since we don't know what our target arch is.
+
+        private delegate UIntPtr FnGetIndexOfFirstNonAsciiByte(byte* pBuffer, UIntPtr bufferLength);
+        private static readonly UnsafeLazyDelegate<FnGetIndexOfFirstNonAsciiByte> _fnGetIndexOfFirstNonAsciiByte = new UnsafeLazyDelegate<FnGetIndexOfFirstNonAsciiByte>("GetIndexOfFirstNonAsciiByte");
+
+        private delegate UIntPtr FnGetIndexOfFirstNonAsciiChar(char* pBuffer, UIntPtr bufferLength);
+        private static readonly UnsafeLazyDelegate<FnGetIndexOfFirstNonAsciiChar> _fnGetIndexOfFirstNonAsciiChar = new UnsafeLazyDelegate<FnGetIndexOfFirstNonAsciiChar>("GetIndexOfFirstNonAsciiChar");
+
+        private delegate UIntPtr FnNarrowUtf16ToAscii(char* pUtf16Buffer, byte* pAsciiBuffer, UIntPtr elementCount);
+        private static readonly UnsafeLazyDelegate<FnNarrowUtf16ToAscii> _fnNarrowUtf16ToAscii = new UnsafeLazyDelegate<FnNarrowUtf16ToAscii>("NarrowUtf16ToAscii");
+
+        private delegate UIntPtr FnWidenAsciiToUtf16(byte* pAsciiBuffer, char* pUtf16Buffer, UIntPtr elementCount);
+        private static readonly UnsafeLazyDelegate<FnWidenAsciiToUtf16> _fnWidenAsciiToUtf16 = new UnsafeLazyDelegate<FnWidenAsciiToUtf16>("WidenAsciiToUtf16");
+
+        [Fact]
+        public static void GetIndexOfFirstNonAsciiByte_EmptyInput_NullReference()
+        {
+            Assert.Equal(UIntPtr.Zero, _fnGetIndexOfFirstNonAsciiByte.Delegate(null, UIntPtr.Zero));
+        }
+
+        [Fact]
+        public static void GetIndexOfFirstNonAsciiByte_EmptyInput_NonNullReference()
+        {
+            byte b = default;
+            Assert.Equal(UIntPtr.Zero, _fnGetIndexOfFirstNonAsciiByte.Delegate(&b, UIntPtr.Zero));
+        }
+
+        [Fact]
+        public static void GetIndexOfFirstNonAsciiByte_Vector128InnerLoop()
+        {
+            // The purpose of this test is to make sure we're identifying the correct
+            // vector (of the two that we're reading simultaneously) when performing
+            // the final ASCII drain at the end of the method once we've broken out
+            // of the inner loop.
+
+            using (BoundedMemory<byte> mem = BoundedMemory.Allocate<byte>(1024))
+            {
+                Span<byte> bytes = mem.Span;
+
+                for (int i = 0; i < bytes.Length; i++)
+                {
+                    bytes[i] &= 0x7F; // make sure each byte (of the pre-populated random data) is ASCII
+                }
+
+                // Two vectors have offsets 0 .. 31. We'll go backward to avoid having to
+                // re-clear the vector every time.
+
+                for (int i = 2 * SizeOfVector128 - 1; i >= 0; i--)
+                {
+                    bytes[100 + i * 13] = 0x80; // 13 is relatively prime to 32, so it ensures all possible positions are hit
+                    Assert.Equal(100 + i * 13, CallGetIndexOfFirstNonAsciiByte(bytes));
+                }
+            }
+        }
+
+        [Fact]
+        public static void GetIndexOfFirstNonAsciiByte_Boundaries()
+        {
+            // The purpose of this test is to make sure we're hitting all of the vectorized
+            // and draining logic correctly both in the SSE2 and in the non-SSE2 enlightened
+            // code paths. We shouldn't be reading beyond the boundaries we were given.
+
+            // The 5 * Vector test should make sure that we're exercising all possible
+            // code paths across both implementations.
+            using (BoundedMemory<byte> mem = BoundedMemory.Allocate<byte>(5 * Vector<byte>.Count))
+            {
+                Span<byte> bytes = mem.Span;
+
+                // First, try it with all-ASCII buffers.
+
+                for (int i = 0; i < bytes.Length; i++)
+                {
+                    bytes[i] &= 0x7F; // make sure each byte (of the pre-populated random data) is ASCII
+                }
+
+                for (int i = bytes.Length; i >= 0; i--)
+                {
+                    Assert.Equal(i, CallGetIndexOfFirstNonAsciiByte(bytes.Slice(0, i)));
+                }
+
+                // Then, try it with non-ASCII bytes.
+
+                for (int i = bytes.Length; i >= 1; i--)
+                {
+                    bytes[i - 1] = 0x80; // set non-ASCII
+                    Assert.Equal(i - 1, CallGetIndexOfFirstNonAsciiByte(bytes.Slice(0, i)));
+                }
+            }
+        }
+
+        [Fact]
+        public static void GetIndexOfFirstNonAsciiChar_EmptyInput_NullReference()
+        {
+            Assert.Equal(UIntPtr.Zero, _fnGetIndexOfFirstNonAsciiChar.Delegate(null, UIntPtr.Zero));
+        }
+
+        [Fact]
+        public static void GetIndexOfFirstNonAsciiChar_EmptyInput_NonNullReference()
+        {
+            char c = default;
+            Assert.Equal(UIntPtr.Zero, _fnGetIndexOfFirstNonAsciiChar.Delegate(&c, UIntPtr.Zero));
+        }
+
+        [Fact]
+        public static void GetIndexOfFirstNonAsciiChar_Vector128InnerLoop()
+        {
+            // The purpose of this test is to make sure we're identifying the correct
+            // vector (of the two that we're reading simultaneously) when performing
+            // the final ASCII drain at the end of the method once we've broken out
+            // of the inner loop.
+            //
+            // Use U+0123 instead of U+0080 for this test because if our implementation
+            // uses pminuw / pmovmskb incorrectly, U+0123 will incorrectly show up as ASCII,
+            // causing our test to produce a false negative.
+
+            using (BoundedMemory<char> mem = BoundedMemory.Allocate<char>(1024))
+            {
+                Span<char> chars = mem.Span;
+
+                for (int i = 0; i < chars.Length; i++)
+                {
+                    chars[i] &= '\u007F'; // make sure each char (of the pre-populated random data) is ASCII
+                }
+
+                // Two vectors have offsets 0 .. 31. We'll go backward to avoid having to
+                // re-clear the vector every time.
+
+                for (int i = 2 * SizeOfVector128 - 1; i >= 0; i--)
+                {
+                    chars[100 + i * 13] = '\u0123'; // 13 is relatively prime to 32, so it ensures all possible positions are hit
+                    Assert.Equal(100 + i * 13, CallGetIndexOfFirstNonAsciiChar(chars));
+                }
+            }
+        }
+
+        [Fact]
+        public static void GetIndexOfFirstNonAsciiChar_Boundaries()
+        {
+            // The purpose of this test is to make sure we're hitting all of the vectorized
+            // and draining logic correctly both in the SSE2 and in the non-SSE2 enlightened
+            // code paths. We shouldn't be reading beyond the boundaries we were given.
+            //
+            // The 5 * Vector test should make sure that we're exercising all possible
+            // code paths across both implementations. The sizeof(char) is because we're
+            // specifying element count, but underlying implementation reintepret casts to bytes.
+            //
+            // Use U+0123 instead of U+0080 for this test because if our implementation
+            // uses pminuw / pmovmskb incorrectly, U+0123 will incorrectly show up as ASCII,
+            // causing our test to produce a false negative.
+
+            using (BoundedMemory<char> mem = BoundedMemory.Allocate<char>(5 * Vector<byte>.Count / sizeof(char)))
+            {
+                Span<char> chars = mem.Span;
+
+                for (int i = 0; i < chars.Length; i++)
+                {
+                    chars[i] &= '\u007F'; // make sure each char (of the pre-populated random data) is ASCII
+                }
+
+                for (int i = chars.Length; i >= 0; i--)
+                {
+                    Assert.Equal(i, CallGetIndexOfFirstNonAsciiChar(chars.Slice(0, i)));
+                }
+
+                // Then, try it with non-ASCII bytes.
+
+                for (int i = chars.Length; i >= 1; i--)
+                {
+                    chars[i - 1] = '\u0123'; // set non-ASCII
+                    Assert.Equal(i - 1, CallGetIndexOfFirstNonAsciiChar(chars.Slice(0, i)));
+                }
+            }
+        }
+
+        [Fact]
+        public static void WidenAsciiToUtf16_EmptyInput_NullReferences()
+        {
+            Assert.Equal(UIntPtr.Zero, _fnWidenAsciiToUtf16.Delegate(null, null, UIntPtr.Zero));
+        }
+
+        [Fact]
+        public static void WidenAsciiToUtf16_EmptyInput_NonNullReference()
+        {
+            byte b = default;
+            char c = default;
+            Assert.Equal(UIntPtr.Zero, _fnWidenAsciiToUtf16.Delegate(&b, &c, UIntPtr.Zero));
+        }
+
+        [Fact]
+        public static void WidenAsciiToUtf16_AllAsciiInput()
+        {
+            using BoundedMemory<byte> asciiMem = BoundedMemory.Allocate<byte>(128);
+            using BoundedMemory<char> utf16Mem = BoundedMemory.Allocate<char>(128);
+
+            // Fill source with 00 .. 7F, then trap future writes.
+
+            Span<byte> asciiSpan = asciiMem.Span;
+            for (int i = 0; i < asciiSpan.Length; i++)
+            {
+                asciiSpan[i] = (byte)i;
+            }
+            asciiMem.MakeReadonly();
+
+            // We'll write to the UTF-16 span.
+            // We test with a variety of span lengths to test alignment and fallthrough code paths.
+
+            Span<char> utf16Span = utf16Mem.Span;
+
+            for (int i = 0; i < asciiSpan.Length; i++)
+            {
+                utf16Span.Clear(); // remove any data from previous iteration
+
+                // First, validate that the workhorse saw the incoming data as all-ASCII.
+
+                Assert.Equal(128 - i, CallWidenAsciiToUtf16(asciiSpan.Slice(i), utf16Span.Slice(i)));
+
+                // Then, validate that the data was transcoded properly.
+
+                for (int j = i; j < 128; j++)
+                {
+                    Assert.Equal((ushort)asciiSpan[i], (ushort)utf16Span[i]);
+                }
+            }
+        }
+
+        [Fact]
+        public static void WidenAsciiToUtf16_SomeNonAsciiInput()
+        {
+            using BoundedMemory<byte> asciiMem = BoundedMemory.Allocate<byte>(128);
+            using BoundedMemory<char> utf16Mem = BoundedMemory.Allocate<char>(128);
+
+            // Fill source with 00 .. 7F, then trap future writes.
+
+            Span<byte> asciiSpan = asciiMem.Span;
+            for (int i = 0; i < asciiSpan.Length; i++)
+            {
+                asciiSpan[i] = (byte)i;
+            }
+
+            // We'll write to the UTF-16 span.
+
+            Span<char> utf16Span = utf16Mem.Span;
+
+            for (int i = asciiSpan.Length - 1; i >= 0; i--)
+            {
+                RandomNumberGenerator.Fill(MemoryMarshal.Cast<char, byte>(utf16Span)); // fill with garbage
+
+                // First, keep track of the garbage we wrote to the destination.
+                // We want to ensure it wasn't overwritten.
+
+                char[] expectedTrailingData = utf16Span.Slice(i).ToArray();
+
+                // Then, set the desired byte as non-ASCII, then check that the workhorse
+                // correctly saw the data as non-ASCII.
+
+                asciiSpan[i] |= (byte)0x80;
+                Assert.Equal(i, CallWidenAsciiToUtf16(asciiSpan, utf16Span));
+
+                // Next, validate that the ASCII data was transcoded properly.
+
+                for (int j = 0; j < i; j++)
+                {
+                    Assert.Equal((ushort)asciiSpan[j], (ushort)utf16Span[j]);
+                }
+
+                // Finally, validate that the trailing data wasn't overwritten with non-ASCII data.
+
+                Assert.Equal(expectedTrailingData, utf16Span.Slice(i).ToArray());
+            }
+        }
+
+        [Fact]
+        public static unsafe void NarrowUtf16ToAscii_EmptyInput_NullReferences()
+        {
+            Assert.Equal(UIntPtr.Zero, _fnNarrowUtf16ToAscii.Delegate(null, null, UIntPtr.Zero));
+        }
+
+        [Fact]
+        public static void NarrowUtf16ToAscii_EmptyInput_NonNullReference()
+        {
+            char c = default;
+            byte b = default;
+            Assert.Equal(UIntPtr.Zero, _fnNarrowUtf16ToAscii.Delegate(&c, &b, UIntPtr.Zero));
+        }
+
+        [Fact]
+        public static void NarrowUtf16ToAscii_AllAsciiInput()
+        {
+            using BoundedMemory<char> utf16Mem = BoundedMemory.Allocate<char>(128);
+            using BoundedMemory<byte> asciiMem = BoundedMemory.Allocate<byte>(128);
+
+            // Fill source with 00 .. 7F.
+
+            Span<char> utf16Span = utf16Mem.Span;
+            for (int i = 0; i < utf16Span.Length; i++)
+            {
+                utf16Span[i] = (char)i;
+            }
+            utf16Mem.MakeReadonly();
+
+            // We'll write to the ASCII span.
+            // We test with a variety of span lengths to test alignment and fallthrough code paths.
+
+            Span<byte> asciiSpan = asciiMem.Span;
+
+            for (int i = 0; i < utf16Span.Length; i++)
+            {
+                asciiSpan.Clear(); // remove any data from previous iteration
+
+                // First, validate that the workhorse saw the incoming data as all-ASCII.
+
+                Assert.Equal(128 - i, CallNarrowUtf16ToAscii(utf16Span.Slice(i), asciiSpan.Slice(i)));
+
+                // Then, validate that the data was transcoded properly.
+
+                for (int j = i; j < 128; j++)
+                {
+                    Assert.Equal((ushort)utf16Span[i], (ushort)asciiSpan[i]);
+                }
+            }
+        }
+
+        [Fact]
+        public static void NarrowUtf16ToAscii_SomeNonAsciiInput()
+        {
+            using BoundedMemory<char> utf16Mem = BoundedMemory.Allocate<char>(128);
+            using BoundedMemory<byte> asciiMem = BoundedMemory.Allocate<byte>(128);
+
+            // Fill source with 00 .. 7F.
+
+            Span<char> utf16Span = utf16Mem.Span;
+            for (int i = 0; i < utf16Span.Length; i++)
+            {
+                utf16Span[i] = (char)i;
+            }
+
+            // We'll write to the ASCII span.
+
+            Span<byte> asciiSpan = asciiMem.Span;
+
+            for (int i = utf16Span.Length - 1; i >= 0; i--)
+            {
+                RandomNumberGenerator.Fill(asciiSpan); // fill with garbage
+
+                // First, keep track of the garbage we wrote to the destination.
+                // We want to ensure it wasn't overwritten.
+
+                byte[] expectedTrailingData = asciiSpan.Slice(i).ToArray();
+
+                // Then, set the desired byte as non-ASCII, then check that the workhorse
+                // correctly saw the data as non-ASCII.
+
+                utf16Span[i] = '\u0123'; // use U+0123 instead of U+0080 since it catches inappropriate pmovmskb usage
+                Assert.Equal(i, CallNarrowUtf16ToAscii(utf16Span, asciiSpan));
+
+                // Next, validate that the ASCII data was transcoded properly.
+
+                for (int j = 0; j < i; j++)
+                {
+                    Assert.Equal((ushort)utf16Span[j], (ushort)asciiSpan[j]);
+                }
+
+                // Finally, validate that the trailing data wasn't overwritten with non-ASCII data.
+
+                Assert.Equal(expectedTrailingData, asciiSpan.Slice(i).ToArray());
+            }
+        }
+
+        private static int CallGetIndexOfFirstNonAsciiByte(ReadOnlySpan<byte> buffer)
+        {
+            fixed (byte* pBuffer = &MemoryMarshal.GetReference(buffer))
+            {
+                // Conversions between UIntPtr <-> int are not checked by default.
+                return checked((int)_fnGetIndexOfFirstNonAsciiByte.Delegate(pBuffer, (UIntPtr)buffer.Length));
+            }
+        }
+
+        private static int CallGetIndexOfFirstNonAsciiChar(ReadOnlySpan<char> buffer)
+        {
+            fixed (char* pBuffer = &MemoryMarshal.GetReference(buffer))
+            {
+                // Conversions between UIntPtr <-> int are not checked by default.
+                return checked((int)_fnGetIndexOfFirstNonAsciiChar.Delegate(pBuffer, (UIntPtr)buffer.Length));
+            }
+        }
+
+        private static int CallNarrowUtf16ToAscii(ReadOnlySpan<char> utf16, Span<byte> ascii)
+        {
+            Assert.Equal(utf16.Length, ascii.Length);
+
+            fixed (char* pUtf16 = &MemoryMarshal.GetReference(utf16))
+            fixed (byte* pAscii = &MemoryMarshal.GetReference(ascii))
+            {
+                // Conversions between UIntPtr <-> int are not checked by default.
+                return checked((int)_fnNarrowUtf16ToAscii.Delegate(pUtf16, pAscii, (UIntPtr)utf16.Length));
+            }
+        }
+
+        private static int CallWidenAsciiToUtf16(ReadOnlySpan<byte> ascii, Span<char> utf16)
+        {
+            Assert.Equal(ascii.Length, utf16.Length);
+
+            fixed (byte* pAscii = &MemoryMarshal.GetReference(ascii))
+            fixed (char* pUtf16 = &MemoryMarshal.GetReference(utf16))
+            {
+                // Conversions between UIntPtr <-> int are not checked by default.
+                return checked((int)_fnWidenAsciiToUtf16.Delegate(pAscii, pUtf16, (UIntPtr)ascii.Length));
+            }
+        }
+
+        private static Type GetAsciiUtilityType()
+        {
+            return typeof(object).Assembly.GetType("System.Text.ASCIIUtility");
+        }
+
+        private sealed class UnsafeLazyDelegate<TDelegate> where TDelegate : class
+        {
+            private readonly Lazy<TDelegate> _lazyDelegate;
+
+            public UnsafeLazyDelegate(string methodName)
+            {
+                _lazyDelegate = new Lazy<TDelegate>(() =>
+                {
+                    Assert.True(typeof(TDelegate).IsSubclassOf(typeof(MulticastDelegate)));
+
+                    // Get the MethodInfo for the target method
+
+                    MethodInfo methodInfo = GetAsciiUtilityType().GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+                    Assert.NotNull(methodInfo);
+
+                    // Construct the TDelegate pointing to this method
+
+                    return (TDelegate)Activator.CreateInstance(typeof(TDelegate), new object[] { null, methodInfo.MethodHandle.GetFunctionPointer() });
+                });
+            }
+
+            public TDelegate Delegate => _lazyDelegate.Value;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Text/ASCIIUtilityTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/ASCIIUtilityTests.netcoreapp.cs
deleted file mode 100644 (file)
index 638c131..0000000
+++ /dev/null
@@ -1,460 +0,0 @@
-// 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.Numerics;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Security.Cryptography;
-using Xunit;
-
-namespace System.Text.Tests
-{
-    // 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
-    {
-        private const int SizeOfVector128 = 128 / 8;
-
-        // The delegate definitions and members below provide us access to CoreLib's internals.
-        // We use UIntPtr instead of nuint everywhere here since we don't know what our target arch is.
-
-        private delegate UIntPtr FnGetIndexOfFirstNonAsciiByte(byte* pBuffer, UIntPtr bufferLength);
-        private static readonly UnsafeLazyDelegate<FnGetIndexOfFirstNonAsciiByte> _fnGetIndexOfFirstNonAsciiByte = new UnsafeLazyDelegate<FnGetIndexOfFirstNonAsciiByte>("GetIndexOfFirstNonAsciiByte");
-
-        private delegate UIntPtr FnGetIndexOfFirstNonAsciiChar(char* pBuffer, UIntPtr bufferLength);
-        private static readonly UnsafeLazyDelegate<FnGetIndexOfFirstNonAsciiChar> _fnGetIndexOfFirstNonAsciiChar = new UnsafeLazyDelegate<FnGetIndexOfFirstNonAsciiChar>("GetIndexOfFirstNonAsciiChar");
-
-        private delegate UIntPtr FnNarrowUtf16ToAscii(char* pUtf16Buffer, byte* pAsciiBuffer, UIntPtr elementCount);
-        private static readonly UnsafeLazyDelegate<FnNarrowUtf16ToAscii> _fnNarrowUtf16ToAscii = new UnsafeLazyDelegate<FnNarrowUtf16ToAscii>("NarrowUtf16ToAscii");
-
-        private delegate UIntPtr FnWidenAsciiToUtf16(byte* pAsciiBuffer, char* pUtf16Buffer, UIntPtr elementCount);
-        private static readonly UnsafeLazyDelegate<FnWidenAsciiToUtf16> _fnWidenAsciiToUtf16 = new UnsafeLazyDelegate<FnWidenAsciiToUtf16>("WidenAsciiToUtf16");
-
-        [Fact]
-        public static void GetIndexOfFirstNonAsciiByte_EmptyInput_NullReference()
-        {
-            Assert.Equal(UIntPtr.Zero, _fnGetIndexOfFirstNonAsciiByte.Delegate(null, UIntPtr.Zero));
-        }
-
-        [Fact]
-        public static void GetIndexOfFirstNonAsciiByte_EmptyInput_NonNullReference()
-        {
-            byte b = default;
-            Assert.Equal(UIntPtr.Zero, _fnGetIndexOfFirstNonAsciiByte.Delegate(&b, UIntPtr.Zero));
-        }
-
-        [Fact]
-        public static void GetIndexOfFirstNonAsciiByte_Vector128InnerLoop()
-        {
-            // The purpose of this test is to make sure we're identifying the correct
-            // vector (of the two that we're reading simultaneously) when performing
-            // the final ASCII drain at the end of the method once we've broken out
-            // of the inner loop.
-
-            using (BoundedMemory<byte> mem = BoundedMemory.Allocate<byte>(1024))
-            {
-                Span<byte> bytes = mem.Span;
-
-                for (int i = 0; i < bytes.Length; i++)
-                {
-                    bytes[i] &= 0x7F; // make sure each byte (of the pre-populated random data) is ASCII
-                }
-
-                // Two vectors have offsets 0 .. 31. We'll go backward to avoid having to
-                // re-clear the vector every time.
-
-                for (int i = 2 * SizeOfVector128 - 1; i >= 0; i--)
-                {
-                    bytes[100 + i * 13] = 0x80; // 13 is relatively prime to 32, so it ensures all possible positions are hit
-                    Assert.Equal(100 + i * 13, CallGetIndexOfFirstNonAsciiByte(bytes));
-                }
-            }
-        }
-
-        [Fact]
-        public static void GetIndexOfFirstNonAsciiByte_Boundaries()
-        {
-            // The purpose of this test is to make sure we're hitting all of the vectorized
-            // and draining logic correctly both in the SSE2 and in the non-SSE2 enlightened
-            // code paths. We shouldn't be reading beyond the boundaries we were given.
-
-            // The 5 * Vector test should make sure that we're exercising all possible
-            // code paths across both implementations.
-            using (BoundedMemory<byte> mem = BoundedMemory.Allocate<byte>(5 * Vector<byte>.Count))
-            {
-                Span<byte> bytes = mem.Span;
-
-                // First, try it with all-ASCII buffers.
-
-                for (int i = 0; i < bytes.Length; i++)
-                {
-                    bytes[i] &= 0x7F; // make sure each byte (of the pre-populated random data) is ASCII
-                }
-
-                for (int i = bytes.Length; i >= 0; i--)
-                {
-                    Assert.Equal(i, CallGetIndexOfFirstNonAsciiByte(bytes.Slice(0, i)));
-                }
-
-                // Then, try it with non-ASCII bytes.
-
-                for (int i = bytes.Length; i >= 1; i--)
-                {
-                    bytes[i - 1] = 0x80; // set non-ASCII
-                    Assert.Equal(i - 1, CallGetIndexOfFirstNonAsciiByte(bytes.Slice(0, i)));
-                }
-            }
-        }
-
-        [Fact]
-        public static void GetIndexOfFirstNonAsciiChar_EmptyInput_NullReference()
-        {
-            Assert.Equal(UIntPtr.Zero, _fnGetIndexOfFirstNonAsciiChar.Delegate(null, UIntPtr.Zero));
-        }
-
-        [Fact]
-        public static void GetIndexOfFirstNonAsciiChar_EmptyInput_NonNullReference()
-        {
-            char c = default;
-            Assert.Equal(UIntPtr.Zero, _fnGetIndexOfFirstNonAsciiChar.Delegate(&c, UIntPtr.Zero));
-        }
-
-        [Fact]
-        public static void GetIndexOfFirstNonAsciiChar_Vector128InnerLoop()
-        {
-            // The purpose of this test is to make sure we're identifying the correct
-            // vector (of the two that we're reading simultaneously) when performing
-            // the final ASCII drain at the end of the method once we've broken out
-            // of the inner loop.
-            //
-            // Use U+0123 instead of U+0080 for this test because if our implementation
-            // uses pminuw / pmovmskb incorrectly, U+0123 will incorrectly show up as ASCII,
-            // causing our test to produce a false negative.
-
-            using (BoundedMemory<char> mem = BoundedMemory.Allocate<char>(1024))
-            {
-                Span<char> chars = mem.Span;
-
-                for (int i = 0; i < chars.Length; i++)
-                {
-                    chars[i] &= '\u007F'; // make sure each char (of the pre-populated random data) is ASCII
-                }
-
-                // Two vectors have offsets 0 .. 31. We'll go backward to avoid having to
-                // re-clear the vector every time.
-
-                for (int i = 2 * SizeOfVector128 - 1; i >= 0; i--)
-                {
-                    chars[100 + i * 13] = '\u0123'; // 13 is relatively prime to 32, so it ensures all possible positions are hit
-                    Assert.Equal(100 + i * 13, CallGetIndexOfFirstNonAsciiChar(chars));
-                }
-            }
-        }
-
-        [Fact]
-        public static void GetIndexOfFirstNonAsciiChar_Boundaries()
-        {
-            // The purpose of this test is to make sure we're hitting all of the vectorized
-            // and draining logic correctly both in the SSE2 and in the non-SSE2 enlightened
-            // code paths. We shouldn't be reading beyond the boundaries we were given.
-            //
-            // The 5 * Vector test should make sure that we're exercising all possible
-            // code paths across both implementations. The sizeof(char) is because we're
-            // specifying element count, but underlying implementation reintepret casts to bytes.
-            //
-            // Use U+0123 instead of U+0080 for this test because if our implementation
-            // uses pminuw / pmovmskb incorrectly, U+0123 will incorrectly show up as ASCII,
-            // causing our test to produce a false negative.
-
-            using (BoundedMemory<char> mem = BoundedMemory.Allocate<char>(5 * Vector<byte>.Count / sizeof(char)))
-            {
-                Span<char> chars = mem.Span;
-
-                for (int i = 0; i < chars.Length; i++)
-                {
-                    chars[i] &= '\u007F'; // make sure each char (of the pre-populated random data) is ASCII
-                }
-
-                for (int i = chars.Length; i >= 0; i--)
-                {
-                    Assert.Equal(i, CallGetIndexOfFirstNonAsciiChar(chars.Slice(0, i)));
-                }
-
-                // Then, try it with non-ASCII bytes.
-
-                for (int i = chars.Length; i >= 1; i--)
-                {
-                    chars[i - 1] = '\u0123'; // set non-ASCII
-                    Assert.Equal(i - 1, CallGetIndexOfFirstNonAsciiChar(chars.Slice(0, i)));
-                }
-            }
-        }
-
-        [Fact]
-        public static void WidenAsciiToUtf16_EmptyInput_NullReferences()
-        {
-            Assert.Equal(UIntPtr.Zero, _fnWidenAsciiToUtf16.Delegate(null, null, UIntPtr.Zero));
-        }
-
-        [Fact]
-        public static void WidenAsciiToUtf16_EmptyInput_NonNullReference()
-        {
-            byte b = default;
-            char c = default;
-            Assert.Equal(UIntPtr.Zero, _fnWidenAsciiToUtf16.Delegate(&b, &c, UIntPtr.Zero));
-        }
-
-        [Fact]
-        public static void WidenAsciiToUtf16_AllAsciiInput()
-        {
-            using BoundedMemory<byte> asciiMem = BoundedMemory.Allocate<byte>(128);
-            using BoundedMemory<char> utf16Mem = BoundedMemory.Allocate<char>(128);
-
-            // Fill source with 00 .. 7F, then trap future writes.
-
-            Span<byte> asciiSpan = asciiMem.Span;
-            for (int i = 0; i < asciiSpan.Length; i++)
-            {
-                asciiSpan[i] = (byte)i;
-            }
-            asciiMem.MakeReadonly();
-
-            // We'll write to the UTF-16 span.
-            // We test with a variety of span lengths to test alignment and fallthrough code paths.
-
-            Span<char> utf16Span = utf16Mem.Span;
-
-            for (int i = 0; i < asciiSpan.Length; i++)
-            {
-                utf16Span.Clear(); // remove any data from previous iteration
-
-                // First, validate that the workhorse saw the incoming data as all-ASCII.
-
-                Assert.Equal(128 - i, CallWidenAsciiToUtf16(asciiSpan.Slice(i), utf16Span.Slice(i)));
-
-                // Then, validate that the data was transcoded properly.
-
-                for (int j = i; j < 128; j++)
-                {
-                    Assert.Equal((ushort)asciiSpan[i], (ushort)utf16Span[i]);
-                }
-            }
-        }
-
-        [Fact]
-        public static void WidenAsciiToUtf16_SomeNonAsciiInput()
-        {
-            using BoundedMemory<byte> asciiMem = BoundedMemory.Allocate<byte>(128);
-            using BoundedMemory<char> utf16Mem = BoundedMemory.Allocate<char>(128);
-
-            // Fill source with 00 .. 7F, then trap future writes.
-
-            Span<byte> asciiSpan = asciiMem.Span;
-            for (int i = 0; i < asciiSpan.Length; i++)
-            {
-                asciiSpan[i] = (byte)i;
-            }
-
-            // We'll write to the UTF-16 span.
-
-            Span<char> utf16Span = utf16Mem.Span;
-
-            for (int i = asciiSpan.Length - 1; i >= 0; i--)
-            {
-                RandomNumberGenerator.Fill(MemoryMarshal.Cast<char, byte>(utf16Span)); // fill with garbage
-
-                // First, keep track of the garbage we wrote to the destination.
-                // We want to ensure it wasn't overwritten.
-
-                char[] expectedTrailingData = utf16Span.Slice(i).ToArray();
-
-                // Then, set the desired byte as non-ASCII, then check that the workhorse
-                // correctly saw the data as non-ASCII.
-
-                asciiSpan[i] |= (byte)0x80;
-                Assert.Equal(i, CallWidenAsciiToUtf16(asciiSpan, utf16Span));
-
-                // Next, validate that the ASCII data was transcoded properly.
-
-                for (int j = 0; j < i; j++)
-                {
-                    Assert.Equal((ushort)asciiSpan[j], (ushort)utf16Span[j]);
-                }
-
-                // Finally, validate that the trailing data wasn't overwritten with non-ASCII data.
-
-                Assert.Equal(expectedTrailingData, utf16Span.Slice(i).ToArray());
-            }
-        }
-
-        [Fact]
-        public static unsafe void NarrowUtf16ToAscii_EmptyInput_NullReferences()
-        {
-            Assert.Equal(UIntPtr.Zero, _fnNarrowUtf16ToAscii.Delegate(null, null, UIntPtr.Zero));
-        }
-
-        [Fact]
-        public static void NarrowUtf16ToAscii_EmptyInput_NonNullReference()
-        {
-            char c = default;
-            byte b = default;
-            Assert.Equal(UIntPtr.Zero, _fnNarrowUtf16ToAscii.Delegate(&c, &b, UIntPtr.Zero));
-        }
-
-        [Fact]
-        public static void NarrowUtf16ToAscii_AllAsciiInput()
-        {
-            using BoundedMemory<char> utf16Mem = BoundedMemory.Allocate<char>(128);
-            using BoundedMemory<byte> asciiMem = BoundedMemory.Allocate<byte>(128);
-
-            // Fill source with 00 .. 7F.
-
-            Span<char> utf16Span = utf16Mem.Span;
-            for (int i = 0; i < utf16Span.Length; i++)
-            {
-                utf16Span[i] = (char)i;
-            }
-            utf16Mem.MakeReadonly();
-
-            // We'll write to the ASCII span.
-            // We test with a variety of span lengths to test alignment and fallthrough code paths.
-
-            Span<byte> asciiSpan = asciiMem.Span;
-
-            for (int i = 0; i < utf16Span.Length; i++)
-            {
-                asciiSpan.Clear(); // remove any data from previous iteration
-
-                // First, validate that the workhorse saw the incoming data as all-ASCII.
-
-                Assert.Equal(128 - i, CallNarrowUtf16ToAscii(utf16Span.Slice(i), asciiSpan.Slice(i)));
-
-                // Then, validate that the data was transcoded properly.
-
-                for (int j = i; j < 128; j++)
-                {
-                    Assert.Equal((ushort)utf16Span[i], (ushort)asciiSpan[i]);
-                }
-            }
-        }
-
-        [Fact]
-        public static void NarrowUtf16ToAscii_SomeNonAsciiInput()
-        {
-            using BoundedMemory<char> utf16Mem = BoundedMemory.Allocate<char>(128);
-            using BoundedMemory<byte> asciiMem = BoundedMemory.Allocate<byte>(128);
-
-            // Fill source with 00 .. 7F.
-
-            Span<char> utf16Span = utf16Mem.Span;
-            for (int i = 0; i < utf16Span.Length; i++)
-            {
-                utf16Span[i] = (char)i;
-            }
-
-            // We'll write to the ASCII span.
-
-            Span<byte> asciiSpan = asciiMem.Span;
-
-            for (int i = utf16Span.Length - 1; i >= 0; i--)
-            {
-                RandomNumberGenerator.Fill(asciiSpan); // fill with garbage
-
-                // First, keep track of the garbage we wrote to the destination.
-                // We want to ensure it wasn't overwritten.
-
-                byte[] expectedTrailingData = asciiSpan.Slice(i).ToArray();
-
-                // Then, set the desired byte as non-ASCII, then check that the workhorse
-                // correctly saw the data as non-ASCII.
-
-                utf16Span[i] = '\u0123'; // use U+0123 instead of U+0080 since it catches inappropriate pmovmskb usage
-                Assert.Equal(i, CallNarrowUtf16ToAscii(utf16Span, asciiSpan));
-
-                // Next, validate that the ASCII data was transcoded properly.
-
-                for (int j = 0; j < i; j++)
-                {
-                    Assert.Equal((ushort)utf16Span[j], (ushort)asciiSpan[j]);
-                }
-
-                // Finally, validate that the trailing data wasn't overwritten with non-ASCII data.
-
-                Assert.Equal(expectedTrailingData, asciiSpan.Slice(i).ToArray());
-            }
-        }
-
-        private static int CallGetIndexOfFirstNonAsciiByte(ReadOnlySpan<byte> buffer)
-        {
-            fixed (byte* pBuffer = &MemoryMarshal.GetReference(buffer))
-            {
-                // Conversions between UIntPtr <-> int are not checked by default.
-                return checked((int)_fnGetIndexOfFirstNonAsciiByte.Delegate(pBuffer, (UIntPtr)buffer.Length));
-            }
-        }
-
-        private static int CallGetIndexOfFirstNonAsciiChar(ReadOnlySpan<char> buffer)
-        {
-            fixed (char* pBuffer = &MemoryMarshal.GetReference(buffer))
-            {
-                // Conversions between UIntPtr <-> int are not checked by default.
-                return checked((int)_fnGetIndexOfFirstNonAsciiChar.Delegate(pBuffer, (UIntPtr)buffer.Length));
-            }
-        }
-
-        private static int CallNarrowUtf16ToAscii(ReadOnlySpan<char> utf16, Span<byte> ascii)
-        {
-            Assert.Equal(utf16.Length, ascii.Length);
-
-            fixed (char* pUtf16 = &MemoryMarshal.GetReference(utf16))
-            fixed (byte* pAscii = &MemoryMarshal.GetReference(ascii))
-            {
-                // Conversions between UIntPtr <-> int are not checked by default.
-                return checked((int)_fnNarrowUtf16ToAscii.Delegate(pUtf16, pAscii, (UIntPtr)utf16.Length));
-            }
-        }
-
-        private static int CallWidenAsciiToUtf16(ReadOnlySpan<byte> ascii, Span<char> utf16)
-        {
-            Assert.Equal(ascii.Length, utf16.Length);
-
-            fixed (byte* pAscii = &MemoryMarshal.GetReference(ascii))
-            fixed (char* pUtf16 = &MemoryMarshal.GetReference(utf16))
-            {
-                // Conversions between UIntPtr <-> int are not checked by default.
-                return checked((int)_fnWidenAsciiToUtf16.Delegate(pAscii, pUtf16, (UIntPtr)ascii.Length));
-            }
-        }
-
-        private static Type GetAsciiUtilityType()
-        {
-            return typeof(object).Assembly.GetType("System.Text.ASCIIUtility");
-        }
-
-        private sealed class UnsafeLazyDelegate<TDelegate> where TDelegate : class
-        {
-            private readonly Lazy<TDelegate> _lazyDelegate;
-
-            public UnsafeLazyDelegate(string methodName)
-            {
-                _lazyDelegate = new Lazy<TDelegate>(() =>
-                {
-                    Assert.True(typeof(TDelegate).IsSubclassOf(typeof(MulticastDelegate)));
-
-                    // Get the MethodInfo for the target method
-
-                    MethodInfo methodInfo = GetAsciiUtilityType().GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
-                    Assert.NotNull(methodInfo);
-
-                    // Construct the TDelegate pointing to this method
-
-                    return (TDelegate)Activator.CreateInstance(typeof(TDelegate), new object[] { null, methodInfo.MethodHandle.GetFunctionPointer() });
-                });
-            }
-
-            public TDelegate Delegate => _lazyDelegate.Value;
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Text/RuneTests.TestData.cs b/src/libraries/System.Runtime/tests/System/Text/RuneTests.TestData.cs
new file mode 100644 (file)
index 0000000..0143436
--- /dev/null
@@ -0,0 +1,550 @@
+// 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 System.Linq;
+
+namespace System.Text.Tests
+{
+    public static partial class RuneTests
+    {
+        public static IEnumerable<Rune> AllRunes()
+        {
+            for (uint i = 0; i < 0xD800; i++)
+            {
+                yield return new Rune(i);
+            }
+
+            for (uint i = 0xE000; i <= 0x10FFFF; i++)
+            {
+                yield return new Rune(i);
+            }
+        }
+
+        public static IEnumerable<object[]> GeneralTestData_BmpCodePoints_NoSurrogates()
+        {
+            yield return new object[]
+            {
+                // first BMP code point / first ASCII code point
+                new GeneralTestData
+                {
+                    ScalarValue = 0x0000,
+                    IsAscii = true,
+                    IsBmp = true,
+                    Plane = 0,
+                    Utf16Sequence = new char[] { '\u0000' },
+                    Utf8Sequence = new byte[] { 0x00 }
+                }
+            };
+
+            yield return new object[]
+            {
+                // last ASCII code point
+                new GeneralTestData
+                {
+                    ScalarValue = 0x007F,
+                    IsAscii = true,
+                    IsBmp = true,
+                    Plane = 0,
+                    Utf16Sequence = new char[] { '\u007F' },
+                    Utf8Sequence = new byte[] { 0x7F }
+                }
+            };
+
+            yield return new object[] {
+                // first non-ASCII code point / first UTF-8 two-code unit code point
+                new GeneralTestData
+                {
+                    ScalarValue = 0x0080,
+                    IsAscii = false,
+                    IsBmp = true,
+                    Plane = 0,
+                    Utf16Sequence = new char[] { '\u0080' },
+                    Utf8Sequence = new byte[] { 0xC2, 0x80 }
+                }
+            };
+
+            yield return new object[] {
+                // last UTF-8 two-code unit code point
+                new GeneralTestData
+                {
+                    ScalarValue = 0x07FF,
+                    IsAscii = false,
+                    IsBmp = true,
+                    Plane = 0,
+                    Utf16Sequence = new char[] { '\u07FF' },
+                    Utf8Sequence = new byte[] { 0xDF, 0xBF }
+                }
+            };
+
+            yield return new object[] {
+                // first UTF-8 three-code unit code point
+                new GeneralTestData
+                {
+                    ScalarValue = 0x0800,
+                    IsAscii = false,
+                    IsBmp = true,
+                    Plane = 0,
+                    Utf16Sequence = new char[] { '\u0800' },
+                    Utf8Sequence = new byte[] { 0xE0, 0xA0, 0x80 }
+                }
+            };
+
+            yield return new object[] {
+                // last code point before the surrogate range
+                new GeneralTestData
+                {
+                    ScalarValue = 0xD7FF,
+                    IsAscii = false,
+                    IsBmp = true,
+                    Plane = 0,
+                    Utf16Sequence = new char[] { '\uD7FF' },
+                    Utf8Sequence = new byte[] { 0xED, 0x9F, 0xBF }
+                }
+            };
+
+            yield return new object[] {
+                // first code point after the surrogate range
+                new GeneralTestData
+                {
+                    ScalarValue = 0xE000,
+                    IsAscii = false,
+                    IsBmp = true,
+                    Plane = 0,
+                    Utf16Sequence = new char[] { '\uE000' },
+                    Utf8Sequence = new byte[] { 0xEE, 0x80, 0x80 }
+                }
+            };
+
+            yield return new object[] {
+                // replacement character
+                new GeneralTestData
+                {
+                    ScalarValue = 0xFFFD,
+                    IsAscii = false,
+                    IsBmp = true,
+                    Plane = 0,
+                    Utf16Sequence = new char[] { '\uFFFD' },
+                    Utf8Sequence = new byte[] { 0xEF, 0xBF, 0xBD }
+                }
+            };
+
+            yield return new object[] {
+                // last BMP code point / last UTF-8 two-code unit code point
+                new GeneralTestData
+                {
+                    ScalarValue = 0xFFFF,
+                    IsAscii = false,
+                    IsBmp = true,
+                    Plane = 0,
+                    Utf16Sequence = new char[] { '\uFFFF' },
+                    Utf8Sequence = new byte[] { 0xEF, 0xBF, 0xBF }
+                }
+            };
+        }
+
+        public static IEnumerable<object[]> GeneralTestData_SupplementaryCodePoints_ValidOnly()
+        {
+            yield return new object[]
+            {
+                // first BMP code point / first ASCII code point
+                new GeneralTestData
+                {
+                    ScalarValue = 0x10000,
+                    IsAscii = false,
+                    IsBmp = false,
+                    Plane = 1,
+                    Utf16Sequence = new char[] { '\uD800', '\uDC00' },
+                    Utf8Sequence = new byte[] { 0xF0, 0x90, 0x80, 0x80 }
+                }
+            };
+
+            yield return new object[]
+            {
+                // last supplementary code point
+                new GeneralTestData
+                {
+                    ScalarValue = 0x10FFFF,
+                    IsAscii = false,
+                    IsBmp = false,
+                    Plane = 16,
+                    Utf16Sequence = new char[] { '\uDBFF', '\uDFFF' },
+                    Utf8Sequence = new byte[] { 0xF4, 0x8F, 0xBF, 0xBF }
+                }
+            };
+        }
+        public static IEnumerable<object[]> IsValidTestData()
+        {
+            foreach (var obj in GeneralTestData_BmpCodePoints_NoSurrogates().Concat(GeneralTestData_SupplementaryCodePoints_ValidOnly()))
+            {
+                yield return new object[] { ((GeneralTestData)obj[0]).ScalarValue /* value */, true /* isValid */ };
+            }
+
+            foreach (var obj in BmpCodePoints_SurrogatesOnly().Concat(SupplementaryCodePoints_InvalidOnly()))
+            {
+                yield return new object[] { Convert.ToInt32(obj[0], CultureInfo.InvariantCulture) /* value */, false /* isValid */ };
+            }
+        }
+
+        public static IEnumerable<object[]> BmpCodePoints_SurrogatesOnly()
+        {
+            yield return new object[] { '\uD800' }; // first high surrogate code point
+            yield return new object[] { '\uDBFF' }; // last high surrogate code point
+            yield return new object[] { '\uDC00' }; // first low surrogate code point
+            yield return new object[] { '\uDFFF' }; // last low surrogate code point
+        }
+
+        public static IEnumerable<object[]> SupplementaryCodePoints_InvalidOnly()
+        {
+            yield return new object[] { (int)-1 }; // negative code points are disallowed
+            yield return new object[] { (int)0x110000 }; // just past the end of the allowed code point range
+            yield return new object[] { int.MaxValue }; // too large
+        }
+
+        public static IEnumerable<object[]> SurrogatePairTestData_InvalidOnly()
+        {
+            yield return new object[] { '\ud800', '\ud800' }; // two high surrogates
+            yield return new object[] { '\udfff', '\udfff' }; // two low surrogates
+            yield return new object[] { '\ude00', '\udb00' }; // low surrogate before high surrogate
+            yield return new object[] { '\ud900', '\u1234' }; // high surrogate followed by non-surrogate
+            yield return new object[] { '\ud900', '\ue000' }; // high surrogate followed by value just beyond low surrogate range
+            yield return new object[] { '\u1234', '\ude00' }; // low surrogate preceded by non-surrogate
+            yield return new object[] { '\udc00', '\ude00' }; // low surrogate preceded by value just beyond high surrogate range
+        }
+
+        public static IEnumerable<object[]> SurrogatePairTestData_ValidOnly()
+        {
+            yield return new object[] { '\ud800', '\udc00', 0x00010000 }; // lower bound for high & low surrogate
+            yield return new object[] { '\udbff', '\udfff', 0x0010FFFF }; // upper bound for high & low surrogate
+            yield return new object[] { '\ud83c', '\udfa8', 0x0001F3A8 }; // U+1F3A8 ARTIST PALETTE
+        }
+
+        public class GeneralTestData
+        {
+            public int ScalarValue;
+            public bool IsAscii;
+            public bool IsBmp;
+            public int Plane;
+            public char[] Utf16Sequence;
+            public byte[] Utf8Sequence;
+        }
+
+        public static IEnumerable<object[]> UnicodeInfoTestData_Latin1AndSelectOthers()
+        {
+            // ASCII
+
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x00), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x01), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x02), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x03), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x04), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x05), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x06), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x07), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x08), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x09), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0A), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0B), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0C), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0D), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0E), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x10), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x11), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x12), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x13), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x14), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x15), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x16), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x17), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x18), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x19), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1A), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1B), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1C), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1D), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1E), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x20), UnicodeCategory = UnicodeCategory.SpaceSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x21), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x22), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x23), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x24), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x25), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x26), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x27), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x28), UnicodeCategory = UnicodeCategory.OpenPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x29), UnicodeCategory = UnicodeCategory.ClosePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2A), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2B), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2C), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2D), UnicodeCategory = UnicodeCategory.DashPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2E), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2F), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x30), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 0, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x31), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 1, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x32), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 2, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x33), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 3, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x34), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 4, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x35), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 5, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x36), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 6, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x37), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 7, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x38), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 8, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x39), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 9, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3A), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3B), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3C), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3D), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3E), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3F), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x40), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x41), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x42), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x43), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x44), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x45), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x46), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x47), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x48), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x49), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4A), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4B), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4C), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4D), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4E), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4F), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x50), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x51), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x52), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x53), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x54), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x55), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x56), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x57), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x58), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x59), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5A), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5B), UnicodeCategory = UnicodeCategory.OpenPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5C), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5D), UnicodeCategory = UnicodeCategory.ClosePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5E), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5F), UnicodeCategory = UnicodeCategory.ConnectorPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x60), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x61), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x62), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x63), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x64), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x65), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x66), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x67), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x68), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x69), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6A), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6B), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6C), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6D), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6E), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6F), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x70), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x71), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x72), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x73), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x74), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x75), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x76), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x77), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x78), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x79), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7A), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7B), UnicodeCategory = UnicodeCategory.OpenPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7C), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7D), UnicodeCategory = UnicodeCategory.ClosePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7E), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+
+            // Remainder of Latin-1
+
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x80), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x81), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x82), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x83), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x84), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x85), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x86), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x87), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x88), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x89), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8A), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8B), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8C), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8D), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8E), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x90), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x91), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x92), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x93), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x94), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x95), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x96), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x97), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x98), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x99), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9A), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9B), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9C), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9D), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9E), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA0), UnicodeCategory = UnicodeCategory.SpaceSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA1), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA2), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA3), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA4), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA5), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA6), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA7), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA8), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA9), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAA), UnicodeCategory = UnicodeCategory.OtherLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAB), UnicodeCategory = UnicodeCategory.InitialQuotePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAC), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAD), UnicodeCategory = UnicodeCategory.Format, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAE), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAF), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB0), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB1), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB2), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 2, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB3), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 3, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB4), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB5), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB6), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB7), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB8), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB9), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBA), UnicodeCategory = UnicodeCategory.OtherLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBB), UnicodeCategory = UnicodeCategory.FinalQuotePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBC), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 0.25, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBD), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 0.5, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBE), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 0.75, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBF), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC0), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC1), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC2), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC3), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC4), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC5), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC6), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC7), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC8), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC9), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCA), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCB), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCC), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCD), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCE), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCF), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD0), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD1), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD2), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD3), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD4), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD5), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD6), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD7), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD8), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD9), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDA), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDB), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDC), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDD), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDE), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDF), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE0), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE1), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE2), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE3), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE4), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE5), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE6), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE7), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE8), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE9), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEA), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEB), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEC), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xED), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEE), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEF), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF0), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF1), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF2), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF3), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF4), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF5), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF6), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF7), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF8), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF9), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFA), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFB), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFC), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFD), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFE), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFF), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+
+            // Select others
+
+            // U+2000 EN QUAD
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2000), UnicodeCategory = UnicodeCategory.SpaceSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+
+            // U+2028 LINE SEPARATOR
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2028), UnicodeCategory = UnicodeCategory.LineSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+
+            // U+2029 PARAGRAPH SEPARATOR
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2029), UnicodeCategory = UnicodeCategory.ParagraphSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+
+            // U+202F NARROW NO-BREAK SPACE
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x202F), UnicodeCategory = UnicodeCategory.SpaceSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
+
+            // U+2154 VULGAR FRACTION TWO THIRDS
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2154), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 2.0 / 3, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+
+            // U+FFFD REPLACEMENT CHARACTER
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFFFD), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
+
+            // U+10000 LINEAR B SYLLABLE B008 A
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x10000), UnicodeCategory = UnicodeCategory.OtherLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+
+            // U+10110 AEGEAN NUMBER TEN
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x10110), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 10, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+
+            // U+10177 GREEK TWO THIRDS SIGN
+            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x10177), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 2.0 / 3, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
+
+        }
+
+        public class UnicodeInfoTestData
+        {
+            // named such so that it appears at the beginning of the console output for any failing unit test
+            public string __DebugDisplay => $"U+{ScalarValue.Value:X4}";
+
+            public Rune ScalarValue;
+            public UnicodeCategory UnicodeCategory;
+            public double NumericValue;
+            public bool IsControl;
+            public bool IsDigit;
+            public bool IsLetter;
+            public bool IsLetterOrDigit;
+            public bool IsLower;
+            public bool IsNumber;
+            public bool IsPunctuation;
+            public bool IsSeparator;
+            public bool IsSymbol;
+            public bool IsUpper;
+            public bool IsWhiteSpace;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Text/RuneTests.TestData.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/RuneTests.TestData.netcoreapp.cs
deleted file mode 100644 (file)
index 0143436..0000000
+++ /dev/null
@@ -1,550 +0,0 @@
-// 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 System.Linq;
-
-namespace System.Text.Tests
-{
-    public static partial class RuneTests
-    {
-        public static IEnumerable<Rune> AllRunes()
-        {
-            for (uint i = 0; i < 0xD800; i++)
-            {
-                yield return new Rune(i);
-            }
-
-            for (uint i = 0xE000; i <= 0x10FFFF; i++)
-            {
-                yield return new Rune(i);
-            }
-        }
-
-        public static IEnumerable<object[]> GeneralTestData_BmpCodePoints_NoSurrogates()
-        {
-            yield return new object[]
-            {
-                // first BMP code point / first ASCII code point
-                new GeneralTestData
-                {
-                    ScalarValue = 0x0000,
-                    IsAscii = true,
-                    IsBmp = true,
-                    Plane = 0,
-                    Utf16Sequence = new char[] { '\u0000' },
-                    Utf8Sequence = new byte[] { 0x00 }
-                }
-            };
-
-            yield return new object[]
-            {
-                // last ASCII code point
-                new GeneralTestData
-                {
-                    ScalarValue = 0x007F,
-                    IsAscii = true,
-                    IsBmp = true,
-                    Plane = 0,
-                    Utf16Sequence = new char[] { '\u007F' },
-                    Utf8Sequence = new byte[] { 0x7F }
-                }
-            };
-
-            yield return new object[] {
-                // first non-ASCII code point / first UTF-8 two-code unit code point
-                new GeneralTestData
-                {
-                    ScalarValue = 0x0080,
-                    IsAscii = false,
-                    IsBmp = true,
-                    Plane = 0,
-                    Utf16Sequence = new char[] { '\u0080' },
-                    Utf8Sequence = new byte[] { 0xC2, 0x80 }
-                }
-            };
-
-            yield return new object[] {
-                // last UTF-8 two-code unit code point
-                new GeneralTestData
-                {
-                    ScalarValue = 0x07FF,
-                    IsAscii = false,
-                    IsBmp = true,
-                    Plane = 0,
-                    Utf16Sequence = new char[] { '\u07FF' },
-                    Utf8Sequence = new byte[] { 0xDF, 0xBF }
-                }
-            };
-
-            yield return new object[] {
-                // first UTF-8 three-code unit code point
-                new GeneralTestData
-                {
-                    ScalarValue = 0x0800,
-                    IsAscii = false,
-                    IsBmp = true,
-                    Plane = 0,
-                    Utf16Sequence = new char[] { '\u0800' },
-                    Utf8Sequence = new byte[] { 0xE0, 0xA0, 0x80 }
-                }
-            };
-
-            yield return new object[] {
-                // last code point before the surrogate range
-                new GeneralTestData
-                {
-                    ScalarValue = 0xD7FF,
-                    IsAscii = false,
-                    IsBmp = true,
-                    Plane = 0,
-                    Utf16Sequence = new char[] { '\uD7FF' },
-                    Utf8Sequence = new byte[] { 0xED, 0x9F, 0xBF }
-                }
-            };
-
-            yield return new object[] {
-                // first code point after the surrogate range
-                new GeneralTestData
-                {
-                    ScalarValue = 0xE000,
-                    IsAscii = false,
-                    IsBmp = true,
-                    Plane = 0,
-                    Utf16Sequence = new char[] { '\uE000' },
-                    Utf8Sequence = new byte[] { 0xEE, 0x80, 0x80 }
-                }
-            };
-
-            yield return new object[] {
-                // replacement character
-                new GeneralTestData
-                {
-                    ScalarValue = 0xFFFD,
-                    IsAscii = false,
-                    IsBmp = true,
-                    Plane = 0,
-                    Utf16Sequence = new char[] { '\uFFFD' },
-                    Utf8Sequence = new byte[] { 0xEF, 0xBF, 0xBD }
-                }
-            };
-
-            yield return new object[] {
-                // last BMP code point / last UTF-8 two-code unit code point
-                new GeneralTestData
-                {
-                    ScalarValue = 0xFFFF,
-                    IsAscii = false,
-                    IsBmp = true,
-                    Plane = 0,
-                    Utf16Sequence = new char[] { '\uFFFF' },
-                    Utf8Sequence = new byte[] { 0xEF, 0xBF, 0xBF }
-                }
-            };
-        }
-
-        public static IEnumerable<object[]> GeneralTestData_SupplementaryCodePoints_ValidOnly()
-        {
-            yield return new object[]
-            {
-                // first BMP code point / first ASCII code point
-                new GeneralTestData
-                {
-                    ScalarValue = 0x10000,
-                    IsAscii = false,
-                    IsBmp = false,
-                    Plane = 1,
-                    Utf16Sequence = new char[] { '\uD800', '\uDC00' },
-                    Utf8Sequence = new byte[] { 0xF0, 0x90, 0x80, 0x80 }
-                }
-            };
-
-            yield return new object[]
-            {
-                // last supplementary code point
-                new GeneralTestData
-                {
-                    ScalarValue = 0x10FFFF,
-                    IsAscii = false,
-                    IsBmp = false,
-                    Plane = 16,
-                    Utf16Sequence = new char[] { '\uDBFF', '\uDFFF' },
-                    Utf8Sequence = new byte[] { 0xF4, 0x8F, 0xBF, 0xBF }
-                }
-            };
-        }
-        public static IEnumerable<object[]> IsValidTestData()
-        {
-            foreach (var obj in GeneralTestData_BmpCodePoints_NoSurrogates().Concat(GeneralTestData_SupplementaryCodePoints_ValidOnly()))
-            {
-                yield return new object[] { ((GeneralTestData)obj[0]).ScalarValue /* value */, true /* isValid */ };
-            }
-
-            foreach (var obj in BmpCodePoints_SurrogatesOnly().Concat(SupplementaryCodePoints_InvalidOnly()))
-            {
-                yield return new object[] { Convert.ToInt32(obj[0], CultureInfo.InvariantCulture) /* value */, false /* isValid */ };
-            }
-        }
-
-        public static IEnumerable<object[]> BmpCodePoints_SurrogatesOnly()
-        {
-            yield return new object[] { '\uD800' }; // first high surrogate code point
-            yield return new object[] { '\uDBFF' }; // last high surrogate code point
-            yield return new object[] { '\uDC00' }; // first low surrogate code point
-            yield return new object[] { '\uDFFF' }; // last low surrogate code point
-        }
-
-        public static IEnumerable<object[]> SupplementaryCodePoints_InvalidOnly()
-        {
-            yield return new object[] { (int)-1 }; // negative code points are disallowed
-            yield return new object[] { (int)0x110000 }; // just past the end of the allowed code point range
-            yield return new object[] { int.MaxValue }; // too large
-        }
-
-        public static IEnumerable<object[]> SurrogatePairTestData_InvalidOnly()
-        {
-            yield return new object[] { '\ud800', '\ud800' }; // two high surrogates
-            yield return new object[] { '\udfff', '\udfff' }; // two low surrogates
-            yield return new object[] { '\ude00', '\udb00' }; // low surrogate before high surrogate
-            yield return new object[] { '\ud900', '\u1234' }; // high surrogate followed by non-surrogate
-            yield return new object[] { '\ud900', '\ue000' }; // high surrogate followed by value just beyond low surrogate range
-            yield return new object[] { '\u1234', '\ude00' }; // low surrogate preceded by non-surrogate
-            yield return new object[] { '\udc00', '\ude00' }; // low surrogate preceded by value just beyond high surrogate range
-        }
-
-        public static IEnumerable<object[]> SurrogatePairTestData_ValidOnly()
-        {
-            yield return new object[] { '\ud800', '\udc00', 0x00010000 }; // lower bound for high & low surrogate
-            yield return new object[] { '\udbff', '\udfff', 0x0010FFFF }; // upper bound for high & low surrogate
-            yield return new object[] { '\ud83c', '\udfa8', 0x0001F3A8 }; // U+1F3A8 ARTIST PALETTE
-        }
-
-        public class GeneralTestData
-        {
-            public int ScalarValue;
-            public bool IsAscii;
-            public bool IsBmp;
-            public int Plane;
-            public char[] Utf16Sequence;
-            public byte[] Utf8Sequence;
-        }
-
-        public static IEnumerable<object[]> UnicodeInfoTestData_Latin1AndSelectOthers()
-        {
-            // ASCII
-
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x00), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x01), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x02), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x03), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x04), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x05), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x06), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x07), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x08), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x09), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0A), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0B), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0C), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0D), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0E), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x0F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x10), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x11), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x12), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x13), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x14), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x15), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x16), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x17), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x18), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x19), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1A), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1B), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1C), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1D), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1E), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x1F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x20), UnicodeCategory = UnicodeCategory.SpaceSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x21), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x22), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x23), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x24), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x25), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x26), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x27), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x28), UnicodeCategory = UnicodeCategory.OpenPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x29), UnicodeCategory = UnicodeCategory.ClosePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2A), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2B), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2C), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2D), UnicodeCategory = UnicodeCategory.DashPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2E), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2F), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x30), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 0, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x31), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 1, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x32), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 2, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x33), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 3, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x34), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 4, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x35), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 5, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x36), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 6, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x37), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 7, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x38), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 8, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x39), UnicodeCategory = UnicodeCategory.DecimalDigitNumber, NumericValue = 9, IsControl = false, IsDigit = true, IsLetter = false, IsLetterOrDigit = true, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3A), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3B), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3C), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3D), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3E), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x3F), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x40), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x41), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x42), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x43), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x44), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x45), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x46), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x47), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x48), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x49), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4A), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4B), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4C), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4D), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4E), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x4F), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x50), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x51), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x52), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x53), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x54), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x55), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x56), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x57), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x58), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x59), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5A), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5B), UnicodeCategory = UnicodeCategory.OpenPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5C), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5D), UnicodeCategory = UnicodeCategory.ClosePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5E), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x5F), UnicodeCategory = UnicodeCategory.ConnectorPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x60), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x61), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x62), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x63), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x64), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x65), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x66), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x67), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x68), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x69), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6A), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6B), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6C), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6D), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6E), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x6F), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x70), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x71), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x72), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x73), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x74), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x75), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x76), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x77), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x78), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x79), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7A), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7B), UnicodeCategory = UnicodeCategory.OpenPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7C), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7D), UnicodeCategory = UnicodeCategory.ClosePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7E), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x7F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-
-            // Remainder of Latin-1
-
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x80), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x81), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x82), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x83), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x84), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x85), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x86), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x87), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x88), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x89), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8A), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8B), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8C), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8D), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8E), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x8F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x90), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x91), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x92), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x93), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x94), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x95), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x96), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x97), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x98), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x99), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9A), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9B), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9C), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9D), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9E), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x9F), UnicodeCategory = UnicodeCategory.Control, NumericValue = -1, IsControl = true, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA0), UnicodeCategory = UnicodeCategory.SpaceSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA1), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA2), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA3), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA4), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA5), UnicodeCategory = UnicodeCategory.CurrencySymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA6), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA7), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA8), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xA9), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAA), UnicodeCategory = UnicodeCategory.OtherLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAB), UnicodeCategory = UnicodeCategory.InitialQuotePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAC), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAD), UnicodeCategory = UnicodeCategory.Format, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAE), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xAF), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB0), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB1), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB2), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 2, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB3), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 3, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB4), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB5), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB6), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB7), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB8), UnicodeCategory = UnicodeCategory.ModifierSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xB9), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBA), UnicodeCategory = UnicodeCategory.OtherLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBB), UnicodeCategory = UnicodeCategory.FinalQuotePunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBC), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 0.25, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBD), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 0.5, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBE), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 0.75, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xBF), UnicodeCategory = UnicodeCategory.OtherPunctuation, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = true, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC0), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC1), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC2), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC3), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC4), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC5), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC6), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC7), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC8), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xC9), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCA), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCB), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCC), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCD), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCE), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xCF), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD0), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD1), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD2), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD3), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD4), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD5), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD6), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD7), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD8), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xD9), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDA), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDB), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDC), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDD), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDE), UnicodeCategory = UnicodeCategory.UppercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = true, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xDF), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE0), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE1), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE2), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE3), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE4), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE5), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE6), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE7), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE8), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xE9), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEA), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEB), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEC), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xED), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEE), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xEF), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF0), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF1), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF2), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF3), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF4), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF5), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF6), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF7), UnicodeCategory = UnicodeCategory.MathSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF8), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xF9), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFA), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFB), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFC), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFD), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFE), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFF), UnicodeCategory = UnicodeCategory.LowercaseLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = true, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-
-            // Select others
-
-            // U+2000 EN QUAD
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2000), UnicodeCategory = UnicodeCategory.SpaceSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-
-            // U+2028 LINE SEPARATOR
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2028), UnicodeCategory = UnicodeCategory.LineSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-
-            // U+2029 PARAGRAPH SEPARATOR
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2029), UnicodeCategory = UnicodeCategory.ParagraphSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-
-            // U+202F NARROW NO-BREAK SPACE
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x202F), UnicodeCategory = UnicodeCategory.SpaceSeparator, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = true, IsSymbol = false, IsUpper = false, IsWhiteSpace = true } };
-
-            // U+2154 VULGAR FRACTION TWO THIRDS
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x2154), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 2.0 / 3, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-
-            // U+FFFD REPLACEMENT CHARACTER
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0xFFFD), UnicodeCategory = UnicodeCategory.OtherSymbol, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = true, IsUpper = false, IsWhiteSpace = false } };
-
-            // U+10000 LINEAR B SYLLABLE B008 A
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x10000), UnicodeCategory = UnicodeCategory.OtherLetter, NumericValue = -1, IsControl = false, IsDigit = false, IsLetter = true, IsLetterOrDigit = true, IsLower = false, IsNumber = false, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-
-            // U+10110 AEGEAN NUMBER TEN
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x10110), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 10, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-
-            // U+10177 GREEK TWO THIRDS SIGN
-            yield return new object[] { new UnicodeInfoTestData { ScalarValue = (Rune)(0x10177), UnicodeCategory = UnicodeCategory.OtherNumber, NumericValue = 2.0 / 3, IsControl = false, IsDigit = false, IsLetter = false, IsLetterOrDigit = false, IsLower = false, IsNumber = true, IsPunctuation = false, IsSeparator = false, IsSymbol = false, IsUpper = false, IsWhiteSpace = false } };
-
-        }
-
-        public class UnicodeInfoTestData
-        {
-            // named such so that it appears at the beginning of the console output for any failing unit test
-            public string __DebugDisplay => $"U+{ScalarValue.Value:X4}";
-
-            public Rune ScalarValue;
-            public UnicodeCategory UnicodeCategory;
-            public double NumericValue;
-            public bool IsControl;
-            public bool IsDigit;
-            public bool IsLetter;
-            public bool IsLetterOrDigit;
-            public bool IsLower;
-            public bool IsNumber;
-            public bool IsPunctuation;
-            public bool IsSeparator;
-            public bool IsSymbol;
-            public bool IsUpper;
-            public bool IsWhiteSpace;
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Text/RuneTests.cs b/src/libraries/System.Runtime/tests/System/Text/RuneTests.cs
new file mode 100644 (file)
index 0000000..28e097f
--- /dev/null
@@ -0,0 +1,647 @@
+// 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.Globalization;
+using System.Text.Unicode.Tests;
+using Xunit;
+using Xunit.Sdk;
+
+namespace System.Text.Tests
+{
+    public static partial class RuneTests
+    {
+        [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows8xOrLater))] // the localization tables used by our test data only exist on Win8+
+        [PlatformSpecific(TestPlatforms.Windows)]
+        [InlineData('0', '0', '0', "en-US")]
+        [InlineData('a', 'A', 'a', "en-US")]
+        [InlineData('i', 'I', 'i', "en-US")]
+        [InlineData('i', '\u0130', 'i', "tr-TR")]
+        [InlineData('z', 'Z', 'z', "en-US")]
+        [InlineData('A', 'A', 'a', "en-US")]
+        [InlineData('I', 'I', 'i', "en-US")]
+        [InlineData('I', 'I', '\u0131', "tr-TR")]
+        [InlineData('Z', 'Z', 'z', "en-US")]
+        [InlineData('\u00DF', '\u00DF', '\u00DF', "de-DE")] // U+00DF LATIN SMALL LETTER SHARP S -- n.b. ToUpper doesn't create the majuscule form
+        [InlineData('\u0130', '\u0130', 'i', "tr-TR")] // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE
+        [InlineData('\u0131', 'I', '\u0131', "tr-TR")] // U+0131 LATIN SMALL LETTER DOTLESS I
+        [InlineData('\u1E9E', '\u1E9E', '\u00DF', "de-DE")] // U+1E9E LATIN CAPITAL LETTER SHARP S
+        [InlineData(0x10400, 0x10400, 0x10428, "en-US")] // U+10400 DESERET CAPITAL LETTER LONG I
+        [InlineData(0x10428, 0x10400, 0x10428, "en-US")] // U+10428 DESERET SMALL LETTER LONG I
+        public static void Casing_CultureAware(int original, int upper, int lower, string culture)
+        {
+            var rune = new Rune(original);
+            var cultureInfo = CultureInfo.GetCultureInfo(culture);
+            Assert.Equal(new Rune(upper), Rune.ToUpper(rune, cultureInfo));
+            Assert.Equal(new Rune(lower), Rune.ToLower(rune, cultureInfo));
+        }
+
+        // Invariant ToUpper / ToLower doesn't modify Turkish I or majuscule Eszett
+        [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows8xOrLater))] // the localization tables used by our test data only exist on Win8+
+        [PlatformSpecific(TestPlatforms.Windows)]
+        [InlineData('0', '0', '0')]
+        [InlineData('a', 'A', 'a')]
+        [InlineData('i', 'I', 'i')]
+        [InlineData('z', 'Z', 'z')]
+        [InlineData('A', 'A', 'a')]
+        [InlineData('I', 'I', 'i')]
+        [InlineData('Z', 'Z', 'z')]
+        [InlineData('\u00DF', '\u00DF', '\u00DF')] // U+00DF LATIN SMALL LETTER SHARP S
+        [InlineData('\u0130', '\u0130', '\u0130')] // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE
+        [InlineData('\u0131', '\u0131', '\u0131')] // U+0131 LATIN SMALL LETTER DOTLESS I
+        [InlineData('\u1E9E', '\u1E9E', '\u1E9E')] // U+1E9E LATIN CAPITAL LETTER SHARP S
+        [InlineData(0x10400, 0x10400, 0x10428)] // U+10400 DESERET CAPITAL LETTER LONG I
+        [InlineData(0x10428, 0x10400, 0x10428)] // U+10428 DESERET SMALL LETTER LONG I
+        public static void Casing_Invariant(int original, int upper, int lower)
+        {
+            var rune = new Rune(original);
+            Assert.Equal(new Rune(upper), Rune.ToUpperInvariant(rune));
+            Assert.Equal(new Rune(lower), Rune.ToLowerInvariant(rune));
+        }
+
+        [Theory]
+        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
+        public static void Ctor_Cast_Char_Valid(GeneralTestData testData)
+        {
+            Rune rune = new Rune(checked((char)testData.ScalarValue));
+            Rune runeFromCast = (Rune)(char)testData.ScalarValue;
+
+            Assert.Equal(rune, runeFromCast);
+            Assert.Equal(testData.ScalarValue, rune.Value);
+            Assert.Equal(testData.IsAscii, rune.IsAscii);
+            Assert.Equal(testData.IsBmp, rune.IsBmp);
+            Assert.Equal(testData.Plane, rune.Plane);
+        }
+
+        [Theory]
+        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
+        public static void Ctor_Cast_Char_Invalid_Throws(char ch)
+        {
+            Assert.Throws<ArgumentOutOfRangeException>(nameof(ch), () => new Rune(ch));
+            Assert.Throws<ArgumentOutOfRangeException>(nameof(ch), () => (Rune)ch);
+        }
+
+        [Theory]
+        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
+        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
+        public static void Ctor_Cast_Int32_Valid(GeneralTestData testData)
+        {
+            Rune rune = new Rune((int)testData.ScalarValue);
+            Rune runeFromCast = (Rune)(int)testData.ScalarValue;
+
+            Assert.Equal(rune, runeFromCast);
+            Assert.Equal(testData.ScalarValue, rune.Value);
+            Assert.Equal(testData.IsAscii, rune.IsAscii);
+            Assert.Equal(testData.IsBmp, rune.IsBmp);
+            Assert.Equal(testData.Plane, rune.Plane);
+        }
+
+        [Theory]
+        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
+        [MemberData(nameof(SupplementaryCodePoints_InvalidOnly))]
+        public static void Ctor_Cast_Int32_Invalid_Throws(int value)
+        {
+            Assert.Throws<ArgumentOutOfRangeException>(nameof(value), () => new Rune(value));
+            Assert.Throws<ArgumentOutOfRangeException>(nameof(value), () => (Rune)value);
+        }
+
+        [Theory]
+        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
+        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
+        public static void Ctor_Cast_UInt32_Valid(GeneralTestData testData)
+        {
+            Rune rune = new Rune((uint)testData.ScalarValue);
+            Rune runeFromCast = (Rune)(uint)testData.ScalarValue;
+
+            Assert.Equal(rune, runeFromCast);
+            Assert.Equal(testData.ScalarValue, rune.Value);
+            Assert.Equal(testData.IsAscii, rune.IsAscii);
+            Assert.Equal(testData.IsBmp, rune.IsBmp);
+            Assert.Equal(testData.Plane, rune.Plane);
+        }
+
+        [Theory]
+        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
+        [MemberData(nameof(SupplementaryCodePoints_InvalidOnly))]
+        public static void Ctor_Cast_UInt32_Invalid_Throws(int value)
+        {
+            Assert.Throws<ArgumentOutOfRangeException>(nameof(value), () => new Rune((uint)value));
+            Assert.Throws<ArgumentOutOfRangeException>(nameof(value), () => (Rune)(uint)value);
+        }
+
+        [Theory]
+        [MemberData(nameof(SurrogatePairTestData_ValidOnly))]
+        public static void Ctor_SurrogatePair_Valid(char highSurrogate, char lowSurrogate, int expectedValue)
+        {
+            Assert.Equal(expectedValue, new Rune(highSurrogate, lowSurrogate).Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(SurrogatePairTestData_InvalidOnly))]
+        public static void Ctor_SurrogatePair_Valid(char highSurrogate, char lowSurrogate)
+        {
+            string expectedParamName = !char.IsHighSurrogate(highSurrogate) ? nameof(highSurrogate) : nameof(lowSurrogate);
+            Assert.Throws<ArgumentOutOfRangeException>(expectedParamName, () => new Rune(highSurrogate, lowSurrogate));
+        }
+
+        [Theory]
+        [InlineData('A', 'a', -1)]
+        [InlineData('A', 'A', 0)]
+        [InlineData('a', 'A', 1)]
+        [InlineData(0x10000, 0x10000, 0)]
+        [InlineData('\uFFFD', 0x10000, -1)]
+        [InlineData(0x10FFFF, 0x10000, 1)]
+        public static void CompareTo_And_ComparisonOperators(int first, int other, int expectedSign)
+        {
+            Rune a = new Rune(first);
+            Rune b = new Rune(other);
+
+            Assert.Equal(expectedSign, Math.Sign(a.CompareTo(b)));
+            Assert.Equal(expectedSign < 0, a < b);
+            Assert.Equal(expectedSign <= 0, a <= b);
+            Assert.Equal(expectedSign > 0, a > b);
+            Assert.Equal(expectedSign >= 0, a >= b);
+        }
+
+        [Theory]
+        [InlineData(new char[0], OperationStatus.NeedMoreData, 0xFFFD, 0)] // empty buffer
+        [InlineData(new char[] { '\u1234' }, OperationStatus.Done, 0x1234, 1)] // BMP char
+        [InlineData(new char[] { '\u1234', '\ud800' }, OperationStatus.Done, 0x1234, 1)] // BMP char
+        [InlineData(new char[] { '\ud83d', '\ude32' }, OperationStatus.Done, 0x1F632, 2)] // supplementary value (U+1F632 ASTONISHED FACE)
+        [InlineData(new char[] { '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
+        [InlineData(new char[] { '\udc00', '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
+        [InlineData(new char[] { '\ud800' }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // high surrogate at end of buffer
+        [InlineData(new char[] { '\ud800', '\ud800' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone high surrogate
+        [InlineData(new char[] { '\ud800', '\u1234' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone high surrogate
+        public static void DecodeFromUtf16(char[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedCharsConsumed)
+        {
+            Assert.Equal(expectedOperationStatus, Rune.DecodeFromUtf16(data, out Rune actualRune, out int actualCharsConsumed));
+            Assert.Equal(expectedRuneValue, actualRune.Value);
+            Assert.Equal(expectedCharsConsumed, actualCharsConsumed);
+        }
+
+        [Theory]
+        [InlineData(new char[0], OperationStatus.NeedMoreData, 0xFFFD, 0)] // empty buffer
+        [InlineData(new char[] { '\u1234', '\u5678' }, OperationStatus.Done, 0x5678, 1)] // BMP char
+        [InlineData(new char[] { '\udc00', '\ud800' }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // high surrogate at end of buffer
+        [InlineData(new char[] { '\ud83d', '\ude32' }, OperationStatus.Done, 0x1F632, 2)] // supplementary value (U+1F632 ASTONISHED FACE)
+        [InlineData(new char[] { '\u1234', '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
+        [InlineData(new char[] { '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
+        public static void DecodeLastFromUtf16(char[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedCharsConsumed)
+        {
+            Assert.Equal(expectedOperationStatus, Rune.DecodeLastFromUtf16(data, out Rune actualRune, out int actualCharsConsumed));
+            Assert.Equal(expectedRuneValue, actualRune.Value);
+            Assert.Equal(expectedCharsConsumed, actualCharsConsumed);
+        }
+
+        [Theory]
+        [InlineData(new byte[0], OperationStatus.NeedMoreData, 0xFFFD, 0)] // empty buffer
+        [InlineData(new byte[] { 0x30 }, OperationStatus.Done, 0x0030, 1)] // ASCII byte
+        [InlineData(new byte[] { 0x30, 0x40, 0x50 }, OperationStatus.Done, 0x0030, 1)] // ASCII byte
+        [InlineData(new byte[] { 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
+        [InlineData(new byte[] { 0x80, 0x80, 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
+        [InlineData(new byte[] { 0xC1 }, OperationStatus.InvalidData, 0xFFFD, 1)] // C1 is never a valid UTF-8 byte
+        [InlineData(new byte[] { 0xF5 }, OperationStatus.InvalidData, 0xFFFD, 1)] // F5 is never a valid UTF-8 byte
+        [InlineData(new byte[] { 0xC2 }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // C2 is a valid byte; expecting it to be followed by a continuation byte
+        [InlineData(new byte[] { 0xED }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // ED is a valid byte; expecting it to be followed by a continuation byte
+        [InlineData(new byte[] { 0xF4 }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // F4 is a valid byte; expecting it to be followed by a continuation byte
+        [InlineData(new byte[] { 0xC2, 0xC2 }, OperationStatus.InvalidData, 0xFFFD, 1)] // C2 not followed by continuation byte
+        [InlineData(new byte[] { 0xC3, 0x90 }, OperationStatus.Done, 0x00D0, 2)] // [ C3 90 ] is U+00D0 LATIN CAPITAL LETTER ETH
+        [InlineData(new byte[] { 0xC1, 0xBF }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ C1 BF ] is overlong 2-byte sequence, all overlong sequences have maximal invalid subsequence length 1
+        [InlineData(new byte[] { 0xE0, 0x9F }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ E0 9F ] is overlong 3-byte sequence, all overlong sequences have maximal invalid subsequence length 1
+        [InlineData(new byte[] { 0xE0, 0xA0 }, OperationStatus.NeedMoreData, 0xFFFD, 2)] // [ E0 A0 ] is valid 2-byte start of 3-byte sequence
+        [InlineData(new byte[] { 0xED, 0x9F }, OperationStatus.NeedMoreData, 0xFFFD, 2)] // [ ED 9F ] is valid 2-byte start of 3-byte sequence
+        [InlineData(new byte[] { 0xED, 0xBF }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ ED BF ] would place us in UTF-16 surrogate range, all surrogate sequences have maximal invalid subsequence length 1
+        [InlineData(new byte[] { 0xEE, 0x80 }, OperationStatus.NeedMoreData, 0xFFFD, 2)] // [ EE 80 ] is valid 2-byte start of 3-byte sequence
+        [InlineData(new byte[] { 0xF0, 0x8F }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ F0 8F ] is overlong 4-byte sequence, all overlong sequences have maximal invalid subsequence length 1
+        [InlineData(new byte[] { 0xF0, 0x90 }, OperationStatus.NeedMoreData, 0xFFFD, 2)] // [ F0 90 ] is valid 2-byte start of 4-byte sequence
+        [InlineData(new byte[] { 0xF4, 0x90 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ F4 90 ] would place us beyond U+10FFFF, all such sequences have maximal invalid subsequence length 1
+        [InlineData(new byte[] { 0xE2, 0x88, 0xB4 }, OperationStatus.Done, 0x2234, 3)] // [ E2 88 B4 ] is U+2234 THEREFORE
+        [InlineData(new byte[] { 0xE2, 0x88, 0xC0 }, OperationStatus.InvalidData, 0xFFFD, 2)] // [ E2 88 ] followed by non-continuation byte, maximal invalid subsequence length 2
+        [InlineData(new byte[] { 0xF0, 0x9F, 0x98 }, OperationStatus.NeedMoreData, 0xFFFD, 3)] // [ F0 9F 98 ] is valid 3-byte start of 4-byte sequence
+        [InlineData(new byte[] { 0xF0, 0x9F, 0x98, 0x20 }, OperationStatus.InvalidData, 0xFFFD, 3)] // [ F0 9F 98 ] followed by non-continuation byte, maximal invalid subsequence length 3
+        [InlineData(new byte[] { 0xF0, 0x9F, 0x98, 0xB2 }, OperationStatus.Done, 0x1F632, 4)] // [ F0 9F 98 B2 ] is U+1F632 ASTONISHED FACE
+        public static void DecodeFromUtf8(byte[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedBytesConsumed)
+        {
+            Assert.Equal(expectedOperationStatus, Rune.DecodeFromUtf8(data, out Rune actualRune, out int actualBytesConsumed));
+            Assert.Equal(expectedRuneValue, actualRune.Value);
+            Assert.Equal(expectedBytesConsumed, actualBytesConsumed);
+        }
+
+        [Theory]
+        [InlineData(new byte[0], OperationStatus.NeedMoreData, 0xFFFD, 0)] // empty buffer
+        [InlineData(new byte[] { 0x30 }, OperationStatus.Done, 0x0030, 1)] // ASCII byte
+        [InlineData(new byte[] { 0x30, 0x40, 0x50 }, OperationStatus.Done, 0x0050, 1)] // ASCII byte
+        [InlineData(new byte[] { 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
+        [InlineData(new byte[] { 0x80, 0x80, 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
+        [InlineData(new byte[] { 0x80, 0x80, 0x80, 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
+        [InlineData(new byte[] { 0x80, 0x80, 0x80, 0xC2 }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // [ C2 ] at end of buffer, valid 1-byte start of 2-byte sequence
+        [InlineData(new byte[] { 0xC1 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ C1 ] is never a valid byte
+        [InlineData(new byte[] { 0x80, 0xE2, 0x88, 0xB4 }, OperationStatus.Done, 0x2234, 3)] // [ E2 88 B4 ] is U+2234 THEREFORE
+        [InlineData(new byte[] { 0xF0, 0x9F, 0x98, 0xB2 }, OperationStatus.Done, 0x1F632, 4)] // [ F0 9F 98 B2 ] is U+1F632 ASTONISHED FACE
+        [InlineData(new byte[] { 0xE2, 0x88, 0xB4, 0xB2 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ B2 ] is standalone continuation byte
+        [InlineData(new byte[] { 0x80, 0x62, 0x80, 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ 80 ] is standalone continuation byte
+        [InlineData(new byte[] { 0xF0, 0x9F, 0x98, }, OperationStatus.NeedMoreData, 0xFFFD, 3)] // [ F0 9F 98 ] is valid 3-byte start of 4-byte sequence
+        public static void DecodeLastFromUtf8(byte[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedBytesConsumed)
+        {
+            Assert.Equal(expectedOperationStatus, Rune.DecodeLastFromUtf8(data, out Rune actualRune, out int actualBytesConsumed));
+            Assert.Equal(expectedRuneValue, actualRune.Value);
+            Assert.Equal(expectedBytesConsumed, actualBytesConsumed);
+        }
+
+        [Theory]
+        [InlineData(0, 0, true)]
+        [InlineData(0x10FFFF, 0x10FFFF, true)]
+        [InlineData(0xFFFD, 0xFFFD, true)]
+        [InlineData(0xFFFD, 0xFFFF, false)]
+        [InlineData('a', 'a', true)]
+        [InlineData('a', 'A', false)]
+        [InlineData('a', 'b', false)]
+        public static void Equals_OperatorEqual_OperatorNotEqual(int first, int other, bool expected)
+        {
+            Rune a = new Rune(first);
+            Rune b = new Rune(other);
+
+            Assert.Equal(expected, Object.Equals(a, b));
+            Assert.Equal(expected, a.Equals(b));
+            Assert.Equal(expected, a.Equals((object)b));
+            Assert.Equal(expected, a == b);
+            Assert.NotEqual(expected, a != b);
+        }
+
+        [Theory]
+        [InlineData(0)]
+        [InlineData('a')]
+        [InlineData('\uFFFD')]
+        [InlineData(0x10FFFF)]
+        public static void GetHashCodeTests(int scalarValue)
+        {
+            Assert.Equal(scalarValue, new Rune(scalarValue).GetHashCode());
+        }
+
+        [Theory]
+        [InlineData("a", 0, (int)'a')]
+        [InlineData("ab", 1, (int)'b')]
+        [InlineData("x\U0001F46Ey", 3, (int)'y')]
+        [InlineData("x\U0001F46Ey", 1, 0x1F46E)] // U+1F46E POLICE OFFICER
+        public static void GetRuneAt_TryGetRuneAt_Utf16_Success(string inputString, int index, int expectedScalarValue)
+        {
+            // GetRuneAt
+            Assert.Equal(expectedScalarValue, Rune.GetRuneAt(inputString, index).Value);
+
+            // TryGetRuneAt
+            Assert.True(Rune.TryGetRuneAt(inputString, index, out Rune rune));
+            Assert.Equal(expectedScalarValue, rune.Value);
+        }
+
+        // Our unit test runner doesn't deal well with malformed literal strings, so
+        // we smuggle it as a char[] and turn it into a string within the test itself.
+        [Theory]
+        [InlineData(new char[] { 'x', '\uD83D', '\uDC6E', 'y' }, 2)] // attempt to index into the middle of a UTF-16 surrogate pair
+        [InlineData(new char[] { 'x', '\uD800', 'y' }, 1)] // high surrogate not followed by low surrogate
+        [InlineData(new char[] { 'x', '\uDFFF', '\uDFFF' }, 1)] // attempt to start at a low surrogate
+        [InlineData(new char[] { 'x', '\uD800' }, 1)] // end of string reached before could complete surrogate pair
+        public static void GetRuneAt_TryGetRuneAt_Utf16_InvalidData(char[] inputCharArray, int index)
+        {
+            string inputString = new string(inputCharArray);
+
+            // GetRuneAt
+            Assert.Throws<ArgumentException>("index", () => Rune.GetRuneAt(inputString, index));
+
+            // TryGetRuneAt
+            Assert.False(Rune.TryGetRuneAt(inputString, index, out Rune rune));
+            Assert.Equal(0, rune.Value);
+        }
+
+        [Fact]
+        public static void GetRuneAt_TryGetRuneAt_Utf16_BadArgs()
+        {
+            // null input
+            Assert.Throws<ArgumentNullException>("input", () => Rune.GetRuneAt(null, 0));
+
+            // negative index specified
+            Assert.Throws<ArgumentOutOfRangeException>("index", () => Rune.GetRuneAt("hello", -1));
+
+            // index goes past end of string
+            Assert.Throws<ArgumentOutOfRangeException>("index", () => Rune.GetRuneAt(string.Empty, 0));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void GetNumericValue(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.NumericValue, Rune.GetNumericValue(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void GetUnicodeCategory(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.UnicodeCategory, Rune.GetUnicodeCategory(testData.ScalarValue));
+        }
+
+        [OuterLoop]
+        [Fact]
+        public static void GetUnicodeCategory_AllInputs()
+        {
+            // This tests calls Rune.GetUnicodeCategory for every possible input, ensuring that
+            // the runtime agrees with the data in the core Unicode files.
+
+            foreach (Rune rune in AllRunes())
+            {
+                if (UnicodeData.GetUnicodeCategory((uint)rune.Value) != Rune.GetUnicodeCategory(rune))
+                {
+                    // We'll build up the exception message ourselves so the dev knows what code point failed.
+                    throw new AssertActualExpectedException(
+                        expected: UnicodeData.GetUnicodeCategory((uint)rune.Value),
+                        actual: Rune.GetUnicodeCategory(rune),
+                        userMessage: FormattableString.Invariant($@"Rune.GetUnicodeCategory(U+{rune.Value:X4}) returned wrong value."));
+                }
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsControl(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsControl, Rune.IsControl(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsDigit(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsDigit, Rune.IsDigit(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsLetter(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsLetter, Rune.IsLetter(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsLetterOrDigit(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsLetterOrDigit, Rune.IsLetterOrDigit(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsLower(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsLower, Rune.IsLower(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsNumber(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsNumber, Rune.IsNumber(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsPunctuation(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsPunctuation, Rune.IsPunctuation(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsSeparator(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsSeparator, Rune.IsSeparator(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsSymbol(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsSymbol, Rune.IsSymbol(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsUpper(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsUpper, Rune.IsUpper(testData.ScalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(IsValidTestData))]
+        public static void IsValid(int scalarValue, bool expectedIsValid)
+        {
+            Assert.Equal(expectedIsValid, Rune.IsValid(scalarValue));
+            Assert.Equal(expectedIsValid, Rune.IsValid((uint)scalarValue));
+        }
+
+        [Theory]
+        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
+        public static void IsWhiteSpace(UnicodeInfoTestData testData)
+        {
+            Assert.Equal(testData.IsWhiteSpace, Rune.IsWhiteSpace(testData.ScalarValue));
+        }
+
+        [OuterLoop]
+        [Fact]
+        public static void IsWhiteSpace_AllInputs()
+        {
+            // This tests calls Rune.IsWhiteSpace for every possible input, ensuring that
+            // the runtime agrees with the data in the core Unicode files.
+
+            foreach (Rune rune in AllRunes())
+            {
+                Assert.Equal(UnicodeData.IsWhiteSpace((uint)rune.Value), Rune.IsWhiteSpace(rune));
+            }
+        }
+
+        [Theory]
+        [InlineData(0, 0)]
+        [InlineData(0x80, 0x80)]
+        [InlineData(0x80, 0x100)]
+        [InlineData(0x100, 0x80)]
+        public static void Operators_And_CompareTo(uint scalarValueLeft, uint scalarValueRight)
+        {
+            Rune left = new Rune(scalarValueLeft);
+            Rune right = new Rune(scalarValueRight);
+
+            Assert.Equal(scalarValueLeft == scalarValueRight, left == right);
+            Assert.Equal(scalarValueLeft != scalarValueRight, left != right);
+            Assert.Equal(scalarValueLeft < scalarValueRight, left < right);
+            Assert.Equal(scalarValueLeft <= scalarValueRight, left <= right);
+            Assert.Equal(scalarValueLeft > scalarValueRight, left > right);
+            Assert.Equal(scalarValueLeft >= scalarValueRight, left >= right);
+            Assert.Equal(scalarValueLeft.CompareTo(scalarValueRight), left.CompareTo(right));
+        }
+
+        [Fact]
+        public static void ReplacementChar()
+        {
+            Assert.Equal(0xFFFD, Rune.ReplacementChar.Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
+        public static void TryCreate_Char_Valid(GeneralTestData testData)
+        {
+            Assert.True(Rune.TryCreate((char)testData.ScalarValue, out Rune result));
+            Assert.Equal(testData.ScalarValue, result.Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
+        public static void TryCreate_Char_Invalid(int scalarValue)
+        {
+            Assert.False(Rune.TryCreate((char)scalarValue, out Rune result));
+            Assert.Equal(0, result.Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(SurrogatePairTestData_InvalidOnly))]
+        public static void TryCreate_SurrogateChars_Invalid(char highSurrogate, char lowSurrogate)
+        {
+            Assert.False(Rune.TryCreate(highSurrogate, lowSurrogate, out Rune result));
+            Assert.Equal(0, result.Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(SurrogatePairTestData_ValidOnly))]
+        public static void TryCreate_SurrogateChars_Valid(char highSurrogate, char lowSurrogate, int expectedValue)
+        {
+            Assert.True(Rune.TryCreate(highSurrogate, lowSurrogate, out Rune result));
+            Assert.Equal(expectedValue, result.Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
+        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
+        public static void TryCreate_Int32_Valid(GeneralTestData testData)
+        {
+            Assert.True(Rune.TryCreate((int)testData.ScalarValue, out Rune result));
+            Assert.Equal(testData.ScalarValue, result.Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
+        [MemberData(nameof(SupplementaryCodePoints_InvalidOnly))]
+        public static void TryCreate_Int32_Invalid(int scalarValue)
+        {
+            Assert.False(Rune.TryCreate((int)scalarValue, out Rune result));
+            Assert.Equal(0, result.Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
+        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
+        public static void TryCreate_UInt32_Valid(GeneralTestData testData)
+        {
+            Assert.True(Rune.TryCreate((uint)testData.ScalarValue, out Rune result));
+            Assert.Equal(testData.ScalarValue, result.Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
+        [MemberData(nameof(SupplementaryCodePoints_InvalidOnly))]
+        public static void TryCreate_UInt32_Invalid(int scalarValue)
+        {
+            Assert.False(Rune.TryCreate((uint)scalarValue, out Rune result));
+            Assert.Equal(0, result.Value);
+        }
+
+        [Theory]
+        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
+        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
+        public static void ToStringTests(GeneralTestData testData)
+        {
+            Assert.Equal(new string(testData.Utf16Sequence), new Rune(testData.ScalarValue).ToString());
+        }
+
+        [Theory]
+        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
+        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
+        public static void TryEncodeToUtf16(GeneralTestData testData)
+        {
+            Rune rune = new Rune(testData.ScalarValue);
+            Assert.Equal(testData.Utf16Sequence.Length, rune.Utf16SequenceLength);
+
+            // First, try with a buffer that's too short
+
+            Span<char> utf16Buffer = stackalloc char[rune.Utf16SequenceLength - 1];
+            bool success = rune.TryEncodeToUtf16(utf16Buffer, out int charsWritten);
+            Assert.False(success);
+            Assert.Equal(0, charsWritten);
+
+            Assert.Throws<ArgumentException>("destination", () => rune.EncodeToUtf16(new char[rune.Utf16SequenceLength - 1]));
+
+            // Then, try with a buffer that's appropriately sized
+
+            utf16Buffer = stackalloc char[rune.Utf16SequenceLength];
+            success = rune.TryEncodeToUtf16(utf16Buffer, out charsWritten);
+            Assert.True(success);
+            Assert.Equal(testData.Utf16Sequence.Length, charsWritten);
+            Assert.True(utf16Buffer.SequenceEqual(testData.Utf16Sequence));
+
+            utf16Buffer.Clear();
+            Assert.Equal(testData.Utf16Sequence.Length, rune.EncodeToUtf16(utf16Buffer));
+            Assert.True(utf16Buffer.SequenceEqual(testData.Utf16Sequence));
+
+            // Finally, try with a buffer that's too long (should succeed)
+
+            utf16Buffer = stackalloc char[rune.Utf16SequenceLength + 1];
+            success = rune.TryEncodeToUtf16(utf16Buffer, out charsWritten);
+            Assert.True(success);
+            Assert.Equal(testData.Utf16Sequence.Length, charsWritten);
+            Assert.True(utf16Buffer.Slice(0, testData.Utf16Sequence.Length).SequenceEqual(testData.Utf16Sequence));
+
+            utf16Buffer.Clear();
+            Assert.Equal(testData.Utf16Sequence.Length, rune.EncodeToUtf16(utf16Buffer));
+            Assert.True(utf16Buffer.Slice(0, testData.Utf16Sequence.Length).SequenceEqual(testData.Utf16Sequence));
+        }
+
+        [Theory]
+        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
+        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
+        public static void TryEncodeToUtf8(GeneralTestData testData)
+        {
+            Rune rune = new Rune(testData.ScalarValue);
+            Assert.Equal(testData.Utf8Sequence.Length, actual: rune.Utf8SequenceLength);
+
+            // First, try with a buffer that's too short
+
+            Span<byte> utf8Buffer = stackalloc byte[rune.Utf8SequenceLength - 1];
+            bool success = rune.TryEncodeToUtf8(utf8Buffer, out int bytesWritten);
+            Assert.False(success);
+            Assert.Equal(0, bytesWritten);
+
+            Assert.Throws<ArgumentException>("destination", () => rune.EncodeToUtf8(new byte[rune.Utf8SequenceLength - 1]));
+
+            // Then, try with a buffer that's appropriately sized
+
+            utf8Buffer = stackalloc byte[rune.Utf8SequenceLength];
+            success = rune.TryEncodeToUtf8(utf8Buffer, out bytesWritten);
+            Assert.True(success);
+            Assert.Equal(testData.Utf8Sequence.Length, bytesWritten);
+            Assert.True(utf8Buffer.SequenceEqual(testData.Utf8Sequence));
+
+            utf8Buffer.Clear();
+            Assert.Equal(testData.Utf8Sequence.Length, rune.EncodeToUtf8(utf8Buffer));
+            Assert.True(utf8Buffer.SequenceEqual(testData.Utf8Sequence));
+
+            // Finally, try with a buffer that's too long (should succeed)
+
+            utf8Buffer = stackalloc byte[rune.Utf8SequenceLength + 1];
+            success = rune.TryEncodeToUtf8(utf8Buffer, out bytesWritten);
+            Assert.True(success);
+            Assert.Equal(testData.Utf8Sequence.Length, bytesWritten);
+            Assert.True(utf8Buffer.Slice(0, testData.Utf8Sequence.Length).SequenceEqual(testData.Utf8Sequence));
+
+            utf8Buffer.Clear();
+            Assert.Equal(testData.Utf8Sequence.Length, rune.EncodeToUtf8(utf8Buffer));
+            Assert.True(utf8Buffer.Slice(0, testData.Utf8Sequence.Length).SequenceEqual(testData.Utf8Sequence));
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Text/RuneTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/RuneTests.netcoreapp.cs
deleted file mode 100644 (file)
index 28e097f..0000000
+++ /dev/null
@@ -1,647 +0,0 @@
-// 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.Globalization;
-using System.Text.Unicode.Tests;
-using Xunit;
-using Xunit.Sdk;
-
-namespace System.Text.Tests
-{
-    public static partial class RuneTests
-    {
-        [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows8xOrLater))] // the localization tables used by our test data only exist on Win8+
-        [PlatformSpecific(TestPlatforms.Windows)]
-        [InlineData('0', '0', '0', "en-US")]
-        [InlineData('a', 'A', 'a', "en-US")]
-        [InlineData('i', 'I', 'i', "en-US")]
-        [InlineData('i', '\u0130', 'i', "tr-TR")]
-        [InlineData('z', 'Z', 'z', "en-US")]
-        [InlineData('A', 'A', 'a', "en-US")]
-        [InlineData('I', 'I', 'i', "en-US")]
-        [InlineData('I', 'I', '\u0131', "tr-TR")]
-        [InlineData('Z', 'Z', 'z', "en-US")]
-        [InlineData('\u00DF', '\u00DF', '\u00DF', "de-DE")] // U+00DF LATIN SMALL LETTER SHARP S -- n.b. ToUpper doesn't create the majuscule form
-        [InlineData('\u0130', '\u0130', 'i', "tr-TR")] // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE
-        [InlineData('\u0131', 'I', '\u0131', "tr-TR")] // U+0131 LATIN SMALL LETTER DOTLESS I
-        [InlineData('\u1E9E', '\u1E9E', '\u00DF', "de-DE")] // U+1E9E LATIN CAPITAL LETTER SHARP S
-        [InlineData(0x10400, 0x10400, 0x10428, "en-US")] // U+10400 DESERET CAPITAL LETTER LONG I
-        [InlineData(0x10428, 0x10400, 0x10428, "en-US")] // U+10428 DESERET SMALL LETTER LONG I
-        public static void Casing_CultureAware(int original, int upper, int lower, string culture)
-        {
-            var rune = new Rune(original);
-            var cultureInfo = CultureInfo.GetCultureInfo(culture);
-            Assert.Equal(new Rune(upper), Rune.ToUpper(rune, cultureInfo));
-            Assert.Equal(new Rune(lower), Rune.ToLower(rune, cultureInfo));
-        }
-
-        // Invariant ToUpper / ToLower doesn't modify Turkish I or majuscule Eszett
-        [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows8xOrLater))] // the localization tables used by our test data only exist on Win8+
-        [PlatformSpecific(TestPlatforms.Windows)]
-        [InlineData('0', '0', '0')]
-        [InlineData('a', 'A', 'a')]
-        [InlineData('i', 'I', 'i')]
-        [InlineData('z', 'Z', 'z')]
-        [InlineData('A', 'A', 'a')]
-        [InlineData('I', 'I', 'i')]
-        [InlineData('Z', 'Z', 'z')]
-        [InlineData('\u00DF', '\u00DF', '\u00DF')] // U+00DF LATIN SMALL LETTER SHARP S
-        [InlineData('\u0130', '\u0130', '\u0130')] // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE
-        [InlineData('\u0131', '\u0131', '\u0131')] // U+0131 LATIN SMALL LETTER DOTLESS I
-        [InlineData('\u1E9E', '\u1E9E', '\u1E9E')] // U+1E9E LATIN CAPITAL LETTER SHARP S
-        [InlineData(0x10400, 0x10400, 0x10428)] // U+10400 DESERET CAPITAL LETTER LONG I
-        [InlineData(0x10428, 0x10400, 0x10428)] // U+10428 DESERET SMALL LETTER LONG I
-        public static void Casing_Invariant(int original, int upper, int lower)
-        {
-            var rune = new Rune(original);
-            Assert.Equal(new Rune(upper), Rune.ToUpperInvariant(rune));
-            Assert.Equal(new Rune(lower), Rune.ToLowerInvariant(rune));
-        }
-
-        [Theory]
-        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
-        public static void Ctor_Cast_Char_Valid(GeneralTestData testData)
-        {
-            Rune rune = new Rune(checked((char)testData.ScalarValue));
-            Rune runeFromCast = (Rune)(char)testData.ScalarValue;
-
-            Assert.Equal(rune, runeFromCast);
-            Assert.Equal(testData.ScalarValue, rune.Value);
-            Assert.Equal(testData.IsAscii, rune.IsAscii);
-            Assert.Equal(testData.IsBmp, rune.IsBmp);
-            Assert.Equal(testData.Plane, rune.Plane);
-        }
-
-        [Theory]
-        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
-        public static void Ctor_Cast_Char_Invalid_Throws(char ch)
-        {
-            Assert.Throws<ArgumentOutOfRangeException>(nameof(ch), () => new Rune(ch));
-            Assert.Throws<ArgumentOutOfRangeException>(nameof(ch), () => (Rune)ch);
-        }
-
-        [Theory]
-        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
-        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
-        public static void Ctor_Cast_Int32_Valid(GeneralTestData testData)
-        {
-            Rune rune = new Rune((int)testData.ScalarValue);
-            Rune runeFromCast = (Rune)(int)testData.ScalarValue;
-
-            Assert.Equal(rune, runeFromCast);
-            Assert.Equal(testData.ScalarValue, rune.Value);
-            Assert.Equal(testData.IsAscii, rune.IsAscii);
-            Assert.Equal(testData.IsBmp, rune.IsBmp);
-            Assert.Equal(testData.Plane, rune.Plane);
-        }
-
-        [Theory]
-        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
-        [MemberData(nameof(SupplementaryCodePoints_InvalidOnly))]
-        public static void Ctor_Cast_Int32_Invalid_Throws(int value)
-        {
-            Assert.Throws<ArgumentOutOfRangeException>(nameof(value), () => new Rune(value));
-            Assert.Throws<ArgumentOutOfRangeException>(nameof(value), () => (Rune)value);
-        }
-
-        [Theory]
-        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
-        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
-        public static void Ctor_Cast_UInt32_Valid(GeneralTestData testData)
-        {
-            Rune rune = new Rune((uint)testData.ScalarValue);
-            Rune runeFromCast = (Rune)(uint)testData.ScalarValue;
-
-            Assert.Equal(rune, runeFromCast);
-            Assert.Equal(testData.ScalarValue, rune.Value);
-            Assert.Equal(testData.IsAscii, rune.IsAscii);
-            Assert.Equal(testData.IsBmp, rune.IsBmp);
-            Assert.Equal(testData.Plane, rune.Plane);
-        }
-
-        [Theory]
-        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
-        [MemberData(nameof(SupplementaryCodePoints_InvalidOnly))]
-        public static void Ctor_Cast_UInt32_Invalid_Throws(int value)
-        {
-            Assert.Throws<ArgumentOutOfRangeException>(nameof(value), () => new Rune((uint)value));
-            Assert.Throws<ArgumentOutOfRangeException>(nameof(value), () => (Rune)(uint)value);
-        }
-
-        [Theory]
-        [MemberData(nameof(SurrogatePairTestData_ValidOnly))]
-        public static void Ctor_SurrogatePair_Valid(char highSurrogate, char lowSurrogate, int expectedValue)
-        {
-            Assert.Equal(expectedValue, new Rune(highSurrogate, lowSurrogate).Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(SurrogatePairTestData_InvalidOnly))]
-        public static void Ctor_SurrogatePair_Valid(char highSurrogate, char lowSurrogate)
-        {
-            string expectedParamName = !char.IsHighSurrogate(highSurrogate) ? nameof(highSurrogate) : nameof(lowSurrogate);
-            Assert.Throws<ArgumentOutOfRangeException>(expectedParamName, () => new Rune(highSurrogate, lowSurrogate));
-        }
-
-        [Theory]
-        [InlineData('A', 'a', -1)]
-        [InlineData('A', 'A', 0)]
-        [InlineData('a', 'A', 1)]
-        [InlineData(0x10000, 0x10000, 0)]
-        [InlineData('\uFFFD', 0x10000, -1)]
-        [InlineData(0x10FFFF, 0x10000, 1)]
-        public static void CompareTo_And_ComparisonOperators(int first, int other, int expectedSign)
-        {
-            Rune a = new Rune(first);
-            Rune b = new Rune(other);
-
-            Assert.Equal(expectedSign, Math.Sign(a.CompareTo(b)));
-            Assert.Equal(expectedSign < 0, a < b);
-            Assert.Equal(expectedSign <= 0, a <= b);
-            Assert.Equal(expectedSign > 0, a > b);
-            Assert.Equal(expectedSign >= 0, a >= b);
-        }
-
-        [Theory]
-        [InlineData(new char[0], OperationStatus.NeedMoreData, 0xFFFD, 0)] // empty buffer
-        [InlineData(new char[] { '\u1234' }, OperationStatus.Done, 0x1234, 1)] // BMP char
-        [InlineData(new char[] { '\u1234', '\ud800' }, OperationStatus.Done, 0x1234, 1)] // BMP char
-        [InlineData(new char[] { '\ud83d', '\ude32' }, OperationStatus.Done, 0x1F632, 2)] // supplementary value (U+1F632 ASTONISHED FACE)
-        [InlineData(new char[] { '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
-        [InlineData(new char[] { '\udc00', '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
-        [InlineData(new char[] { '\ud800' }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // high surrogate at end of buffer
-        [InlineData(new char[] { '\ud800', '\ud800' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone high surrogate
-        [InlineData(new char[] { '\ud800', '\u1234' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone high surrogate
-        public static void DecodeFromUtf16(char[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedCharsConsumed)
-        {
-            Assert.Equal(expectedOperationStatus, Rune.DecodeFromUtf16(data, out Rune actualRune, out int actualCharsConsumed));
-            Assert.Equal(expectedRuneValue, actualRune.Value);
-            Assert.Equal(expectedCharsConsumed, actualCharsConsumed);
-        }
-
-        [Theory]
-        [InlineData(new char[0], OperationStatus.NeedMoreData, 0xFFFD, 0)] // empty buffer
-        [InlineData(new char[] { '\u1234', '\u5678' }, OperationStatus.Done, 0x5678, 1)] // BMP char
-        [InlineData(new char[] { '\udc00', '\ud800' }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // high surrogate at end of buffer
-        [InlineData(new char[] { '\ud83d', '\ude32' }, OperationStatus.Done, 0x1F632, 2)] // supplementary value (U+1F632 ASTONISHED FACE)
-        [InlineData(new char[] { '\u1234', '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
-        [InlineData(new char[] { '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
-        public static void DecodeLastFromUtf16(char[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedCharsConsumed)
-        {
-            Assert.Equal(expectedOperationStatus, Rune.DecodeLastFromUtf16(data, out Rune actualRune, out int actualCharsConsumed));
-            Assert.Equal(expectedRuneValue, actualRune.Value);
-            Assert.Equal(expectedCharsConsumed, actualCharsConsumed);
-        }
-
-        [Theory]
-        [InlineData(new byte[0], OperationStatus.NeedMoreData, 0xFFFD, 0)] // empty buffer
-        [InlineData(new byte[] { 0x30 }, OperationStatus.Done, 0x0030, 1)] // ASCII byte
-        [InlineData(new byte[] { 0x30, 0x40, 0x50 }, OperationStatus.Done, 0x0030, 1)] // ASCII byte
-        [InlineData(new byte[] { 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
-        [InlineData(new byte[] { 0x80, 0x80, 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
-        [InlineData(new byte[] { 0xC1 }, OperationStatus.InvalidData, 0xFFFD, 1)] // C1 is never a valid UTF-8 byte
-        [InlineData(new byte[] { 0xF5 }, OperationStatus.InvalidData, 0xFFFD, 1)] // F5 is never a valid UTF-8 byte
-        [InlineData(new byte[] { 0xC2 }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // C2 is a valid byte; expecting it to be followed by a continuation byte
-        [InlineData(new byte[] { 0xED }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // ED is a valid byte; expecting it to be followed by a continuation byte
-        [InlineData(new byte[] { 0xF4 }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // F4 is a valid byte; expecting it to be followed by a continuation byte
-        [InlineData(new byte[] { 0xC2, 0xC2 }, OperationStatus.InvalidData, 0xFFFD, 1)] // C2 not followed by continuation byte
-        [InlineData(new byte[] { 0xC3, 0x90 }, OperationStatus.Done, 0x00D0, 2)] // [ C3 90 ] is U+00D0 LATIN CAPITAL LETTER ETH
-        [InlineData(new byte[] { 0xC1, 0xBF }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ C1 BF ] is overlong 2-byte sequence, all overlong sequences have maximal invalid subsequence length 1
-        [InlineData(new byte[] { 0xE0, 0x9F }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ E0 9F ] is overlong 3-byte sequence, all overlong sequences have maximal invalid subsequence length 1
-        [InlineData(new byte[] { 0xE0, 0xA0 }, OperationStatus.NeedMoreData, 0xFFFD, 2)] // [ E0 A0 ] is valid 2-byte start of 3-byte sequence
-        [InlineData(new byte[] { 0xED, 0x9F }, OperationStatus.NeedMoreData, 0xFFFD, 2)] // [ ED 9F ] is valid 2-byte start of 3-byte sequence
-        [InlineData(new byte[] { 0xED, 0xBF }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ ED BF ] would place us in UTF-16 surrogate range, all surrogate sequences have maximal invalid subsequence length 1
-        [InlineData(new byte[] { 0xEE, 0x80 }, OperationStatus.NeedMoreData, 0xFFFD, 2)] // [ EE 80 ] is valid 2-byte start of 3-byte sequence
-        [InlineData(new byte[] { 0xF0, 0x8F }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ F0 8F ] is overlong 4-byte sequence, all overlong sequences have maximal invalid subsequence length 1
-        [InlineData(new byte[] { 0xF0, 0x90 }, OperationStatus.NeedMoreData, 0xFFFD, 2)] // [ F0 90 ] is valid 2-byte start of 4-byte sequence
-        [InlineData(new byte[] { 0xF4, 0x90 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ F4 90 ] would place us beyond U+10FFFF, all such sequences have maximal invalid subsequence length 1
-        [InlineData(new byte[] { 0xE2, 0x88, 0xB4 }, OperationStatus.Done, 0x2234, 3)] // [ E2 88 B4 ] is U+2234 THEREFORE
-        [InlineData(new byte[] { 0xE2, 0x88, 0xC0 }, OperationStatus.InvalidData, 0xFFFD, 2)] // [ E2 88 ] followed by non-continuation byte, maximal invalid subsequence length 2
-        [InlineData(new byte[] { 0xF0, 0x9F, 0x98 }, OperationStatus.NeedMoreData, 0xFFFD, 3)] // [ F0 9F 98 ] is valid 3-byte start of 4-byte sequence
-        [InlineData(new byte[] { 0xF0, 0x9F, 0x98, 0x20 }, OperationStatus.InvalidData, 0xFFFD, 3)] // [ F0 9F 98 ] followed by non-continuation byte, maximal invalid subsequence length 3
-        [InlineData(new byte[] { 0xF0, 0x9F, 0x98, 0xB2 }, OperationStatus.Done, 0x1F632, 4)] // [ F0 9F 98 B2 ] is U+1F632 ASTONISHED FACE
-        public static void DecodeFromUtf8(byte[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedBytesConsumed)
-        {
-            Assert.Equal(expectedOperationStatus, Rune.DecodeFromUtf8(data, out Rune actualRune, out int actualBytesConsumed));
-            Assert.Equal(expectedRuneValue, actualRune.Value);
-            Assert.Equal(expectedBytesConsumed, actualBytesConsumed);
-        }
-
-        [Theory]
-        [InlineData(new byte[0], OperationStatus.NeedMoreData, 0xFFFD, 0)] // empty buffer
-        [InlineData(new byte[] { 0x30 }, OperationStatus.Done, 0x0030, 1)] // ASCII byte
-        [InlineData(new byte[] { 0x30, 0x40, 0x50 }, OperationStatus.Done, 0x0050, 1)] // ASCII byte
-        [InlineData(new byte[] { 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
-        [InlineData(new byte[] { 0x80, 0x80, 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
-        [InlineData(new byte[] { 0x80, 0x80, 0x80, 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone continuation byte
-        [InlineData(new byte[] { 0x80, 0x80, 0x80, 0xC2 }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // [ C2 ] at end of buffer, valid 1-byte start of 2-byte sequence
-        [InlineData(new byte[] { 0xC1 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ C1 ] is never a valid byte
-        [InlineData(new byte[] { 0x80, 0xE2, 0x88, 0xB4 }, OperationStatus.Done, 0x2234, 3)] // [ E2 88 B4 ] is U+2234 THEREFORE
-        [InlineData(new byte[] { 0xF0, 0x9F, 0x98, 0xB2 }, OperationStatus.Done, 0x1F632, 4)] // [ F0 9F 98 B2 ] is U+1F632 ASTONISHED FACE
-        [InlineData(new byte[] { 0xE2, 0x88, 0xB4, 0xB2 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ B2 ] is standalone continuation byte
-        [InlineData(new byte[] { 0x80, 0x62, 0x80, 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ 80 ] is standalone continuation byte
-        [InlineData(new byte[] { 0xF0, 0x9F, 0x98, }, OperationStatus.NeedMoreData, 0xFFFD, 3)] // [ F0 9F 98 ] is valid 3-byte start of 4-byte sequence
-        public static void DecodeLastFromUtf8(byte[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedBytesConsumed)
-        {
-            Assert.Equal(expectedOperationStatus, Rune.DecodeLastFromUtf8(data, out Rune actualRune, out int actualBytesConsumed));
-            Assert.Equal(expectedRuneValue, actualRune.Value);
-            Assert.Equal(expectedBytesConsumed, actualBytesConsumed);
-        }
-
-        [Theory]
-        [InlineData(0, 0, true)]
-        [InlineData(0x10FFFF, 0x10FFFF, true)]
-        [InlineData(0xFFFD, 0xFFFD, true)]
-        [InlineData(0xFFFD, 0xFFFF, false)]
-        [InlineData('a', 'a', true)]
-        [InlineData('a', 'A', false)]
-        [InlineData('a', 'b', false)]
-        public static void Equals_OperatorEqual_OperatorNotEqual(int first, int other, bool expected)
-        {
-            Rune a = new Rune(first);
-            Rune b = new Rune(other);
-
-            Assert.Equal(expected, Object.Equals(a, b));
-            Assert.Equal(expected, a.Equals(b));
-            Assert.Equal(expected, a.Equals((object)b));
-            Assert.Equal(expected, a == b);
-            Assert.NotEqual(expected, a != b);
-        }
-
-        [Theory]
-        [InlineData(0)]
-        [InlineData('a')]
-        [InlineData('\uFFFD')]
-        [InlineData(0x10FFFF)]
-        public static void GetHashCodeTests(int scalarValue)
-        {
-            Assert.Equal(scalarValue, new Rune(scalarValue).GetHashCode());
-        }
-
-        [Theory]
-        [InlineData("a", 0, (int)'a')]
-        [InlineData("ab", 1, (int)'b')]
-        [InlineData("x\U0001F46Ey", 3, (int)'y')]
-        [InlineData("x\U0001F46Ey", 1, 0x1F46E)] // U+1F46E POLICE OFFICER
-        public static void GetRuneAt_TryGetRuneAt_Utf16_Success(string inputString, int index, int expectedScalarValue)
-        {
-            // GetRuneAt
-            Assert.Equal(expectedScalarValue, Rune.GetRuneAt(inputString, index).Value);
-
-            // TryGetRuneAt
-            Assert.True(Rune.TryGetRuneAt(inputString, index, out Rune rune));
-            Assert.Equal(expectedScalarValue, rune.Value);
-        }
-
-        // Our unit test runner doesn't deal well with malformed literal strings, so
-        // we smuggle it as a char[] and turn it into a string within the test itself.
-        [Theory]
-        [InlineData(new char[] { 'x', '\uD83D', '\uDC6E', 'y' }, 2)] // attempt to index into the middle of a UTF-16 surrogate pair
-        [InlineData(new char[] { 'x', '\uD800', 'y' }, 1)] // high surrogate not followed by low surrogate
-        [InlineData(new char[] { 'x', '\uDFFF', '\uDFFF' }, 1)] // attempt to start at a low surrogate
-        [InlineData(new char[] { 'x', '\uD800' }, 1)] // end of string reached before could complete surrogate pair
-        public static void GetRuneAt_TryGetRuneAt_Utf16_InvalidData(char[] inputCharArray, int index)
-        {
-            string inputString = new string(inputCharArray);
-
-            // GetRuneAt
-            Assert.Throws<ArgumentException>("index", () => Rune.GetRuneAt(inputString, index));
-
-            // TryGetRuneAt
-            Assert.False(Rune.TryGetRuneAt(inputString, index, out Rune rune));
-            Assert.Equal(0, rune.Value);
-        }
-
-        [Fact]
-        public static void GetRuneAt_TryGetRuneAt_Utf16_BadArgs()
-        {
-            // null input
-            Assert.Throws<ArgumentNullException>("input", () => Rune.GetRuneAt(null, 0));
-
-            // negative index specified
-            Assert.Throws<ArgumentOutOfRangeException>("index", () => Rune.GetRuneAt("hello", -1));
-
-            // index goes past end of string
-            Assert.Throws<ArgumentOutOfRangeException>("index", () => Rune.GetRuneAt(string.Empty, 0));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void GetNumericValue(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.NumericValue, Rune.GetNumericValue(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void GetUnicodeCategory(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.UnicodeCategory, Rune.GetUnicodeCategory(testData.ScalarValue));
-        }
-
-        [OuterLoop]
-        [Fact]
-        public static void GetUnicodeCategory_AllInputs()
-        {
-            // This tests calls Rune.GetUnicodeCategory for every possible input, ensuring that
-            // the runtime agrees with the data in the core Unicode files.
-
-            foreach (Rune rune in AllRunes())
-            {
-                if (UnicodeData.GetUnicodeCategory((uint)rune.Value) != Rune.GetUnicodeCategory(rune))
-                {
-                    // We'll build up the exception message ourselves so the dev knows what code point failed.
-                    throw new AssertActualExpectedException(
-                        expected: UnicodeData.GetUnicodeCategory((uint)rune.Value),
-                        actual: Rune.GetUnicodeCategory(rune),
-                        userMessage: FormattableString.Invariant($@"Rune.GetUnicodeCategory(U+{rune.Value:X4}) returned wrong value."));
-                }
-            }
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsControl(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsControl, Rune.IsControl(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsDigit(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsDigit, Rune.IsDigit(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsLetter(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsLetter, Rune.IsLetter(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsLetterOrDigit(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsLetterOrDigit, Rune.IsLetterOrDigit(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsLower(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsLower, Rune.IsLower(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsNumber(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsNumber, Rune.IsNumber(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsPunctuation(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsPunctuation, Rune.IsPunctuation(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsSeparator(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsSeparator, Rune.IsSeparator(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsSymbol(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsSymbol, Rune.IsSymbol(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsUpper(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsUpper, Rune.IsUpper(testData.ScalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(IsValidTestData))]
-        public static void IsValid(int scalarValue, bool expectedIsValid)
-        {
-            Assert.Equal(expectedIsValid, Rune.IsValid(scalarValue));
-            Assert.Equal(expectedIsValid, Rune.IsValid((uint)scalarValue));
-        }
-
-        [Theory]
-        [MemberData(nameof(UnicodeInfoTestData_Latin1AndSelectOthers))]
-        public static void IsWhiteSpace(UnicodeInfoTestData testData)
-        {
-            Assert.Equal(testData.IsWhiteSpace, Rune.IsWhiteSpace(testData.ScalarValue));
-        }
-
-        [OuterLoop]
-        [Fact]
-        public static void IsWhiteSpace_AllInputs()
-        {
-            // This tests calls Rune.IsWhiteSpace for every possible input, ensuring that
-            // the runtime agrees with the data in the core Unicode files.
-
-            foreach (Rune rune in AllRunes())
-            {
-                Assert.Equal(UnicodeData.IsWhiteSpace((uint)rune.Value), Rune.IsWhiteSpace(rune));
-            }
-        }
-
-        [Theory]
-        [InlineData(0, 0)]
-        [InlineData(0x80, 0x80)]
-        [InlineData(0x80, 0x100)]
-        [InlineData(0x100, 0x80)]
-        public static void Operators_And_CompareTo(uint scalarValueLeft, uint scalarValueRight)
-        {
-            Rune left = new Rune(scalarValueLeft);
-            Rune right = new Rune(scalarValueRight);
-
-            Assert.Equal(scalarValueLeft == scalarValueRight, left == right);
-            Assert.Equal(scalarValueLeft != scalarValueRight, left != right);
-            Assert.Equal(scalarValueLeft < scalarValueRight, left < right);
-            Assert.Equal(scalarValueLeft <= scalarValueRight, left <= right);
-            Assert.Equal(scalarValueLeft > scalarValueRight, left > right);
-            Assert.Equal(scalarValueLeft >= scalarValueRight, left >= right);
-            Assert.Equal(scalarValueLeft.CompareTo(scalarValueRight), left.CompareTo(right));
-        }
-
-        [Fact]
-        public static void ReplacementChar()
-        {
-            Assert.Equal(0xFFFD, Rune.ReplacementChar.Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
-        public static void TryCreate_Char_Valid(GeneralTestData testData)
-        {
-            Assert.True(Rune.TryCreate((char)testData.ScalarValue, out Rune result));
-            Assert.Equal(testData.ScalarValue, result.Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
-        public static void TryCreate_Char_Invalid(int scalarValue)
-        {
-            Assert.False(Rune.TryCreate((char)scalarValue, out Rune result));
-            Assert.Equal(0, result.Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(SurrogatePairTestData_InvalidOnly))]
-        public static void TryCreate_SurrogateChars_Invalid(char highSurrogate, char lowSurrogate)
-        {
-            Assert.False(Rune.TryCreate(highSurrogate, lowSurrogate, out Rune result));
-            Assert.Equal(0, result.Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(SurrogatePairTestData_ValidOnly))]
-        public static void TryCreate_SurrogateChars_Valid(char highSurrogate, char lowSurrogate, int expectedValue)
-        {
-            Assert.True(Rune.TryCreate(highSurrogate, lowSurrogate, out Rune result));
-            Assert.Equal(expectedValue, result.Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
-        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
-        public static void TryCreate_Int32_Valid(GeneralTestData testData)
-        {
-            Assert.True(Rune.TryCreate((int)testData.ScalarValue, out Rune result));
-            Assert.Equal(testData.ScalarValue, result.Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
-        [MemberData(nameof(SupplementaryCodePoints_InvalidOnly))]
-        public static void TryCreate_Int32_Invalid(int scalarValue)
-        {
-            Assert.False(Rune.TryCreate((int)scalarValue, out Rune result));
-            Assert.Equal(0, result.Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
-        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
-        public static void TryCreate_UInt32_Valid(GeneralTestData testData)
-        {
-            Assert.True(Rune.TryCreate((uint)testData.ScalarValue, out Rune result));
-            Assert.Equal(testData.ScalarValue, result.Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(BmpCodePoints_SurrogatesOnly))]
-        [MemberData(nameof(SupplementaryCodePoints_InvalidOnly))]
-        public static void TryCreate_UInt32_Invalid(int scalarValue)
-        {
-            Assert.False(Rune.TryCreate((uint)scalarValue, out Rune result));
-            Assert.Equal(0, result.Value);
-        }
-
-        [Theory]
-        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
-        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
-        public static void ToStringTests(GeneralTestData testData)
-        {
-            Assert.Equal(new string(testData.Utf16Sequence), new Rune(testData.ScalarValue).ToString());
-        }
-
-        [Theory]
-        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
-        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
-        public static void TryEncodeToUtf16(GeneralTestData testData)
-        {
-            Rune rune = new Rune(testData.ScalarValue);
-            Assert.Equal(testData.Utf16Sequence.Length, rune.Utf16SequenceLength);
-
-            // First, try with a buffer that's too short
-
-            Span<char> utf16Buffer = stackalloc char[rune.Utf16SequenceLength - 1];
-            bool success = rune.TryEncodeToUtf16(utf16Buffer, out int charsWritten);
-            Assert.False(success);
-            Assert.Equal(0, charsWritten);
-
-            Assert.Throws<ArgumentException>("destination", () => rune.EncodeToUtf16(new char[rune.Utf16SequenceLength - 1]));
-
-            // Then, try with a buffer that's appropriately sized
-
-            utf16Buffer = stackalloc char[rune.Utf16SequenceLength];
-            success = rune.TryEncodeToUtf16(utf16Buffer, out charsWritten);
-            Assert.True(success);
-            Assert.Equal(testData.Utf16Sequence.Length, charsWritten);
-            Assert.True(utf16Buffer.SequenceEqual(testData.Utf16Sequence));
-
-            utf16Buffer.Clear();
-            Assert.Equal(testData.Utf16Sequence.Length, rune.EncodeToUtf16(utf16Buffer));
-            Assert.True(utf16Buffer.SequenceEqual(testData.Utf16Sequence));
-
-            // Finally, try with a buffer that's too long (should succeed)
-
-            utf16Buffer = stackalloc char[rune.Utf16SequenceLength + 1];
-            success = rune.TryEncodeToUtf16(utf16Buffer, out charsWritten);
-            Assert.True(success);
-            Assert.Equal(testData.Utf16Sequence.Length, charsWritten);
-            Assert.True(utf16Buffer.Slice(0, testData.Utf16Sequence.Length).SequenceEqual(testData.Utf16Sequence));
-
-            utf16Buffer.Clear();
-            Assert.Equal(testData.Utf16Sequence.Length, rune.EncodeToUtf16(utf16Buffer));
-            Assert.True(utf16Buffer.Slice(0, testData.Utf16Sequence.Length).SequenceEqual(testData.Utf16Sequence));
-        }
-
-        [Theory]
-        [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
-        [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
-        public static void TryEncodeToUtf8(GeneralTestData testData)
-        {
-            Rune rune = new Rune(testData.ScalarValue);
-            Assert.Equal(testData.Utf8Sequence.Length, actual: rune.Utf8SequenceLength);
-
-            // First, try with a buffer that's too short
-
-            Span<byte> utf8Buffer = stackalloc byte[rune.Utf8SequenceLength - 1];
-            bool success = rune.TryEncodeToUtf8(utf8Buffer, out int bytesWritten);
-            Assert.False(success);
-            Assert.Equal(0, bytesWritten);
-
-            Assert.Throws<ArgumentException>("destination", () => rune.EncodeToUtf8(new byte[rune.Utf8SequenceLength - 1]));
-
-            // Then, try with a buffer that's appropriately sized
-
-            utf8Buffer = stackalloc byte[rune.Utf8SequenceLength];
-            success = rune.TryEncodeToUtf8(utf8Buffer, out bytesWritten);
-            Assert.True(success);
-            Assert.Equal(testData.Utf8Sequence.Length, bytesWritten);
-            Assert.True(utf8Buffer.SequenceEqual(testData.Utf8Sequence));
-
-            utf8Buffer.Clear();
-            Assert.Equal(testData.Utf8Sequence.Length, rune.EncodeToUtf8(utf8Buffer));
-            Assert.True(utf8Buffer.SequenceEqual(testData.Utf8Sequence));
-
-            // Finally, try with a buffer that's too long (should succeed)
-
-            utf8Buffer = stackalloc byte[rune.Utf8SequenceLength + 1];
-            success = rune.TryEncodeToUtf8(utf8Buffer, out bytesWritten);
-            Assert.True(success);
-            Assert.Equal(testData.Utf8Sequence.Length, bytesWritten);
-            Assert.True(utf8Buffer.Slice(0, testData.Utf8Sequence.Length).SequenceEqual(testData.Utf8Sequence));
-
-            utf8Buffer.Clear();
-            Assert.Equal(testData.Utf8Sequence.Length, rune.EncodeToUtf8(utf8Buffer));
-            Assert.True(utf8Buffer.Slice(0, testData.Utf8Sequence.Length).SequenceEqual(testData.Utf8Sequence));
-        }
-    }
-}
index d6d9388f6fe0d5ea9da98ea4f4b31f3e748357d9..7862302388d9e9fa4b8349dea554e0f652981ac1 100644 (file)
@@ -5,6 +5,7 @@
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Globalization;
+using System.Linq;
 using System.Tests;
 using Microsoft.DotNet.RemoteExecutor;
 using Xunit;
@@ -1782,5 +1783,453 @@ namespace System.Text.Tests
             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));
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/Text/StringBuilderTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/StringBuilderTests.netcoreapp.cs
deleted file mode 100644 (file)
index e854c3c..0000000
+++ /dev/null
@@ -1,462 +0,0 @@
-// 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));
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/UnicodeData.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/UnicodeData.cs
new file mode 100644 (file)
index 0000000..df9201c
--- /dev/null
@@ -0,0 +1,297 @@
+// 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 System.IO;
+using System.Text.RegularExpressions;
+using Xunit;
+using Xunit.Sdk;
+
+namespace System.Text.Unicode.Tests
+{
+    /*
+     * This file contains helpers for parsing the Unicode data files, which we can then use to test
+     * our Framework's implementations of various character & text processing routines.
+     */
+
+    public static class UnicodeData
+    {
+        private const string UnicodeDataFilename = "UnicodeData.11.0.txt";
+        private const string CaseFoldingFilename = "CaseFolding-12.1.0.txt";
+        private const string PropListFilename = "PropList-12.1.0.txt";
+
+        private static readonly Dictionary<string, UnicodeCategory> _categoryCodeMap = new Dictionary<string, UnicodeCategory>()
+        {
+            { "Lu", UnicodeCategory.UppercaseLetter },
+            { "Ll", UnicodeCategory.LowercaseLetter },
+            { "Lt", UnicodeCategory.TitlecaseLetter },
+            { "Lm", UnicodeCategory.ModifierLetter },
+            { "Lo", UnicodeCategory.OtherLetter },
+            { "Mn", UnicodeCategory.NonSpacingMark },
+            { "Mc", UnicodeCategory.SpacingCombiningMark },
+            { "Me", UnicodeCategory.EnclosingMark },
+            { "Nd", UnicodeCategory.DecimalDigitNumber },
+            { "Nl", UnicodeCategory.LetterNumber },
+            { "No", UnicodeCategory.OtherNumber },
+            { "Pc", UnicodeCategory.ConnectorPunctuation },
+            { "Pd", UnicodeCategory.DashPunctuation },
+            { "Ps", UnicodeCategory.OpenPunctuation },
+            { "Pe", UnicodeCategory.ClosePunctuation },
+            { "Pi", UnicodeCategory.InitialQuotePunctuation },
+            { "Pf", UnicodeCategory.FinalQuotePunctuation },
+            { "Po", UnicodeCategory.OtherPunctuation },
+            { "Sm", UnicodeCategory.MathSymbol },
+            { "Sc", UnicodeCategory.CurrencySymbol },
+            { "Sk", UnicodeCategory.ModifierSymbol },
+            { "So", UnicodeCategory.OtherSymbol },
+            { "Zs", UnicodeCategory.SpaceSeparator },
+            { "Zl", UnicodeCategory.LineSeparator },
+            { "Zp", UnicodeCategory.ParagraphSeparator },
+            { "Cc", UnicodeCategory.Control },
+            { "Cf", UnicodeCategory.Format },
+            { "Cs", UnicodeCategory.Surrogate },
+            { "Co", UnicodeCategory.PrivateUse },
+        };
+
+        private static readonly Dictionary<uint, UnicodeCategory> _categoryMap = new Dictionary<uint, UnicodeCategory>();
+        private static readonly Dictionary<uint, CharProperty> _propertyMap = new Dictionary<uint, CharProperty>();
+        private static readonly Dictionary<uint, uint> _simpleCaseFoldMap = new Dictionary<uint, uint>();
+        private static readonly Dictionary<uint, uint> _simpleLowerCaseMap = new Dictionary<uint, uint>();
+        private static readonly Dictionary<uint, uint> _simpleTitleCaseMap = new Dictionary<uint, uint>();
+        private static readonly Dictionary<uint, uint> _simpleUpperCaseMap = new Dictionary<uint, uint>();
+
+        static UnicodeData()
+        {
+            static IEnumerable<string> ReadAllLines(string resourceName)
+            {
+                using (Stream stream = typeof(UnicodeData).Assembly.GetManifestResourceStream(resourceName))
+                {
+                    if (stream is null)
+                    {
+                        throw new XunitException($"Could not locate resource stream {resourceName} in the assembly.");
+                    }
+
+                    List<string> allLines = new List<string>();
+
+                    using (StreamReader reader = new StreamReader(stream))
+                    {
+                        string nextLine;
+                        while ((nextLine = reader.ReadLine()) != null)
+                        {
+                            yield return nextLine;
+                        }
+                    }
+                }
+            }
+
+            // First, read the basic category, bidi data, and simple upper / lower / title mappings from UnicodeData.txt
+            // File format is documented at https://www.unicode.org/reports/tr44/#UnicodeData.txt
+
+            string nameOfCurrentRange = null;
+            uint startOfCurrentRange = 0;
+
+            foreach (string line in ReadAllLines(UnicodeDataFilename))
+            {
+                string[] splitLine = line.Split(';');
+                Assert.Equal(15, splitLine.Length); // expected 15 segments resulting from the split
+
+                uint currentCodePoint = uint.Parse(splitLine[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+                string codePointName = splitLine[1];
+                string category = splitLine[2];
+
+                // Is this the start of a range?
+                // If so, save this data and keep iterating.
+
+                if (codePointName.EndsWith(", First>", StringComparison.Ordinal))
+                {
+                    startOfCurrentRange = currentCodePoint;
+                    nameOfCurrentRange = codePointName[..^(", First>".Length)];
+                    continue;
+                }
+
+                // If we didn't see a <..., First> range immediately before
+                // this, assume it's a range of length 1.
+
+                if (codePointName != nameOfCurrentRange + ", Last>")
+                {
+                    startOfCurrentRange = currentCodePoint;
+                }
+
+                uint.TryParse(splitLine[12], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint simpleUpperMapping);
+                uint.TryParse(splitLine[13], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint simpleLowerMapping);
+                uint.TryParse(splitLine[14], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint simpleTitleMapping);
+
+                for (uint i = startOfCurrentRange; i <= currentCodePoint; i++)
+                {
+                    _categoryMap[i] = _categoryCodeMap[category];
+
+                    if (simpleLowerMapping != 0)
+                    {
+                        _simpleLowerCaseMap[i] = simpleLowerMapping;
+                    }
+
+                    if (simpleUpperMapping != 0)
+                    {
+                        _simpleUpperCaseMap[i] = simpleUpperMapping;
+                    }
+
+                    if (simpleTitleMapping != 0)
+                    {
+                        _simpleTitleCaseMap[i] = simpleTitleMapping;
+                    }
+                }
+            }
+
+            // Then, read the property map from PropList.txt.
+            // We're looking for lines of the form "XXXX[..YYYY] ; <prop> # <comment>"
+
+            Regex propListRegex = new Regex(@"^\s*(?<firstCodePoint>[0-9A-F]{4,})(\.\.(?<lastCodePoint>[0-9A-F]{4,}))?\s*;\s*(?<propName>\w+)\s*#", RegexOptions.IgnoreCase);
+
+            foreach (string line in ReadAllLines(PropListFilename))
+            {
+                Match match = propListRegex.Match(line);
+                if (!match.Success)
+                {
+                    continue; // line was blank or was comment-only
+                }
+
+                uint firstCodePoint = uint.Parse(match.Groups["firstCodePoint"].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+                if (!uint.TryParse(match.Groups["lastCodePoint"].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint lastCodePoint))
+                {
+                    lastCodePoint = firstCodePoint; // If not "XXXX..YYYY", assume "XXXX..XXXX"
+                }
+                CharProperty property = Enum.Parse<CharProperty>(match.Groups["propName"].Value);
+
+                for (uint i = firstCodePoint; i <= lastCodePoint; i++)
+                {
+                    _propertyMap.TryGetValue(i, out CharProperty existingValue);
+                    _propertyMap[i] = existingValue | property; // remember, this is flags
+                }
+            }
+
+            // Finally, read the case fold map from CaseFolding.txt.
+            // We're looking for lines of the form "<code>; <status>; <mapping>; # <name>", where <status> is 'C' or 'S'
+
+            Regex caseFoldRegex = new Regex(@"^\s*(?<fromCodePoint>[0-9A-F]{4,}); [CS]; (?<toCodePoint>[0-9A-F]{4,});", RegexOptions.IgnoreCase);
+
+            foreach (string line in ReadAllLines(CaseFoldingFilename))
+            {
+                Match match = caseFoldRegex.Match(line);
+                if (!match.Success)
+                {
+                    continue; // line was blank, comment-only, or not simple / common
+                }
+
+                uint fromCodePoint = uint.Parse(match.Groups["fromCodePoint"].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+                uint toCodePoint = uint.Parse(match.Groups["toCodePoint"].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+
+                _simpleCaseFoldMap[fromCodePoint] = toCodePoint;
+            }
+        }
+
+        public static UnicodeCategory GetUnicodeCategory(uint codePoint)
+        {
+            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
+
+            return _categoryMap.TryGetValue(codePoint, out UnicodeCategory category) ? category : UnicodeCategory.OtherNotAssigned;
+        }
+
+        public static bool IsLetter(uint codePoint)
+        {
+            switch (GetUnicodeCategory(codePoint))
+            {
+                case UnicodeCategory.UppercaseLetter:
+                case UnicodeCategory.LowercaseLetter:
+                case UnicodeCategory.TitlecaseLetter:
+                case UnicodeCategory.ModifierLetter:
+                case UnicodeCategory.OtherLetter:
+                    return true;
+
+                default:
+                    return false;
+            }
+        }
+
+        // Returns true iff code point is listed at https://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:whitespace:]
+        public static bool IsWhiteSpace(uint codePoint)
+        {
+            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
+
+            _propertyMap.TryGetValue(codePoint, out CharProperty property);
+            return property.HasFlag(CharProperty.White_Space);
+        }
+
+        public static uint SimpleFoldCaseMap(uint codePoint)
+        {
+            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
+
+            // If an entry doesn't exist, the value maps to itself.
+            return _simpleCaseFoldMap.TryGetValue(codePoint, out uint value) ? value : codePoint;
+        }
+
+        public static uint SimpleLowerCaseMap(uint codePoint)
+        {
+            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
+
+            // If an entry doesn't exist, the value maps to itself.
+            return _simpleLowerCaseMap.TryGetValue(codePoint, out uint value) ? value : codePoint;
+        }
+
+        public static uint SimpleTitleCaseMap(uint codePoint)
+        {
+            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
+
+            // If an entry doesn't exist, the value maps to itself.
+            return _simpleTitleCaseMap.TryGetValue(codePoint, out uint value) ? value : codePoint;
+        }
+
+        public static uint SimpleUpperCaseMap(uint codePoint)
+        {
+            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
+
+            // If an entry doesn't exist, the value maps to itself.
+            return _simpleUpperCaseMap.TryGetValue(codePoint, out uint value) ? value : codePoint;
+        }
+
+        [Flags]
+        private enum CharProperty : ulong
+        {
+            ASCII_Hex_Digit = 1ul << 0,
+            Bidi_Control = 1ul << 1,
+            Dash = 1ul << 2,
+            Deprecated = 1ul << 3,
+            Diacritic = 1ul << 4,
+            Extender = 1ul << 5,
+            Hex_Digit = 1ul << 6,
+            Hyphen = 1ul << 7,
+            Ideographic = 1ul << 8,
+            IDS_Binary_Operator = 1ul << 9,
+            IDS_Trinary_Operator = 1ul << 10,
+            Join_Control = 1ul << 11,
+            Logical_Order_Exception = 1ul << 12,
+            Noncharacter_Code_Point = 1ul << 13,
+            Other_Alphabetic = 1ul << 14,
+            Other_Default_Ignorable_Code_Point = 1ul << 15,
+            Other_Grapheme_Extend = 1ul << 16,
+            Other_ID_Continue = 1ul << 17,
+            Other_ID_Start = 1ul << 18,
+            Other_Lowercase = 1ul << 19,
+            Other_Math = 1ul << 20,
+            Other_Uppercase = 1ul << 21,
+            Pattern_Syntax = 1ul << 22,
+            Pattern_White_Space = 1ul << 23,
+            Prepended_Concatenation_Mark = 1ul << 24,
+            Quotation_Mark = 1ul << 25,
+            Radical = 1ul << 26,
+            Regional_Indicator = 1ul << 27,
+            Sentence_Terminal = 1ul << 28,
+            Soft_Dotted = 1ul << 29,
+            Terminal_Punctuation = 1ul << 30,
+            Unified_Ideograph = 1ul << 31,
+            Variation_Selector = 1ul << 32,
+            White_Space = 1ul << 33,
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/UnicodeData.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/UnicodeData.netcoreapp.cs
deleted file mode 100644 (file)
index df9201c..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-// 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 System.IO;
-using System.Text.RegularExpressions;
-using Xunit;
-using Xunit.Sdk;
-
-namespace System.Text.Unicode.Tests
-{
-    /*
-     * This file contains helpers for parsing the Unicode data files, which we can then use to test
-     * our Framework's implementations of various character & text processing routines.
-     */
-
-    public static class UnicodeData
-    {
-        private const string UnicodeDataFilename = "UnicodeData.11.0.txt";
-        private const string CaseFoldingFilename = "CaseFolding-12.1.0.txt";
-        private const string PropListFilename = "PropList-12.1.0.txt";
-
-        private static readonly Dictionary<string, UnicodeCategory> _categoryCodeMap = new Dictionary<string, UnicodeCategory>()
-        {
-            { "Lu", UnicodeCategory.UppercaseLetter },
-            { "Ll", UnicodeCategory.LowercaseLetter },
-            { "Lt", UnicodeCategory.TitlecaseLetter },
-            { "Lm", UnicodeCategory.ModifierLetter },
-            { "Lo", UnicodeCategory.OtherLetter },
-            { "Mn", UnicodeCategory.NonSpacingMark },
-            { "Mc", UnicodeCategory.SpacingCombiningMark },
-            { "Me", UnicodeCategory.EnclosingMark },
-            { "Nd", UnicodeCategory.DecimalDigitNumber },
-            { "Nl", UnicodeCategory.LetterNumber },
-            { "No", UnicodeCategory.OtherNumber },
-            { "Pc", UnicodeCategory.ConnectorPunctuation },
-            { "Pd", UnicodeCategory.DashPunctuation },
-            { "Ps", UnicodeCategory.OpenPunctuation },
-            { "Pe", UnicodeCategory.ClosePunctuation },
-            { "Pi", UnicodeCategory.InitialQuotePunctuation },
-            { "Pf", UnicodeCategory.FinalQuotePunctuation },
-            { "Po", UnicodeCategory.OtherPunctuation },
-            { "Sm", UnicodeCategory.MathSymbol },
-            { "Sc", UnicodeCategory.CurrencySymbol },
-            { "Sk", UnicodeCategory.ModifierSymbol },
-            { "So", UnicodeCategory.OtherSymbol },
-            { "Zs", UnicodeCategory.SpaceSeparator },
-            { "Zl", UnicodeCategory.LineSeparator },
-            { "Zp", UnicodeCategory.ParagraphSeparator },
-            { "Cc", UnicodeCategory.Control },
-            { "Cf", UnicodeCategory.Format },
-            { "Cs", UnicodeCategory.Surrogate },
-            { "Co", UnicodeCategory.PrivateUse },
-        };
-
-        private static readonly Dictionary<uint, UnicodeCategory> _categoryMap = new Dictionary<uint, UnicodeCategory>();
-        private static readonly Dictionary<uint, CharProperty> _propertyMap = new Dictionary<uint, CharProperty>();
-        private static readonly Dictionary<uint, uint> _simpleCaseFoldMap = new Dictionary<uint, uint>();
-        private static readonly Dictionary<uint, uint> _simpleLowerCaseMap = new Dictionary<uint, uint>();
-        private static readonly Dictionary<uint, uint> _simpleTitleCaseMap = new Dictionary<uint, uint>();
-        private static readonly Dictionary<uint, uint> _simpleUpperCaseMap = new Dictionary<uint, uint>();
-
-        static UnicodeData()
-        {
-            static IEnumerable<string> ReadAllLines(string resourceName)
-            {
-                using (Stream stream = typeof(UnicodeData).Assembly.GetManifestResourceStream(resourceName))
-                {
-                    if (stream is null)
-                    {
-                        throw new XunitException($"Could not locate resource stream {resourceName} in the assembly.");
-                    }
-
-                    List<string> allLines = new List<string>();
-
-                    using (StreamReader reader = new StreamReader(stream))
-                    {
-                        string nextLine;
-                        while ((nextLine = reader.ReadLine()) != null)
-                        {
-                            yield return nextLine;
-                        }
-                    }
-                }
-            }
-
-            // First, read the basic category, bidi data, and simple upper / lower / title mappings from UnicodeData.txt
-            // File format is documented at https://www.unicode.org/reports/tr44/#UnicodeData.txt
-
-            string nameOfCurrentRange = null;
-            uint startOfCurrentRange = 0;
-
-            foreach (string line in ReadAllLines(UnicodeDataFilename))
-            {
-                string[] splitLine = line.Split(';');
-                Assert.Equal(15, splitLine.Length); // expected 15 segments resulting from the split
-
-                uint currentCodePoint = uint.Parse(splitLine[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture);
-                string codePointName = splitLine[1];
-                string category = splitLine[2];
-
-                // Is this the start of a range?
-                // If so, save this data and keep iterating.
-
-                if (codePointName.EndsWith(", First>", StringComparison.Ordinal))
-                {
-                    startOfCurrentRange = currentCodePoint;
-                    nameOfCurrentRange = codePointName[..^(", First>".Length)];
-                    continue;
-                }
-
-                // If we didn't see a <..., First> range immediately before
-                // this, assume it's a range of length 1.
-
-                if (codePointName != nameOfCurrentRange + ", Last>")
-                {
-                    startOfCurrentRange = currentCodePoint;
-                }
-
-                uint.TryParse(splitLine[12], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint simpleUpperMapping);
-                uint.TryParse(splitLine[13], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint simpleLowerMapping);
-                uint.TryParse(splitLine[14], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint simpleTitleMapping);
-
-                for (uint i = startOfCurrentRange; i <= currentCodePoint; i++)
-                {
-                    _categoryMap[i] = _categoryCodeMap[category];
-
-                    if (simpleLowerMapping != 0)
-                    {
-                        _simpleLowerCaseMap[i] = simpleLowerMapping;
-                    }
-
-                    if (simpleUpperMapping != 0)
-                    {
-                        _simpleUpperCaseMap[i] = simpleUpperMapping;
-                    }
-
-                    if (simpleTitleMapping != 0)
-                    {
-                        _simpleTitleCaseMap[i] = simpleTitleMapping;
-                    }
-                }
-            }
-
-            // Then, read the property map from PropList.txt.
-            // We're looking for lines of the form "XXXX[..YYYY] ; <prop> # <comment>"
-
-            Regex propListRegex = new Regex(@"^\s*(?<firstCodePoint>[0-9A-F]{4,})(\.\.(?<lastCodePoint>[0-9A-F]{4,}))?\s*;\s*(?<propName>\w+)\s*#", RegexOptions.IgnoreCase);
-
-            foreach (string line in ReadAllLines(PropListFilename))
-            {
-                Match match = propListRegex.Match(line);
-                if (!match.Success)
-                {
-                    continue; // line was blank or was comment-only
-                }
-
-                uint firstCodePoint = uint.Parse(match.Groups["firstCodePoint"].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
-                if (!uint.TryParse(match.Groups["lastCodePoint"].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint lastCodePoint))
-                {
-                    lastCodePoint = firstCodePoint; // If not "XXXX..YYYY", assume "XXXX..XXXX"
-                }
-                CharProperty property = Enum.Parse<CharProperty>(match.Groups["propName"].Value);
-
-                for (uint i = firstCodePoint; i <= lastCodePoint; i++)
-                {
-                    _propertyMap.TryGetValue(i, out CharProperty existingValue);
-                    _propertyMap[i] = existingValue | property; // remember, this is flags
-                }
-            }
-
-            // Finally, read the case fold map from CaseFolding.txt.
-            // We're looking for lines of the form "<code>; <status>; <mapping>; # <name>", where <status> is 'C' or 'S'
-
-            Regex caseFoldRegex = new Regex(@"^\s*(?<fromCodePoint>[0-9A-F]{4,}); [CS]; (?<toCodePoint>[0-9A-F]{4,});", RegexOptions.IgnoreCase);
-
-            foreach (string line in ReadAllLines(CaseFoldingFilename))
-            {
-                Match match = caseFoldRegex.Match(line);
-                if (!match.Success)
-                {
-                    continue; // line was blank, comment-only, or not simple / common
-                }
-
-                uint fromCodePoint = uint.Parse(match.Groups["fromCodePoint"].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
-                uint toCodePoint = uint.Parse(match.Groups["toCodePoint"].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
-
-                _simpleCaseFoldMap[fromCodePoint] = toCodePoint;
-            }
-        }
-
-        public static UnicodeCategory GetUnicodeCategory(uint codePoint)
-        {
-            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
-
-            return _categoryMap.TryGetValue(codePoint, out UnicodeCategory category) ? category : UnicodeCategory.OtherNotAssigned;
-        }
-
-        public static bool IsLetter(uint codePoint)
-        {
-            switch (GetUnicodeCategory(codePoint))
-            {
-                case UnicodeCategory.UppercaseLetter:
-                case UnicodeCategory.LowercaseLetter:
-                case UnicodeCategory.TitlecaseLetter:
-                case UnicodeCategory.ModifierLetter:
-                case UnicodeCategory.OtherLetter:
-                    return true;
-
-                default:
-                    return false;
-            }
-        }
-
-        // Returns true iff code point is listed at https://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:whitespace:]
-        public static bool IsWhiteSpace(uint codePoint)
-        {
-            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
-
-            _propertyMap.TryGetValue(codePoint, out CharProperty property);
-            return property.HasFlag(CharProperty.White_Space);
-        }
-
-        public static uint SimpleFoldCaseMap(uint codePoint)
-        {
-            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
-
-            // If an entry doesn't exist, the value maps to itself.
-            return _simpleCaseFoldMap.TryGetValue(codePoint, out uint value) ? value : codePoint;
-        }
-
-        public static uint SimpleLowerCaseMap(uint codePoint)
-        {
-            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
-
-            // If an entry doesn't exist, the value maps to itself.
-            return _simpleLowerCaseMap.TryGetValue(codePoint, out uint value) ? value : codePoint;
-        }
-
-        public static uint SimpleTitleCaseMap(uint codePoint)
-        {
-            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
-
-            // If an entry doesn't exist, the value maps to itself.
-            return _simpleTitleCaseMap.TryGetValue(codePoint, out uint value) ? value : codePoint;
-        }
-
-        public static uint SimpleUpperCaseMap(uint codePoint)
-        {
-            Assert.True(codePoint <= 0x10FFFF, "Invalid code point provided.");
-
-            // If an entry doesn't exist, the value maps to itself.
-            return _simpleUpperCaseMap.TryGetValue(codePoint, out uint value) ? value : codePoint;
-        }
-
-        [Flags]
-        private enum CharProperty : ulong
-        {
-            ASCII_Hex_Digit = 1ul << 0,
-            Bidi_Control = 1ul << 1,
-            Dash = 1ul << 2,
-            Deprecated = 1ul << 3,
-            Diacritic = 1ul << 4,
-            Extender = 1ul << 5,
-            Hex_Digit = 1ul << 6,
-            Hyphen = 1ul << 7,
-            Ideographic = 1ul << 8,
-            IDS_Binary_Operator = 1ul << 9,
-            IDS_Trinary_Operator = 1ul << 10,
-            Join_Control = 1ul << 11,
-            Logical_Order_Exception = 1ul << 12,
-            Noncharacter_Code_Point = 1ul << 13,
-            Other_Alphabetic = 1ul << 14,
-            Other_Default_Ignorable_Code_Point = 1ul << 15,
-            Other_Grapheme_Extend = 1ul << 16,
-            Other_ID_Continue = 1ul << 17,
-            Other_ID_Start = 1ul << 18,
-            Other_Lowercase = 1ul << 19,
-            Other_Math = 1ul << 20,
-            Other_Uppercase = 1ul << 21,
-            Pattern_Syntax = 1ul << 22,
-            Pattern_White_Space = 1ul << 23,
-            Prepended_Concatenation_Mark = 1ul << 24,
-            Quotation_Mark = 1ul << 25,
-            Radical = 1ul << 26,
-            Regional_Indicator = 1ul << 27,
-            Sentence_Terminal = 1ul << 28,
-            Soft_Dotted = 1ul << 29,
-            Terminal_Punctuation = 1ul << 30,
-            Unified_Ideograph = 1ul << 31,
-            Variation_Selector = 1ul << 32,
-            White_Space = 1ul << 33,
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf16UtilityTests.ValidateChars.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf16UtilityTests.ValidateChars.cs
new file mode 100644 (file)
index 0000000..c719183
--- /dev/null
@@ -0,0 +1,289 @@
+// 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.Globalization;
+using System.Linq;
+using System.Numerics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Xunit;
+
+namespace System.Text.Unicode.Tests
+{
+    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();
+
+        [Theory]
+        [InlineData("", 0, 0)] // empty string is OK
+        [InlineData("X", 1, 1)]
+        [InlineData("XY", 2, 2)]
+        [InlineData("XYZ", 3, 3)]
+        [InlineData("<EACU>", 1, 2)]
+        [InlineData("X<EACU>", 2, 3)]
+        [InlineData("<EACU>X", 2, 3)]
+        [InlineData("<EURO>", 1, 3)]
+        [InlineData("<GRIN>", 1, 4)]
+        [InlineData("X<GRIN>Z", 3, 6)]
+        [InlineData("X<0000>Z", 3, 3)] // null chars are allowed
+        public void GetIndexOfFirstInvalidUtf16Sequence_WithSmallValidBuffers(string unprocessedInput, int expectedRuneCount, int expectedUtf8ByteCount)
+        {
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(unprocessedInput, -1 /* expectedIdxOfFirstInvalidChar */, expectedRuneCount, expectedUtf8ByteCount);
+        }
+
+        [Theory]
+        [InlineData("<DC00>", 0, 0, 0)] // standalone low surrogate (at beginning of sequence)
+        [InlineData("X<DC00>", 1, 1, 1)] // standalone low surrogate (preceded by valid ASCII data)
+        [InlineData("<EURO><DC00>", 1, 1, 3)] // standalone low surrogate (preceded by valid non-ASCII data)
+        [InlineData("<D800>", 0, 0, 0)] // standalone high surrogate (missing follow-up low surrogate)
+        [InlineData("<D800>Y", 0, 0, 0)] // standalone high surrogate (followed by ASCII char)
+        [InlineData("<D800><D800>", 0, 0, 0)] // standalone high surrogate (followed by high surrogate)
+        [InlineData("<D800><EURO>", 0, 0, 0)] // standalone high surrogate (followed by valid non-ASCII char)
+        [InlineData("<DC00><DC00>", 0, 0, 0)] // standalone low surrogate (not preceded by a high surrogate)
+        [InlineData("<DC00><D800>", 0, 0, 0)] // standalone low surrogate (not preceded by a high surrogate)
+        [InlineData("<GRIN><DC00><DC00>", 2, 1, 4)] // standalone low surrogate (preceded by a valid surrogate pair)
+        [InlineData("<GRIN><DC00><D800>", 2, 1, 4)] // standalone low surrogate (preceded by a valid surrogate pair)
+        [InlineData("<GRIN><0000><DC00><D800>", 3, 2, 5)] // standalone low surrogate (preceded by a valid null char)
+        public void GetIndexOfFirstInvalidUtf16Sequence_WithSmallInvalidBuffers(string unprocessedInput, int idxOfFirstInvalidChar, int expectedRuneCount, int expectedUtf8ByteCount)
+        {
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(unprocessedInput, idxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
+        }
+
+        [Theory] // chars below presented as hex since Xunit doesn't like invalid UTF-16 string literals
+        [InlineData("<2BB4><218C><1BC0><613F><F9E9><B740><DE38><E689>", 6, 6, 18)]
+        [InlineData("<1854><C980><012C><4797><DD5A><41D0><A104><5464>", 4, 4, 11)]
+        [InlineData("<F1AF><8BD3><5037><BE29><DEFF><3E3A><DD71><6336>", 4, 4, 12)]
+        [InlineData("<B978><0F25><DC23><D3BB><7352><4025><0B93><4107>", 2, 2, 6)]
+        [InlineData("<887C><C980><012C><4797><DD5A><41D0><A104><5464>", 4, 4, 11)]
+        public void GetIndexOfFirstInvalidUtf16Sequence_WithEightRandomCharsContainingUnpairedSurrogates(string unprocessedInput, int idxOfFirstInvalidChar, int expectedRuneCount, int expectedUtf8ByteCount)
+        {
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(unprocessedInput, idxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf16Sequence_WithInvalidSurrogateSequences()
+        {
+            // All ASCII
+
+            char[] chars = Enumerable.Repeat('x', 128).ToArray();
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 128, expectedUtf8ByteCount: 128);
+
+            // Throw a surrogate pair at the beginning
+
+            chars[0] = '\uD800';
+            chars[1] = '\uDFFF';
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 127, expectedUtf8ByteCount: 130);
+
+            // Throw a surrogate pair near the end
+
+            chars[124] = '\uD800';
+            chars[125] = '\uDFFF';
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 126, expectedUtf8ByteCount: 132);
+
+            // Throw a standalone surrogate code point at the *very* end
+
+            chars[127] = '\uD800'; // high surrogate
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, 127, expectedRuneCount: 125, expectedUtf8ByteCount: 131);
+
+            chars[127] = '\uDFFF'; // low surrogate
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, 127, expectedRuneCount: 125, expectedUtf8ByteCount: 131);
+
+            // Make the final surrogate pair valid
+
+            chars[126] = '\uD800'; // high surrogate
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 125, expectedUtf8ByteCount: 134);
+
+            // Throw an invalid surrogate sequence in the middle (straddles a vector boundary)
+
+            chars[12] = '\u0080'; // 2-byte UTF-8 sequence
+            chars[13] = '\uD800'; // high surrogate
+            chars[14] = '\uD800'; // high surrogate
+            chars[15] = '\uDFFF'; // low surrogate
+            chars[16] = '\uDFFF'; // low surrogate
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, 13, expectedRuneCount: 12, expectedUtf8ByteCount: 16);
+
+            // Correct the surrogate sequence we just added
+
+            chars[14] = '\uDC00'; // low surrogate
+            chars[15] = '\uDBFF'; // high surrogate
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 123, expectedUtf8ByteCount: 139);
+
+            // Corrupt the surrogate pair that's split across a vector boundary
+
+            chars[16] = 'x'; // ASCII char (remember.. chars[15] is a high surrogate char)
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, 15, expectedRuneCount: 13, expectedUtf8ByteCount: 20);
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf16Sequence_WithStandaloneLowSurrogateCharAtStart()
+        {
+            // The input stream will be a vector's worth of ASCII chars, followed by a single standalone low
+            // surrogate char, then padded with U+0000 until it's a multiple of the vector size.
+            // Using Vector<ushort>.Count here as a stand-in for Vector<char>.Count.
+
+            char[] chars = new char[Vector<ushort>.Count * 2];
+            for (int i = 0; i < Vector<ushort>.Count; i++)
+            {
+                chars[i] = 'x'; // ASCII char
+            }
+
+            chars[Vector<ushort>.Count] = '\uDEAD'; // standalone low surrogate char
+
+            for (int i = 0; i <= Vector<ushort>.Count; i++)
+            {
+                // Expect all ASCII chars to be consumed, low surrogate char to be marked invalid.
+                GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars[(Vector<ushort>.Count - i)..], i, i, i);
+            }
+        }
+
+        private static void GetIndexOfFirstInvalidUtf16Sequence_Test_Core(string unprocessedInput, int expectedIdxOfFirstInvalidChar, int expectedRuneCount, long expectedUtf8ByteCount)
+        {
+            char[] processedInput = ProcessInput(unprocessedInput).ToCharArray();
+
+            // Run the test normally
+
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
+
+            // Put a bunch of ASCII data at the beginning (to test the call to ASCIIUtility at method entry)
+
+            processedInput = Enumerable.Repeat('x', 128).Concat(processedInput).ToArray();
+
+            if (expectedIdxOfFirstInvalidChar >= 0)
+            {
+                expectedIdxOfFirstInvalidChar += 128;
+            }
+            expectedRuneCount += 128;
+            expectedUtf8ByteCount += 128;
+
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
+
+            // Change the first few chars to a mixture of 2-byte and 3-byte UTF-8 sequences
+            // This makes sure the vectorized code paths can properly handle these.
+
+            processedInput[0] = '\u0080'; // 2-byte UTF-8 sequence
+            processedInput[1] = '\u0800'; // 3-byte UTF-8 sequence
+            processedInput[2] = '\u0080'; // 2-byte UTF-8 sequence
+            processedInput[3] = '\u0800'; // 3-byte UTF-8 sequence
+            processedInput[4] = '\u0080'; // 2-byte UTF-8 sequence
+            processedInput[5] = '\u0800'; // 3-byte UTF-8 sequence
+            processedInput[6] = '\u0080'; // 2-byte UTF-8 sequence
+            processedInput[7] = '\u0800'; // 3-byte UTF-8 sequence
+
+            expectedUtf8ByteCount += 12;
+
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
+
+            // Throw some surrogate pairs into the mix to make sure they're also handled properly
+            // by the vectorized code paths.
+
+            processedInput[8] = '\u0080'; // 2-byte UTF-8 sequence
+            processedInput[9] = '\u0800'; // 3-byte UTF-8 sequence
+            processedInput[10] = '\u0080'; // 2-byte UTF-8 sequence
+            processedInput[11] = '\u0800'; // 3-byte UTF-8 sequence
+            processedInput[12] = '\u0080'; // 2-byte UTF-8 sequence
+            processedInput[13] = '\uD800'; // high surrogate
+            processedInput[14] = '\uDC00'; // low surrogate
+            processedInput[15] = 'z'; // ASCII char
+
+            expectedRuneCount--;
+            expectedUtf8ByteCount += 9;
+
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
+
+            // Split the next surrogate pair across the vector boundary (so that we
+            // don't inadvertently treat this as a standalone surrogate sequence).
+
+            processedInput[15] = '\uDBFF'; // high surrogate
+            processedInput[16] = '\uDFFF'; // low surrogate
+
+            expectedRuneCount--;
+            expectedUtf8ByteCount += 2;
+
+            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
+        }
+
+        private static unsafe void GetIndexOfFirstInvalidUtf16Sequence_Test_Core(char[] input, int expectedRetVal, int expectedRuneCount, long expectedUtf8ByteCount)
+        {
+            // Arrange
+
+            using BoundedMemory<char> boundedMemory = BoundedMemory.AllocateFromExistingData(input);
+            boundedMemory.MakeReadonly();
+
+            // Act
+
+            int actualRetVal;
+            long actualUtf8CodeUnitCount;
+            int actualRuneCount;
+
+            fixed (char* pInputBuffer = &MemoryMarshal.GetReference(boundedMemory.Span))
+            {
+                char* pFirstInvalidChar = _getPointerToFirstInvalidCharFn.Value(pInputBuffer, input.Length, out long utf8CodeUnitCountAdjustment, out int scalarCountAdjustment);
+
+                long ptrDiff = pFirstInvalidChar - pInputBuffer;
+                Assert.True((ulong)ptrDiff <= (uint)input.Length, "ptrDiff was outside expected range.");
+
+                Assert.True(utf8CodeUnitCountAdjustment >= 0, "UTF-16 code unit count adjustment must be non-negative.");
+                Assert.True(scalarCountAdjustment <= 0, "Scalar count adjustment must be 0 or negative.");
+
+                actualRetVal = (ptrDiff == input.Length) ? -1 : (int)ptrDiff;
+
+                // The last two 'out' parameters are:
+                // a) The number to be added to the "chars processed" return value to come up with the total UTF-8 code unit count, and
+                // b) The number to be added to the "total UTF-16 code unit count" value to come up with the total scalar count.
+
+                actualUtf8CodeUnitCount = ptrDiff + utf8CodeUnitCountAdjustment;
+                actualRuneCount = (int)ptrDiff + scalarCountAdjustment;
+            }
+
+            // Assert
+
+            Assert.Equal(expectedRetVal, actualRetVal);
+            Assert.Equal(expectedRuneCount, actualRuneCount);
+            Assert.Equal(actualUtf8CodeUnitCount, expectedUtf8ByteCount);
+        }
+
+        private static Lazy<GetPointerToFirstInvalidCharDel> CreateGetPointerToFirstInvalidCharFn()
+        {
+            return new Lazy<GetPointerToFirstInvalidCharDel>(() =>
+            {
+                Type utf16UtilityType = typeof(Utf8).Assembly.GetType("System.Text.Unicode.Utf16Utility");
+
+                if (utf16UtilityType is null)
+                {
+                    throw new Exception("Couldn't find Utf16Utility type in System.Private.CoreLib.");
+                }
+
+                MethodInfo methodInfo = utf16UtilityType.GetMethod("GetPointerToFirstInvalidChar", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+
+                if (methodInfo is null)
+                {
+                    throw new Exception("Couldn't find GetPointerToFirstInvalidChar method on Utf8Utility.");
+                }
+
+                return (GetPointerToFirstInvalidCharDel)methodInfo.CreateDelegate(typeof(GetPointerToFirstInvalidCharDel));
+            });
+        }
+
+        private static string ProcessInput(string input)
+        {
+            input = input.Replace("<EACU>", "\u00E9", StringComparison.Ordinal); // U+00E9 LATIN SMALL LETTER E WITH ACUTE
+            input = input.Replace("<EURO>", "\u20AC", StringComparison.Ordinal); // U+20AC EURO SIGN
+            input = input.Replace("<GRIN>", "\U0001F600", StringComparison.Ordinal); //  U+1F600 GRINNING FACE
+
+            // Replace <ABCD> with \uABCD. This allows us to flow potentially malformed
+            // UTF-16 strings without Xunit. (The unit testing framework gets angry when
+            // we try putting invalid UTF-16 data as inline test data.)
+
+            int idx;
+            while ((idx = input.IndexOf('<')) >= 0)
+            {
+                input = input[..idx] + (char)ushort.Parse(input.Substring(idx + 1, 4), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture) + input[(idx + 6)..];
+            }
+
+            return input;
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf16UtilityTests.ValidateChars.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf16UtilityTests.ValidateChars.netcoreapp.cs
deleted file mode 100644 (file)
index cf47587..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-// 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.Globalization;
-using System.Linq;
-using System.Numerics;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using Xunit;
-
-namespace System.Text.Unicode.Tests
-{
-    public partial class Utf16UtilityTests
-    {
-        private unsafe delegate char* GetPointerToFirstInvalidCharDel(char* pInputBuffer, int inputLength, out long utf8CodeUnitCountAdjustment, out int scalarCountAdjustment);
-        private static readonly Lazy<GetPointerToFirstInvalidCharDel> _getPointerToFirstInvalidCharFn = CreateGetPointerToFirstInvalidCharFn();
-
-        [Theory]
-        [InlineData("", 0, 0)] // empty string is OK
-        [InlineData("X", 1, 1)]
-        [InlineData("XY", 2, 2)]
-        [InlineData("XYZ", 3, 3)]
-        [InlineData("<EACU>", 1, 2)]
-        [InlineData("X<EACU>", 2, 3)]
-        [InlineData("<EACU>X", 2, 3)]
-        [InlineData("<EURO>", 1, 3)]
-        [InlineData("<GRIN>", 1, 4)]
-        [InlineData("X<GRIN>Z", 3, 6)]
-        [InlineData("X<0000>Z", 3, 3)] // null chars are allowed
-        public void GetIndexOfFirstInvalidUtf16Sequence_WithSmallValidBuffers(string unprocessedInput, int expectedRuneCount, int expectedUtf8ByteCount)
-        {
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(unprocessedInput, -1 /* expectedIdxOfFirstInvalidChar */, expectedRuneCount, expectedUtf8ByteCount);
-        }
-
-        [Theory]
-        [InlineData("<DC00>", 0, 0, 0)] // standalone low surrogate (at beginning of sequence)
-        [InlineData("X<DC00>", 1, 1, 1)] // standalone low surrogate (preceded by valid ASCII data)
-        [InlineData("<EURO><DC00>", 1, 1, 3)] // standalone low surrogate (preceded by valid non-ASCII data)
-        [InlineData("<D800>", 0, 0, 0)] // standalone high surrogate (missing follow-up low surrogate)
-        [InlineData("<D800>Y", 0, 0, 0)] // standalone high surrogate (followed by ASCII char)
-        [InlineData("<D800><D800>", 0, 0, 0)] // standalone high surrogate (followed by high surrogate)
-        [InlineData("<D800><EURO>", 0, 0, 0)] // standalone high surrogate (followed by valid non-ASCII char)
-        [InlineData("<DC00><DC00>", 0, 0, 0)] // standalone low surrogate (not preceded by a high surrogate)
-        [InlineData("<DC00><D800>", 0, 0, 0)] // standalone low surrogate (not preceded by a high surrogate)
-        [InlineData("<GRIN><DC00><DC00>", 2, 1, 4)] // standalone low surrogate (preceded by a valid surrogate pair)
-        [InlineData("<GRIN><DC00><D800>", 2, 1, 4)] // standalone low surrogate (preceded by a valid surrogate pair)
-        [InlineData("<GRIN><0000><DC00><D800>", 3, 2, 5)] // standalone low surrogate (preceded by a valid null char)
-        public void GetIndexOfFirstInvalidUtf16Sequence_WithSmallInvalidBuffers(string unprocessedInput, int idxOfFirstInvalidChar, int expectedRuneCount, int expectedUtf8ByteCount)
-        {
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(unprocessedInput, idxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
-        }
-
-        [Theory] // chars below presented as hex since Xunit doesn't like invalid UTF-16 string literals
-        [InlineData("<2BB4><218C><1BC0><613F><F9E9><B740><DE38><E689>", 6, 6, 18)]
-        [InlineData("<1854><C980><012C><4797><DD5A><41D0><A104><5464>", 4, 4, 11)]
-        [InlineData("<F1AF><8BD3><5037><BE29><DEFF><3E3A><DD71><6336>", 4, 4, 12)]
-        [InlineData("<B978><0F25><DC23><D3BB><7352><4025><0B93><4107>", 2, 2, 6)]
-        [InlineData("<887C><C980><012C><4797><DD5A><41D0><A104><5464>", 4, 4, 11)]
-        public void GetIndexOfFirstInvalidUtf16Sequence_WithEightRandomCharsContainingUnpairedSurrogates(string unprocessedInput, int idxOfFirstInvalidChar, int expectedRuneCount, int expectedUtf8ByteCount)
-        {
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(unprocessedInput, idxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf16Sequence_WithInvalidSurrogateSequences()
-        {
-            // All ASCII
-
-            char[] chars = Enumerable.Repeat('x', 128).ToArray();
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 128, expectedUtf8ByteCount: 128);
-
-            // Throw a surrogate pair at the beginning
-
-            chars[0] = '\uD800';
-            chars[1] = '\uDFFF';
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 127, expectedUtf8ByteCount: 130);
-
-            // Throw a surrogate pair near the end
-
-            chars[124] = '\uD800';
-            chars[125] = '\uDFFF';
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 126, expectedUtf8ByteCount: 132);
-
-            // Throw a standalone surrogate code point at the *very* end
-
-            chars[127] = '\uD800'; // high surrogate
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, 127, expectedRuneCount: 125, expectedUtf8ByteCount: 131);
-
-            chars[127] = '\uDFFF'; // low surrogate
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, 127, expectedRuneCount: 125, expectedUtf8ByteCount: 131);
-
-            // Make the final surrogate pair valid
-
-            chars[126] = '\uD800'; // high surrogate
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 125, expectedUtf8ByteCount: 134);
-
-            // Throw an invalid surrogate sequence in the middle (straddles a vector boundary)
-
-            chars[12] = '\u0080'; // 2-byte UTF-8 sequence
-            chars[13] = '\uD800'; // high surrogate
-            chars[14] = '\uD800'; // high surrogate
-            chars[15] = '\uDFFF'; // low surrogate
-            chars[16] = '\uDFFF'; // low surrogate
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, 13, expectedRuneCount: 12, expectedUtf8ByteCount: 16);
-
-            // Correct the surrogate sequence we just added
-
-            chars[14] = '\uDC00'; // low surrogate
-            chars[15] = '\uDBFF'; // high surrogate
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, -1, expectedRuneCount: 123, expectedUtf8ByteCount: 139);
-
-            // Corrupt the surrogate pair that's split across a vector boundary
-
-            chars[16] = 'x'; // ASCII char (remember.. chars[15] is a high surrogate char)
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars, 15, expectedRuneCount: 13, expectedUtf8ByteCount: 20);
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf16Sequence_WithStandaloneLowSurrogateCharAtStart()
-        {
-            // The input stream will be a vector's worth of ASCII chars, followed by a single standalone low
-            // surrogate char, then padded with U+0000 until it's a multiple of the vector size.
-            // Using Vector<ushort>.Count here as a stand-in for Vector<char>.Count.
-
-            char[] chars = new char[Vector<ushort>.Count * 2];
-            for (int i = 0; i < Vector<ushort>.Count; i++)
-            {
-                chars[i] = 'x'; // ASCII char
-            }
-
-            chars[Vector<ushort>.Count] = '\uDEAD'; // standalone low surrogate char
-
-            for (int i = 0; i <= Vector<ushort>.Count; i++)
-            {
-                // Expect all ASCII chars to be consumed, low surrogate char to be marked invalid.
-                GetIndexOfFirstInvalidUtf16Sequence_Test_Core(chars[(Vector<ushort>.Count - i)..], i, i, i);
-            }
-        }
-
-        private static void GetIndexOfFirstInvalidUtf16Sequence_Test_Core(string unprocessedInput, int expectedIdxOfFirstInvalidChar, int expectedRuneCount, long expectedUtf8ByteCount)
-        {
-            char[] processedInput = ProcessInput(unprocessedInput).ToCharArray();
-
-            // Run the test normally
-
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
-
-            // Put a bunch of ASCII data at the beginning (to test the call to ASCIIUtility at method entry)
-
-            processedInput = Enumerable.Repeat('x', 128).Concat(processedInput).ToArray();
-
-            if (expectedIdxOfFirstInvalidChar >= 0)
-            {
-                expectedIdxOfFirstInvalidChar += 128;
-            }
-            expectedRuneCount += 128;
-            expectedUtf8ByteCount += 128;
-
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
-
-            // Change the first few chars to a mixture of 2-byte and 3-byte UTF-8 sequences
-            // This makes sure the vectorized code paths can properly handle these.
-
-            processedInput[0] = '\u0080'; // 2-byte UTF-8 sequence
-            processedInput[1] = '\u0800'; // 3-byte UTF-8 sequence
-            processedInput[2] = '\u0080'; // 2-byte UTF-8 sequence
-            processedInput[3] = '\u0800'; // 3-byte UTF-8 sequence
-            processedInput[4] = '\u0080'; // 2-byte UTF-8 sequence
-            processedInput[5] = '\u0800'; // 3-byte UTF-8 sequence
-            processedInput[6] = '\u0080'; // 2-byte UTF-8 sequence
-            processedInput[7] = '\u0800'; // 3-byte UTF-8 sequence
-
-            expectedUtf8ByteCount += 12;
-
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
-
-            // Throw some surrogate pairs into the mix to make sure they're also handled properly
-            // by the vectorized code paths.
-
-            processedInput[8] = '\u0080'; // 2-byte UTF-8 sequence
-            processedInput[9] = '\u0800'; // 3-byte UTF-8 sequence
-            processedInput[10] = '\u0080'; // 2-byte UTF-8 sequence
-            processedInput[11] = '\u0800'; // 3-byte UTF-8 sequence
-            processedInput[12] = '\u0080'; // 2-byte UTF-8 sequence
-            processedInput[13] = '\uD800'; // high surrogate
-            processedInput[14] = '\uDC00'; // low surrogate
-            processedInput[15] = 'z'; // ASCII char
-
-            expectedRuneCount--;
-            expectedUtf8ByteCount += 9;
-
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
-
-            // Split the next surrogate pair across the vector boundary (so that we
-            // don't inadvertently treat this as a standalone surrogate sequence).
-
-            processedInput[15] = '\uDBFF'; // high surrogate
-            processedInput[16] = '\uDFFF'; // low surrogate
-
-            expectedRuneCount--;
-            expectedUtf8ByteCount += 2;
-
-            GetIndexOfFirstInvalidUtf16Sequence_Test_Core(processedInput, expectedIdxOfFirstInvalidChar, expectedRuneCount, expectedUtf8ByteCount);
-        }
-
-        private static unsafe void GetIndexOfFirstInvalidUtf16Sequence_Test_Core(char[] input, int expectedRetVal, int expectedRuneCount, long expectedUtf8ByteCount)
-        {
-            // Arrange
-
-            using BoundedMemory<char> boundedMemory = BoundedMemory.AllocateFromExistingData(input);
-            boundedMemory.MakeReadonly();
-
-            // Act
-
-            int actualRetVal;
-            long actualUtf8CodeUnitCount;
-            int actualRuneCount;
-
-            fixed (char* pInputBuffer = &MemoryMarshal.GetReference(boundedMemory.Span))
-            {
-                char* pFirstInvalidChar = _getPointerToFirstInvalidCharFn.Value(pInputBuffer, input.Length, out long utf8CodeUnitCountAdjustment, out int scalarCountAdjustment);
-
-                long ptrDiff = pFirstInvalidChar - pInputBuffer;
-                Assert.True((ulong)ptrDiff <= (uint)input.Length, "ptrDiff was outside expected range.");
-
-                Assert.True(utf8CodeUnitCountAdjustment >= 0, "UTF-16 code unit count adjustment must be non-negative.");
-                Assert.True(scalarCountAdjustment <= 0, "Scalar count adjustment must be 0 or negative.");
-
-                actualRetVal = (ptrDiff == input.Length) ? -1 : (int)ptrDiff;
-
-                // The last two 'out' parameters are:
-                // a) The number to be added to the "chars processed" return value to come up with the total UTF-8 code unit count, and
-                // b) The number to be added to the "total UTF-16 code unit count" value to come up with the total scalar count.
-
-                actualUtf8CodeUnitCount = ptrDiff + utf8CodeUnitCountAdjustment;
-                actualRuneCount = (int)ptrDiff + scalarCountAdjustment;
-            }
-
-            // Assert
-
-            Assert.Equal(expectedRetVal, actualRetVal);
-            Assert.Equal(expectedRuneCount, actualRuneCount);
-            Assert.Equal(actualUtf8CodeUnitCount, expectedUtf8ByteCount);
-        }
-
-        private static Lazy<GetPointerToFirstInvalidCharDel> CreateGetPointerToFirstInvalidCharFn()
-        {
-            return new Lazy<GetPointerToFirstInvalidCharDel>(() =>
-            {
-                Type utf16UtilityType = typeof(Utf8).Assembly.GetType("System.Text.Unicode.Utf16Utility");
-
-                if (utf16UtilityType is null)
-                {
-                    throw new Exception("Couldn't find Utf16Utility type in System.Private.CoreLib.");
-                }
-
-                MethodInfo methodInfo = utf16UtilityType.GetMethod("GetPointerToFirstInvalidChar", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
-
-                if (methodInfo is null)
-                {
-                    throw new Exception("Couldn't find GetPointerToFirstInvalidChar method on Utf8Utility.");
-                }
-
-                return (GetPointerToFirstInvalidCharDel)methodInfo.CreateDelegate(typeof(GetPointerToFirstInvalidCharDel));
-            });
-        }
-
-        private static string ProcessInput(string input)
-        {
-            input = input.Replace("<EACU>", "\u00E9", StringComparison.Ordinal); // U+00E9 LATIN SMALL LETTER E WITH ACUTE
-            input = input.Replace("<EURO>", "\u20AC", StringComparison.Ordinal); // U+20AC EURO SIGN
-            input = input.Replace("<GRIN>", "\U0001F600", StringComparison.Ordinal); //  U+1F600 GRINNING FACE
-
-            // Replace <ABCD> with \uABCD. This allows us to flow potentially malformed
-            // UTF-16 strings without Xunit. (The unit testing framework gets angry when
-            // we try putting invalid UTF-16 data as inline test data.)
-
-            int idx;
-            while ((idx = input.IndexOf('<')) >= 0)
-            {
-                input = input[..idx] + (char)ushort.Parse(input.Substring(idx + 1, 4), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture) + input[(idx + 6)..];
-            }
-
-            return input;
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.ToBytes.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.ToBytes.netcoreapp.cs
deleted file mode 100644 (file)
index 5432da0..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-// 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());
-            }
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.ToChars.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.ToChars.netcoreapp.cs
deleted file mode 100644 (file)
index cb39338..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-// 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("80", 0, "")] // sequence cannot begin with continuation character
-        [InlineData("8182", 0, "")] // sequence cannot begin with continuation character
-        [InlineData("838485", 0, "")] // sequence cannot begin with continuation character
-        [InlineData(X_UTF8 + "80", 1, X_UTF16)] // sequence cannot begin with continuation character
-        [InlineData(X_UTF8 + "8182", 1, X_UTF16)] // sequence cannot begin with continuation character
-        [InlineData("C0", 0, "")] // [ C0 ] is always invalid
-        [InlineData("C080", 0, "")] // [ C0 ] is always invalid
-        [InlineData("C08081", 0, "")] // [ C0 ] is always invalid
-        [InlineData(X_UTF8 + "C1", 1, X_UTF16)] // [ C1 ] is always invalid
-        [InlineData(X_UTF8 + "C180", 1, X_UTF16)] // [ C1 ] is always invalid
-        [InlineData(X_UTF8 + "C27F", 1, X_UTF16)] // [ C2 ] is improperly terminated
-        [InlineData("E2827F", 0, "")] // [ E2 82 ] is improperly terminated
-        [InlineData("E09F80", 0, "")] // [ E0 9F ... ] is overlong
-        [InlineData("E0C080", 0, "")] // [ E0 ] is improperly terminated
-        [InlineData("ED7F80", 0, "")] // [ ED ] is improperly terminated
-        [InlineData("EDA080", 0, "")] // [ ED A0 ... ] is surrogate
-        public void ToChars_WithSmallInvalidBuffers(string utf8HexInput, int expectedNumBytesConsumed, string expectedUtf16Transcoding)
-        {
-            // These test cases are for the "slow processing" code path at the end of TranscodeToUtf16,
-            // so inputs should be less than 4 bytes.
-
-            Assert.InRange(utf8HexInput.Length, 0, 6);
-
-            ToChars_Test_Core(
-              utf8Input: DecodeHex(utf8HexInput),
-              destinationSize: expectedUtf16Transcoding.Length,
-              replaceInvalidSequences: false,
-              isFinalChunk: false,
-              expectedOperationStatus: OperationStatus.InvalidData,
-              expectedNumBytesRead: expectedNumBytesConsumed,
-              expectedUtf16Transcoding: expectedUtf16Transcoding);
-
-            // Now try the tests again with a larger buffer.
-            // This ensures that running out of destination space wasn't the reason we failed.
-
-            ToChars_Test_Core(
-              utf8Input: DecodeHex(utf8HexInput),
-              destinationSize: expectedUtf16Transcoding.Length + 16,
-              replaceInvalidSequences: false,
-              isFinalChunk: false,
-              expectedOperationStatus: OperationStatus.InvalidData,
-              expectedNumBytesRead: expectedNumBytesConsumed,
-              expectedUtf16Transcoding: expectedUtf16Transcoding);
-        }
-
-        [Theory]
-        [InlineData("C2", 0, "")] // [ C2 ] is an incomplete sequence
-        [InlineData("E282", 0, "")] // [ E2 82 ] is an incomplete sequence
-        [InlineData(X_UTF8 + "C2", 1, X_UTF16)] // [ C2 ] is an incomplete sequence
-        [InlineData(X_UTF8 + "E0", 1, X_UTF16)] // [ E0 ] is an incomplete sequence
-        [InlineData(X_UTF8 + "E0BF", 1, X_UTF16)] // [ E0 BF ] is an incomplete sequence
-        [InlineData(X_UTF8 + "F0", 1, X_UTF16)] // [ F0 ] is an incomplete sequence
-        [InlineData(X_UTF8 + "F0BF", 1, X_UTF16)] // [ F0 BF ] is an incomplete sequence
-        [InlineData(X_UTF8 + "F0BFA0", 1, X_UTF16)] // [ F0 BF A0 ] is an incomplete sequence
-        [InlineData(E_ACUTE_UTF8 + "C2", 2, E_ACUTE_UTF16)] // [ C2 ] is an incomplete sequence
-        [InlineData(E_ACUTE_UTF8 + "E0", 2, E_ACUTE_UTF16)] // [ E0 ] is an incomplete sequence
-        [InlineData(E_ACUTE_UTF8 + "F0", 2, E_ACUTE_UTF16)] // [ F0 ] is an incomplete sequence
-        [InlineData(E_ACUTE_UTF8 + "E0BF", 2, E_ACUTE_UTF16)] // [ E0 BF ] is an incomplete sequence
-        [InlineData(E_ACUTE_UTF8 + "F0BF", 2, E_ACUTE_UTF16)] // [ F0 BF ] is an incomplete sequence
-        [InlineData(EURO_SYMBOL_UTF8 + "C2", 3, EURO_SYMBOL_UTF16)] // [ C2 ] is an incomplete sequence
-        [InlineData(EURO_SYMBOL_UTF8 + "E0", 3, EURO_SYMBOL_UTF16)] // [ E0 ] is an incomplete sequence
-        [InlineData(EURO_SYMBOL_UTF8 + "F0", 3, EURO_SYMBOL_UTF16)] // [ F0 ] is an incomplete sequence
-        public void ToChars_WithVariousIncompleteBuffers(string utf8HexInput, int expectedNumBytesConsumed, string expectedUtf16Transcoding)
-        {
-            // These test cases are for the "slow processing" code path at the end of TranscodeToUtf16,
-            // so inputs should be less than 4 bytes.
-
-            ToChars_Test_Core(
-              utf8Input: DecodeHex(utf8HexInput),
-              destinationSize: expectedUtf16Transcoding.Length,
-              replaceInvalidSequences: false,
-              isFinalChunk: false,
-              expectedOperationStatus: OperationStatus.NeedMoreData,
-              expectedNumBytesRead: expectedNumBytesConsumed,
-              expectedUtf16Transcoding: expectedUtf16Transcoding);
-
-            // Now try the tests again with a larger buffer.
-            // This ensures that running out of destination space wasn't the reason we failed.
-
-            ToChars_Test_Core(
-             utf8Input: DecodeHex(utf8HexInput),
-             destinationSize: expectedUtf16Transcoding.Length + 16,
-             replaceInvalidSequences: false,
-             isFinalChunk: false,
-             expectedOperationStatus: OperationStatus.NeedMoreData,
-             expectedNumBytesRead: expectedNumBytesConsumed,
-             expectedUtf16Transcoding: expectedUtf16Transcoding);
-        }
-
-        [Theory]
-        /* SMALL VALID BUFFERS - tests drain loop at end of method */
-        [InlineData("")] // empty string is OK
-        [InlineData("X")]
-        [InlineData("XY")]
-        [InlineData("XYZ")]
-        [InlineData(E_ACUTE_UTF16)]
-        [InlineData(X_UTF16 + E_ACUTE_UTF16)]
-        [InlineData(E_ACUTE_UTF16 + X_UTF16)]
-        [InlineData(EURO_SYMBOL_UTF16)]
-        /* LARGE VALID BUFFERS - test main loop at beginning of method */
-        [InlineData(E_ACUTE_UTF16 + "ABCD" + "0123456789:;<=>?")] // Loop unrolling at end of buffer
-        [InlineData(E_ACUTE_UTF16 + "ABCD" + "0123456789:;<=>?" + "01234567" + E_ACUTE_UTF16 + "89:;<=>?")] // Loop unrolling interrupted by non-ASCII
-        [InlineData("ABC" + E_ACUTE_UTF16 + "0123")] // 3 ASCII bytes followed by non-ASCII
-        [InlineData("AB" + E_ACUTE_UTF16 + "0123")] // 2 ASCII bytes followed by non-ASCII
-        [InlineData("A" + E_ACUTE_UTF16 + "0123")] // 1 ASCII byte followed by non-ASCII
-        [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16)] // 4x 2-byte sequences, exercises optimization code path in 2-byte sequence processing
-        [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + "PQ")] // 3x 2-byte sequences + 2 ASCII bytes, exercises optimization code path in 2-byte sequence processing
-        [InlineData(E_ACUTE_UTF16 + "PQ")] // single 2-byte sequence + 2 trailing ASCII bytes, exercises draining logic in 2-byte sequence processing
-        [InlineData(E_ACUTE_UTF16 + "P" + E_ACUTE_UTF16 + "0@P")] // single 2-byte sequences + 1 trailing ASCII byte + 2-byte sequence, exercises draining logic in 2-byte sequence processing
-        [InlineData(EURO_SYMBOL_UTF16 + "@")] // single 3-byte sequence + 1 trailing ASCII byte, exercises draining logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL_UTF16 + "@P`")] // single 3-byte sequence + 3 trailing ASCII byte, exercises draining logic and "running out of data" logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // 3x 3-byte sequences, exercises "stay within 3-byte loop" logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // 4x 3-byte sequences, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + E_ACUTE_UTF16)] // 3x 3-byte sequences + single 2-byte sequence, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16)] // 2x 3-byte sequences + 4x 2-byte sequences, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
-        [InlineData(GRINNING_FACE_UTF16 + GRINNING_FACE_UTF16)] // 2x 4-byte sequences, exercises 4-byte sequence processing
-        [InlineData(GRINNING_FACE_UTF16 + "@AB")] // single 4-byte sequence + 3 ASCII bytes, exercises 4-byte sequence processing and draining logic
-        [InlineData(WOMAN_CARTWHEELING_MEDSKIN_UTF16)] // exercises switching between multiple sequence lengths
-        public void ToChars_ValidBuffers(string utf16Input)
-        {
-            // 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();
-
-            // Convert entire input to UTF-8 using our unit test reference logic.
-
-            byte[] utf8Input = enumeratedScalars.SelectMany(ToUtf8).ToArray();
-
-            // 0-length buffer test
-            ToChars_Test_Core(
-                utf8Input: utf8Input,
-                destinationSize: 0,
-                replaceInvalidSequences: false,
-                isFinalChunk: false,
-                expectedOperationStatus: (utf8Input.Length == 0) ? OperationStatus.Done : OperationStatus.DestinationTooSmall,
-                expectedNumBytesRead: 0,
-                expectedUtf16Transcoding: ReadOnlySpan<char>.Empty);
-
-            int expectedNumBytesConsumed = 0;
-            char[] concatenatedUtf16 = Array.Empty<char>();
-
-            for (int i = 0; i < enumeratedScalars.Length; i++)
-            {
-                Rune thisScalar = enumeratedScalars[i];
-
-                // if this is an astral scalar value, quickly test a buffer that's not large enough to contain the entire UTF-16 encoding
-
-                if (!thisScalar.IsBmp)
-                {
-                    ToChars_Test_Core(
-                        utf8Input: utf8Input,
-                        destinationSize: concatenatedUtf16.Length + 1,
-                        replaceInvalidSequences: false,
-                        isFinalChunk: false,
-                        expectedOperationStatus: OperationStatus.DestinationTooSmall,
-                        expectedNumBytesRead: expectedNumBytesConsumed,
-                        expectedUtf16Transcoding: concatenatedUtf16);
-                }
-
-                // now provide a destination buffer large enough to hold the next full scalar encoding
-
-                expectedNumBytesConsumed += thisScalar.Utf8SequenceLength;
-                concatenatedUtf16 = concatenatedUtf16.Concat(ToUtf16(thisScalar)).ToArray();
-
-                ToChars_Test_Core(
-                    utf8Input: utf8Input,
-                    destinationSize: concatenatedUtf16.Length,
-                    replaceInvalidSequences: false,
-                    isFinalChunk: false,
-                    expectedOperationStatus: (i == enumeratedScalars.Length - 1) ? OperationStatus.Done : OperationStatus.DestinationTooSmall,
-                    expectedNumBytesRead: expectedNumBytesConsumed,
-                    expectedUtf16Transcoding: concatenatedUtf16);
-            }
-
-            // now throw lots of ASCII data at the beginning so that we exercise the vectorized code paths
-
-            utf16Input = new string('x', 64) + utf16Input;
-            utf8Input = utf16Input.EnumerateRunes().SelectMany(ToUtf8).ToArray();
-
-            ToChars_Test_Core(
-                utf8Input: utf8Input,
-                destinationSize: utf16Input.Length,
-                replaceInvalidSequences: false,
-                isFinalChunk: true,
-                expectedOperationStatus: OperationStatus.Done,
-                expectedNumBytesRead: utf8Input.Length,
-                expectedUtf16Transcoding: utf16Input);
-
-            // 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..];
-            utf8Input = utf16Input.EnumerateRunes().SelectMany(ToUtf8).ToArray();
-
-            ToChars_Test_Core(
-                utf8Input: utf8Input,
-                destinationSize: utf16Input.Length,
-                replaceInvalidSequences: false,
-                isFinalChunk: true,
-                expectedOperationStatus: OperationStatus.Done,
-                expectedNumBytesRead: utf8Input.Length,
-                expectedUtf16Transcoding: utf16Input);
-        }
-
-        [Theory]
-        [InlineData("3031" + "80" + "202122232425", 2, "01")] // Continuation character at start of sequence should match no bitmask
-        [InlineData("3031" + "C080" + "2021222324", 2, "01")] // Overlong 2-byte sequence at start of DWORD
-        [InlineData("3031" + "C180" + "2021222324", 2, "01")] // Overlong 2-byte sequence at start of DWORD
-        [InlineData("C280" + "C180", 2, "\u0080")] // Overlong 2-byte sequence at end of DWORD
-        [InlineData("C27F" + "C280", 0, "")] // Improperly terminated 2-byte sequence at start of DWORD
-        [InlineData("C2C0" + "C280", 0, "")] // Improperly terminated 2-byte sequence at start of DWORD
-        [InlineData("C280" + "C27F", 2, "\u0080")] // Improperly terminated 2-byte sequence at end of DWORD
-        [InlineData("C280" + "C2C0", 2, "\u0080")] // Improperly terminated 2-byte sequence at end of DWORD
-        [InlineData("C280" + "C280" + "80203040", 4, "\u0080\u0080")] // Continuation character at start of sequence, within "stay in 2-byte processing" optimization
-        [InlineData("C280" + "C280" + "C180" + "C280", 4, "\u0080\u0080")] // Overlong 2-byte sequence at start of DWORD, within "stay in 2-byte processing" optimization
-        [InlineData("C280" + "C280" + "C280" + "C180", 6, "\u0080\u0080\u0080")] // Overlong 2-byte sequence at end of DWORD, within "stay in 2-byte processing" optimization
-        [InlineData("3031" + "E09F80" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Overlong 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E07F80" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Improperly terminated 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E0C080" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Improperly terminated 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E17F80" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Improperly terminated 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E1C080" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Improperly terminated 3-byte sequence at start of DWORD
-        [InlineData("3031" + "EDA080" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Surrogate 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E69C88" + "E59B" + "E69C88", 5, "01\u6708")] // Incomplete 3-byte sequence surrounded by valid 3-byte sequences
-        [InlineData("3031" + "F5808080", 2, "01")] // [ F5 ] is always invalid
-        [InlineData("3031" + "F6808080", 2, "01")] // [ F6 ] is always invalid
-        [InlineData("3031" + "F7808080", 2, "01")] // [ F7 ] is always invalid
-        [InlineData("3031" + "F8808080", 2, "01")] // [ F8 ] is always invalid
-        [InlineData("3031" + "F9808080", 2, "01")] // [ F9 ] is always invalid
-        [InlineData("3031" + "FA808080", 2, "01")] // [ FA ] is always invalid
-        [InlineData("3031" + "FB808080", 2, "01")] // [ FB ] is always invalid
-        [InlineData("3031" + "FC808080", 2, "01")] // [ FC ] is always invalid
-        [InlineData("3031" + "FD808080", 2, "01")] // [ FD ] is always invalid
-        [InlineData("3031" + "FE808080", 2, "01")] // [ FE ] is always invalid
-        [InlineData("3031" + "FF808080", 2, "01")] // [ FF ] is always invalid
-        public void ToChars_WithLargeInvalidBuffers(string utf8HexInput, int expectedNumBytesConsumed, string expectedUtf16Transcoding)
-        {
-            // These test cases are for the "fast processing" code which is the main loop of TranscodeToUtf16,
-            // so inputs should be less >= 4 bytes.
-
-            Assert.True(utf8HexInput.Length >= 8);
-
-            ToChars_Test_Core(
-                utf8Input: DecodeHex(utf8HexInput),
-                destinationSize: expectedUtf16Transcoding.Length,
-                replaceInvalidSequences: false,
-                isFinalChunk: false,
-                expectedOperationStatus: OperationStatus.InvalidData,
-                expectedNumBytesRead: expectedNumBytesConsumed,
-                expectedUtf16Transcoding: expectedUtf16Transcoding);
-
-            // Now try the tests again with a larger buffer.
-            // This ensures that running out of destination space wasn't the reason we failed.
-
-            ToChars_Test_Core(
-                utf8Input: DecodeHex(utf8HexInput),
-                destinationSize: expectedUtf16Transcoding.Length + 16,
-                replaceInvalidSequences: false,
-                isFinalChunk: false,
-                expectedOperationStatus: OperationStatus.InvalidData,
-                expectedNumBytesRead: expectedNumBytesConsumed,
-                expectedUtf16Transcoding: expectedUtf16Transcoding);
-        }
-
-        [Theory]
-        [InlineData(X_UTF8 + "80" + X_UTF8, X_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // stray continuation byte [ 80 ]
-        [InlineData(X_UTF8 + "FF" + X_UTF8, X_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // invalid UTF-8 byte [ FF ]
-        [InlineData(X_UTF8 + "C2" + X_UTF8, X_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // 2-byte sequence starter [ C2 ] not followed by continuation byte
-        [InlineData(X_UTF8 + "C1C180" + X_UTF8, X_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ C1 80 ] is overlong but consists of two maximal invalid subsequences, each of length 1 byte
-        [InlineData(X_UTF8 + E_ACUTE_UTF8 + "E08080", X_UTF16 + E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16)] // [ E0 80 ] is overlong 2-byte sequence (1 byte maximal invalid subsequence), and following [ 80 ] is stray continuation byte
-        [InlineData(GRINNING_FACE_UTF8 + "F08F8080" + GRINNING_FACE_UTF8, GRINNING_FACE_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + GRINNING_FACE_UTF16)] // [ F0 8F ] is overlong 4-byte sequence (1 byte maximal invalid subsequence), and following [ 80 ] instances are stray continuation bytes
-        [InlineData(GRINNING_FACE_UTF8 + "F4908080" + GRINNING_FACE_UTF8, GRINNING_FACE_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + GRINNING_FACE_UTF16)] // [ F4 90 ] is out-of-range 4-byte sequence (1 byte maximal invalid subsequence), and following [ 80 ] instances are stray continuation bytes
-        [InlineData(E_ACUTE_UTF8 + "EDA0" + X_UTF8, E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ ED A0 ] is encoding of UTF-16 surrogate code point, so consists of two maximal invalid subsequences, each of length 1 byte
-        [InlineData(E_ACUTE_UTF8 + "ED80" + X_UTF8, E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ ED 80 ] is incomplete 3-byte sequence, so is 2-byte maximal invalid subsequence
-        [InlineData(E_ACUTE_UTF8 + "F380" + X_UTF8, E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ F3 80 ] is incomplete 4-byte sequence, so is 2-byte maximal invalid subsequence
-        [InlineData(E_ACUTE_UTF8 + "F38080" + X_UTF8, E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ F3 80 80 ] is incomplete 4-byte sequence, so is 3-byte maximal invalid subsequence
-        public void ToChars_WithReplacement(string utf8HexInput, string expectedUtf16Transcoding)
-        {
-            // First run the test with isFinalBlock = false,
-            // both with and without some bytes of incomplete trailing data.
-
-            ToChars_Test_Core(
-                utf8Input: DecodeHex(utf8HexInput),
-                destinationSize: expectedUtf16Transcoding.Length,
-                replaceInvalidSequences: true,
-                isFinalChunk: false,
-                expectedOperationStatus: OperationStatus.Done,
-                expectedNumBytesRead: utf8HexInput.Length / 2,
-                expectedUtf16Transcoding: expectedUtf16Transcoding);
-
-            ToChars_Test_Core(
-                utf8Input: DecodeHex(utf8HexInput + "E0BF" /* trailing data */),
-                destinationSize: expectedUtf16Transcoding.Length,
-                replaceInvalidSequences: true,
-                isFinalChunk: false,
-                expectedOperationStatus: OperationStatus.NeedMoreData,
-                expectedNumBytesRead: utf8HexInput.Length / 2,
-                expectedUtf16Transcoding: expectedUtf16Transcoding);
-
-            // Then run the test with isFinalBlock = true, with incomplete trailing data.
-
-            ToChars_Test_Core(
-                utf8Input: DecodeHex(utf8HexInput + "E0BF" /* trailing data */),
-                destinationSize: expectedUtf16Transcoding.Length,
-                replaceInvalidSequences: true,
-                isFinalChunk: true,
-                expectedOperationStatus: OperationStatus.DestinationTooSmall,
-                expectedNumBytesRead: utf8HexInput.Length / 2,
-                expectedUtf16Transcoding: expectedUtf16Transcoding);
-
-            ToChars_Test_Core(
-                 utf8Input: DecodeHex(utf8HexInput + "E0BF" /* trailing data */),
-                 destinationSize: expectedUtf16Transcoding.Length + 1, // allow room for U+FFFD
-                 replaceInvalidSequences: true,
-                 isFinalChunk: true,
-                 expectedOperationStatus: OperationStatus.Done,
-                 expectedNumBytesRead: utf8HexInput.Length / 2 + 2,
-                 expectedUtf16Transcoding: expectedUtf16Transcoding + REPLACEMENT_CHAR_UTF16);
-        }
-
-        [Fact]
-        public void ToChars_AllPossibleScalarValues()
-        {
-            ToChars_Test_Core(
-                utf8Input: s_allScalarsAsUtf8.Span,
-                destinationSize: s_allScalarsAsUtf16.Length,
-                replaceInvalidSequences: false,
-                isFinalChunk: false,
-                expectedOperationStatus: OperationStatus.Done,
-                expectedNumBytesRead: s_allScalarsAsUtf8.Length,
-                expectedUtf16Transcoding: s_allScalarsAsUtf16.Span);
-        }
-
-        private static void ToChars_Test_Core(ReadOnlySpan<byte> utf8Input, int destinationSize, bool replaceInvalidSequences, bool isFinalChunk, OperationStatus expectedOperationStatus, int expectedNumBytesRead, ReadOnlySpan<char> expectedUtf16Transcoding)
-        {
-            // Arrange
-
-            using (BoundedMemory<byte> boundedSource = BoundedMemory.AllocateFromExistingData(utf8Input))
-            using (BoundedMemory<char> boundedDestination = BoundedMemory.Allocate<char>(destinationSize))
-            {
-                boundedSource.MakeReadonly();
-
-                // Act
-
-                OperationStatus actualOperationStatus = Utf8.ToUtf16(boundedSource.Span, boundedDestination.Span, out int actualNumBytesRead, out int actualNumCharsWritten, replaceInvalidSequences, isFinalChunk);
-
-                // Assert
-
-                Assert.Equal(expectedOperationStatus, actualOperationStatus);
-                Assert.Equal(expectedNumBytesRead, actualNumBytesRead);
-                Assert.Equal(expectedUtf16Transcoding.Length, actualNumCharsWritten);
-                Assert.Equal(expectedUtf16Transcoding.ToString(), boundedDestination.Span.Slice(0, actualNumCharsWritten).ToString());
-            }
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.cs
new file mode 100644 (file)
index 0000000..b633a50
--- /dev/null
@@ -0,0 +1,790 @@
+// 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 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
+        [InlineData("838485", 0, "")] // sequence cannot begin with continuation character
+        [InlineData(X_UTF8 + "80", 1, X_UTF16)] // sequence cannot begin with continuation character
+        [InlineData(X_UTF8 + "8182", 1, X_UTF16)] // sequence cannot begin with continuation character
+        [InlineData("C0", 0, "")] // [ C0 ] is always invalid
+        [InlineData("C080", 0, "")] // [ C0 ] is always invalid
+        [InlineData("C08081", 0, "")] // [ C0 ] is always invalid
+        [InlineData(X_UTF8 + "C1", 1, X_UTF16)] // [ C1 ] is always invalid
+        [InlineData(X_UTF8 + "C180", 1, X_UTF16)] // [ C1 ] is always invalid
+        [InlineData(X_UTF8 + "C27F", 1, X_UTF16)] // [ C2 ] is improperly terminated
+        [InlineData("E2827F", 0, "")] // [ E2 82 ] is improperly terminated
+        [InlineData("E09F80", 0, "")] // [ E0 9F ... ] is overlong
+        [InlineData("E0C080", 0, "")] // [ E0 ] is improperly terminated
+        [InlineData("ED7F80", 0, "")] // [ ED ] is improperly terminated
+        [InlineData("EDA080", 0, "")] // [ ED A0 ... ] is surrogate
+        public void ToChars_WithSmallInvalidBuffers(string utf8HexInput, int expectedNumBytesConsumed, string expectedUtf16Transcoding)
+        {
+            // These test cases are for the "slow processing" code path at the end of TranscodeToUtf16,
+            // so inputs should be less than 4 bytes.
+
+            Assert.InRange(utf8HexInput.Length, 0, 6);
+
+            ToChars_Test_Core(
+              utf8Input: DecodeHex(utf8HexInput),
+              destinationSize: expectedUtf16Transcoding.Length,
+              replaceInvalidSequences: false,
+              isFinalChunk: false,
+              expectedOperationStatus: OperationStatus.InvalidData,
+              expectedNumBytesRead: expectedNumBytesConsumed,
+              expectedUtf16Transcoding: expectedUtf16Transcoding);
+
+            // Now try the tests again with a larger buffer.
+            // This ensures that running out of destination space wasn't the reason we failed.
+
+            ToChars_Test_Core(
+              utf8Input: DecodeHex(utf8HexInput),
+              destinationSize: expectedUtf16Transcoding.Length + 16,
+              replaceInvalidSequences: false,
+              isFinalChunk: false,
+              expectedOperationStatus: OperationStatus.InvalidData,
+              expectedNumBytesRead: expectedNumBytesConsumed,
+              expectedUtf16Transcoding: expectedUtf16Transcoding);
+        }
+
+        [Theory]
+        [InlineData("C2", 0, "")] // [ C2 ] is an incomplete sequence
+        [InlineData("E282", 0, "")] // [ E2 82 ] is an incomplete sequence
+        [InlineData(X_UTF8 + "C2", 1, X_UTF16)] // [ C2 ] is an incomplete sequence
+        [InlineData(X_UTF8 + "E0", 1, X_UTF16)] // [ E0 ] is an incomplete sequence
+        [InlineData(X_UTF8 + "E0BF", 1, X_UTF16)] // [ E0 BF ] is an incomplete sequence
+        [InlineData(X_UTF8 + "F0", 1, X_UTF16)] // [ F0 ] is an incomplete sequence
+        [InlineData(X_UTF8 + "F0BF", 1, X_UTF16)] // [ F0 BF ] is an incomplete sequence
+        [InlineData(X_UTF8 + "F0BFA0", 1, X_UTF16)] // [ F0 BF A0 ] is an incomplete sequence
+        [InlineData(E_ACUTE_UTF8 + "C2", 2, E_ACUTE_UTF16)] // [ C2 ] is an incomplete sequence
+        [InlineData(E_ACUTE_UTF8 + "E0", 2, E_ACUTE_UTF16)] // [ E0 ] is an incomplete sequence
+        [InlineData(E_ACUTE_UTF8 + "F0", 2, E_ACUTE_UTF16)] // [ F0 ] is an incomplete sequence
+        [InlineData(E_ACUTE_UTF8 + "E0BF", 2, E_ACUTE_UTF16)] // [ E0 BF ] is an incomplete sequence
+        [InlineData(E_ACUTE_UTF8 + "F0BF", 2, E_ACUTE_UTF16)] // [ F0 BF ] is an incomplete sequence
+        [InlineData(EURO_SYMBOL_UTF8 + "C2", 3, EURO_SYMBOL_UTF16)] // [ C2 ] is an incomplete sequence
+        [InlineData(EURO_SYMBOL_UTF8 + "E0", 3, EURO_SYMBOL_UTF16)] // [ E0 ] is an incomplete sequence
+        [InlineData(EURO_SYMBOL_UTF8 + "F0", 3, EURO_SYMBOL_UTF16)] // [ F0 ] is an incomplete sequence
+        public void ToChars_WithVariousIncompleteBuffers(string utf8HexInput, int expectedNumBytesConsumed, string expectedUtf16Transcoding)
+        {
+            // These test cases are for the "slow processing" code path at the end of TranscodeToUtf16,
+            // so inputs should be less than 4 bytes.
+
+            ToChars_Test_Core(
+              utf8Input: DecodeHex(utf8HexInput),
+              destinationSize: expectedUtf16Transcoding.Length,
+              replaceInvalidSequences: false,
+              isFinalChunk: false,
+              expectedOperationStatus: OperationStatus.NeedMoreData,
+              expectedNumBytesRead: expectedNumBytesConsumed,
+              expectedUtf16Transcoding: expectedUtf16Transcoding);
+
+            // Now try the tests again with a larger buffer.
+            // This ensures that running out of destination space wasn't the reason we failed.
+
+            ToChars_Test_Core(
+             utf8Input: DecodeHex(utf8HexInput),
+             destinationSize: expectedUtf16Transcoding.Length + 16,
+             replaceInvalidSequences: false,
+             isFinalChunk: false,
+             expectedOperationStatus: OperationStatus.NeedMoreData,
+             expectedNumBytesRead: expectedNumBytesConsumed,
+             expectedUtf16Transcoding: expectedUtf16Transcoding);
+        }
+
+        [Theory]
+        /* SMALL VALID BUFFERS - tests drain loop at end of method */
+        [InlineData("")] // empty string is OK
+        [InlineData("X")]
+        [InlineData("XY")]
+        [InlineData("XYZ")]
+        [InlineData(E_ACUTE_UTF16)]
+        [InlineData(X_UTF16 + E_ACUTE_UTF16)]
+        [InlineData(E_ACUTE_UTF16 + X_UTF16)]
+        [InlineData(EURO_SYMBOL_UTF16)]
+        /* LARGE VALID BUFFERS - test main loop at beginning of method */
+        [InlineData(E_ACUTE_UTF16 + "ABCD" + "0123456789:;<=>?")] // Loop unrolling at end of buffer
+        [InlineData(E_ACUTE_UTF16 + "ABCD" + "0123456789:;<=>?" + "01234567" + E_ACUTE_UTF16 + "89:;<=>?")] // Loop unrolling interrupted by non-ASCII
+        [InlineData("ABC" + E_ACUTE_UTF16 + "0123")] // 3 ASCII bytes followed by non-ASCII
+        [InlineData("AB" + E_ACUTE_UTF16 + "0123")] // 2 ASCII bytes followed by non-ASCII
+        [InlineData("A" + E_ACUTE_UTF16 + "0123")] // 1 ASCII byte followed by non-ASCII
+        [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16)] // 4x 2-byte sequences, exercises optimization code path in 2-byte sequence processing
+        [InlineData(E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + "PQ")] // 3x 2-byte sequences + 2 ASCII bytes, exercises optimization code path in 2-byte sequence processing
+        [InlineData(E_ACUTE_UTF16 + "PQ")] // single 2-byte sequence + 2 trailing ASCII bytes, exercises draining logic in 2-byte sequence processing
+        [InlineData(E_ACUTE_UTF16 + "P" + E_ACUTE_UTF16 + "0@P")] // single 2-byte sequences + 1 trailing ASCII byte + 2-byte sequence, exercises draining logic in 2-byte sequence processing
+        [InlineData(EURO_SYMBOL_UTF16 + "@")] // single 3-byte sequence + 1 trailing ASCII byte, exercises draining logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL_UTF16 + "@P`")] // single 3-byte sequence + 3 trailing ASCII byte, exercises draining logic and "running out of data" logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // 3x 3-byte sequences, exercises "stay within 3-byte loop" logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16)] // 4x 3-byte sequences, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + E_ACUTE_UTF16)] // 3x 3-byte sequences + single 2-byte sequence, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL_UTF16 + EURO_SYMBOL_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16 + E_ACUTE_UTF16)] // 2x 3-byte sequences + 4x 2-byte sequences, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
+        [InlineData(GRINNING_FACE_UTF16 + GRINNING_FACE_UTF16)] // 2x 4-byte sequences, exercises 4-byte sequence processing
+        [InlineData(GRINNING_FACE_UTF16 + "@AB")] // single 4-byte sequence + 3 ASCII bytes, exercises 4-byte sequence processing and draining logic
+        [InlineData(WOMAN_CARTWHEELING_MEDSKIN_UTF16)] // exercises switching between multiple sequence lengths
+        public void ToChars_ValidBuffers(string utf16Input)
+        {
+            // 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();
+
+            // Convert entire input to UTF-8 using our unit test reference logic.
+
+            byte[] utf8Input = enumeratedScalars.SelectMany(ToUtf8).ToArray();
+
+            // 0-length buffer test
+            ToChars_Test_Core(
+                utf8Input: utf8Input,
+                destinationSize: 0,
+                replaceInvalidSequences: false,
+                isFinalChunk: false,
+                expectedOperationStatus: (utf8Input.Length == 0) ? OperationStatus.Done : OperationStatus.DestinationTooSmall,
+                expectedNumBytesRead: 0,
+                expectedUtf16Transcoding: ReadOnlySpan<char>.Empty);
+
+            int expectedNumBytesConsumed = 0;
+            char[] concatenatedUtf16 = Array.Empty<char>();
+
+            for (int i = 0; i < enumeratedScalars.Length; i++)
+            {
+                Rune thisScalar = enumeratedScalars[i];
+
+                // if this is an astral scalar value, quickly test a buffer that's not large enough to contain the entire UTF-16 encoding
+
+                if (!thisScalar.IsBmp)
+                {
+                    ToChars_Test_Core(
+                        utf8Input: utf8Input,
+                        destinationSize: concatenatedUtf16.Length + 1,
+                        replaceInvalidSequences: false,
+                        isFinalChunk: false,
+                        expectedOperationStatus: OperationStatus.DestinationTooSmall,
+                        expectedNumBytesRead: expectedNumBytesConsumed,
+                        expectedUtf16Transcoding: concatenatedUtf16);
+                }
+
+                // now provide a destination buffer large enough to hold the next full scalar encoding
+
+                expectedNumBytesConsumed += thisScalar.Utf8SequenceLength;
+                concatenatedUtf16 = concatenatedUtf16.Concat(ToUtf16(thisScalar)).ToArray();
+
+                ToChars_Test_Core(
+                    utf8Input: utf8Input,
+                    destinationSize: concatenatedUtf16.Length,
+                    replaceInvalidSequences: false,
+                    isFinalChunk: false,
+                    expectedOperationStatus: (i == enumeratedScalars.Length - 1) ? OperationStatus.Done : OperationStatus.DestinationTooSmall,
+                    expectedNumBytesRead: expectedNumBytesConsumed,
+                    expectedUtf16Transcoding: concatenatedUtf16);
+            }
+
+            // now throw lots of ASCII data at the beginning so that we exercise the vectorized code paths
+
+            utf16Input = new string('x', 64) + utf16Input;
+            utf8Input = utf16Input.EnumerateRunes().SelectMany(ToUtf8).ToArray();
+
+            ToChars_Test_Core(
+                utf8Input: utf8Input,
+                destinationSize: utf16Input.Length,
+                replaceInvalidSequences: false,
+                isFinalChunk: true,
+                expectedOperationStatus: OperationStatus.Done,
+                expectedNumBytesRead: utf8Input.Length,
+                expectedUtf16Transcoding: utf16Input);
+
+            // 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..];
+            utf8Input = utf16Input.EnumerateRunes().SelectMany(ToUtf8).ToArray();
+
+            ToChars_Test_Core(
+                utf8Input: utf8Input,
+                destinationSize: utf16Input.Length,
+                replaceInvalidSequences: false,
+                isFinalChunk: true,
+                expectedOperationStatus: OperationStatus.Done,
+                expectedNumBytesRead: utf8Input.Length,
+                expectedUtf16Transcoding: utf16Input);
+        }
+
+        [Theory]
+        [InlineData("3031" + "80" + "202122232425", 2, "01")] // Continuation character at start of sequence should match no bitmask
+        [InlineData("3031" + "C080" + "2021222324", 2, "01")] // Overlong 2-byte sequence at start of DWORD
+        [InlineData("3031" + "C180" + "2021222324", 2, "01")] // Overlong 2-byte sequence at start of DWORD
+        [InlineData("C280" + "C180", 2, "\u0080")] // Overlong 2-byte sequence at end of DWORD
+        [InlineData("C27F" + "C280", 0, "")] // Improperly terminated 2-byte sequence at start of DWORD
+        [InlineData("C2C0" + "C280", 0, "")] // Improperly terminated 2-byte sequence at start of DWORD
+        [InlineData("C280" + "C27F", 2, "\u0080")] // Improperly terminated 2-byte sequence at end of DWORD
+        [InlineData("C280" + "C2C0", 2, "\u0080")] // Improperly terminated 2-byte sequence at end of DWORD
+        [InlineData("C280" + "C280" + "80203040", 4, "\u0080\u0080")] // Continuation character at start of sequence, within "stay in 2-byte processing" optimization
+        [InlineData("C280" + "C280" + "C180" + "C280", 4, "\u0080\u0080")] // Overlong 2-byte sequence at start of DWORD, within "stay in 2-byte processing" optimization
+        [InlineData("C280" + "C280" + "C280" + "C180", 6, "\u0080\u0080\u0080")] // Overlong 2-byte sequence at end of DWORD, within "stay in 2-byte processing" optimization
+        [InlineData("3031" + "E09F80" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Overlong 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E07F80" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Improperly terminated 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E0C080" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Improperly terminated 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E17F80" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Improperly terminated 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E1C080" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Improperly terminated 3-byte sequence at start of DWORD
+        [InlineData("3031" + "EDA080" + EURO_SYMBOL_UTF8 + EURO_SYMBOL_UTF8, 2, "01")] // Surrogate 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E69C88" + "E59B" + "E69C88", 5, "01\u6708")] // Incomplete 3-byte sequence surrounded by valid 3-byte sequences
+        [InlineData("3031" + "F5808080", 2, "01")] // [ F5 ] is always invalid
+        [InlineData("3031" + "F6808080", 2, "01")] // [ F6 ] is always invalid
+        [InlineData("3031" + "F7808080", 2, "01")] // [ F7 ] is always invalid
+        [InlineData("3031" + "F8808080", 2, "01")] // [ F8 ] is always invalid
+        [InlineData("3031" + "F9808080", 2, "01")] // [ F9 ] is always invalid
+        [InlineData("3031" + "FA808080", 2, "01")] // [ FA ] is always invalid
+        [InlineData("3031" + "FB808080", 2, "01")] // [ FB ] is always invalid
+        [InlineData("3031" + "FC808080", 2, "01")] // [ FC ] is always invalid
+        [InlineData("3031" + "FD808080", 2, "01")] // [ FD ] is always invalid
+        [InlineData("3031" + "FE808080", 2, "01")] // [ FE ] is always invalid
+        [InlineData("3031" + "FF808080", 2, "01")] // [ FF ] is always invalid
+        public void ToChars_WithLargeInvalidBuffers(string utf8HexInput, int expectedNumBytesConsumed, string expectedUtf16Transcoding)
+        {
+            // These test cases are for the "fast processing" code which is the main loop of TranscodeToUtf16,
+            // so inputs should be less >= 4 bytes.
+
+            Assert.True(utf8HexInput.Length >= 8);
+
+            ToChars_Test_Core(
+                utf8Input: DecodeHex(utf8HexInput),
+                destinationSize: expectedUtf16Transcoding.Length,
+                replaceInvalidSequences: false,
+                isFinalChunk: false,
+                expectedOperationStatus: OperationStatus.InvalidData,
+                expectedNumBytesRead: expectedNumBytesConsumed,
+                expectedUtf16Transcoding: expectedUtf16Transcoding);
+
+            // Now try the tests again with a larger buffer.
+            // This ensures that running out of destination space wasn't the reason we failed.
+
+            ToChars_Test_Core(
+                utf8Input: DecodeHex(utf8HexInput),
+                destinationSize: expectedUtf16Transcoding.Length + 16,
+                replaceInvalidSequences: false,
+                isFinalChunk: false,
+                expectedOperationStatus: OperationStatus.InvalidData,
+                expectedNumBytesRead: expectedNumBytesConsumed,
+                expectedUtf16Transcoding: expectedUtf16Transcoding);
+        }
+
+        [Theory]
+        [InlineData(X_UTF8 + "80" + X_UTF8, X_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // stray continuation byte [ 80 ]
+        [InlineData(X_UTF8 + "FF" + X_UTF8, X_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // invalid UTF-8 byte [ FF ]
+        [InlineData(X_UTF8 + "C2" + X_UTF8, X_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // 2-byte sequence starter [ C2 ] not followed by continuation byte
+        [InlineData(X_UTF8 + "C1C180" + X_UTF8, X_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ C1 80 ] is overlong but consists of two maximal invalid subsequences, each of length 1 byte
+        [InlineData(X_UTF8 + E_ACUTE_UTF8 + "E08080", X_UTF16 + E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16)] // [ E0 80 ] is overlong 2-byte sequence (1 byte maximal invalid subsequence), and following [ 80 ] is stray continuation byte
+        [InlineData(GRINNING_FACE_UTF8 + "F08F8080" + GRINNING_FACE_UTF8, GRINNING_FACE_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + GRINNING_FACE_UTF16)] // [ F0 8F ] is overlong 4-byte sequence (1 byte maximal invalid subsequence), and following [ 80 ] instances are stray continuation bytes
+        [InlineData(GRINNING_FACE_UTF8 + "F4908080" + GRINNING_FACE_UTF8, GRINNING_FACE_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + GRINNING_FACE_UTF16)] // [ F4 90 ] is out-of-range 4-byte sequence (1 byte maximal invalid subsequence), and following [ 80 ] instances are stray continuation bytes
+        [InlineData(E_ACUTE_UTF8 + "EDA0" + X_UTF8, E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ ED A0 ] is encoding of UTF-16 surrogate code point, so consists of two maximal invalid subsequences, each of length 1 byte
+        [InlineData(E_ACUTE_UTF8 + "ED80" + X_UTF8, E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ ED 80 ] is incomplete 3-byte sequence, so is 2-byte maximal invalid subsequence
+        [InlineData(E_ACUTE_UTF8 + "F380" + X_UTF8, E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ F3 80 ] is incomplete 4-byte sequence, so is 2-byte maximal invalid subsequence
+        [InlineData(E_ACUTE_UTF8 + "F38080" + X_UTF8, E_ACUTE_UTF16 + REPLACEMENT_CHAR_UTF16 + X_UTF16)] // [ F3 80 80 ] is incomplete 4-byte sequence, so is 3-byte maximal invalid subsequence
+        public void ToChars_WithReplacement(string utf8HexInput, string expectedUtf16Transcoding)
+        {
+            // First run the test with isFinalBlock = false,
+            // both with and without some bytes of incomplete trailing data.
+
+            ToChars_Test_Core(
+                utf8Input: DecodeHex(utf8HexInput),
+                destinationSize: expectedUtf16Transcoding.Length,
+                replaceInvalidSequences: true,
+                isFinalChunk: false,
+                expectedOperationStatus: OperationStatus.Done,
+                expectedNumBytesRead: utf8HexInput.Length / 2,
+                expectedUtf16Transcoding: expectedUtf16Transcoding);
+
+            ToChars_Test_Core(
+                utf8Input: DecodeHex(utf8HexInput + "E0BF" /* trailing data */),
+                destinationSize: expectedUtf16Transcoding.Length,
+                replaceInvalidSequences: true,
+                isFinalChunk: false,
+                expectedOperationStatus: OperationStatus.NeedMoreData,
+                expectedNumBytesRead: utf8HexInput.Length / 2,
+                expectedUtf16Transcoding: expectedUtf16Transcoding);
+
+            // Then run the test with isFinalBlock = true, with incomplete trailing data.
+
+            ToChars_Test_Core(
+                utf8Input: DecodeHex(utf8HexInput + "E0BF" /* trailing data */),
+                destinationSize: expectedUtf16Transcoding.Length,
+                replaceInvalidSequences: true,
+                isFinalChunk: true,
+                expectedOperationStatus: OperationStatus.DestinationTooSmall,
+                expectedNumBytesRead: utf8HexInput.Length / 2,
+                expectedUtf16Transcoding: expectedUtf16Transcoding);
+
+            ToChars_Test_Core(
+                 utf8Input: DecodeHex(utf8HexInput + "E0BF" /* trailing data */),
+                 destinationSize: expectedUtf16Transcoding.Length + 1, // allow room for U+FFFD
+                 replaceInvalidSequences: true,
+                 isFinalChunk: true,
+                 expectedOperationStatus: OperationStatus.Done,
+                 expectedNumBytesRead: utf8HexInput.Length / 2 + 2,
+                 expectedUtf16Transcoding: expectedUtf16Transcoding + REPLACEMENT_CHAR_UTF16);
+        }
+
+        [Fact]
+        public void ToChars_AllPossibleScalarValues()
+        {
+            ToChars_Test_Core(
+                utf8Input: s_allScalarsAsUtf8.Span,
+                destinationSize: s_allScalarsAsUtf16.Length,
+                replaceInvalidSequences: false,
+                isFinalChunk: false,
+                expectedOperationStatus: OperationStatus.Done,
+                expectedNumBytesRead: s_allScalarsAsUtf8.Length,
+                expectedUtf16Transcoding: s_allScalarsAsUtf16.Span);
+        }
+
+        private static void ToChars_Test_Core(ReadOnlySpan<byte> utf8Input, int destinationSize, bool replaceInvalidSequences, bool isFinalChunk, OperationStatus expectedOperationStatus, int expectedNumBytesRead, ReadOnlySpan<char> expectedUtf16Transcoding)
+        {
+            // Arrange
+
+            using (BoundedMemory<byte> boundedSource = BoundedMemory.AllocateFromExistingData(utf8Input))
+            using (BoundedMemory<char> boundedDestination = BoundedMemory.Allocate<char>(destinationSize))
+            {
+                boundedSource.MakeReadonly();
+
+                // Act
+
+                OperationStatus actualOperationStatus = Utf8.ToUtf16(boundedSource.Span, boundedDestination.Span, out int actualNumBytesRead, out int actualNumCharsWritten, replaceInvalidSequences, isFinalChunk);
+
+                // Assert
+
+                Assert.Equal(expectedOperationStatus, actualOperationStatus);
+                Assert.Equal(expectedNumBytesRead, actualNumBytesRead);
+                Assert.Equal(expectedUtf16Transcoding.Length, actualNumCharsWritten);
+                Assert.Equal(expectedUtf16Transcoding.ToString(), boundedDestination.Span.Slice(0, actualNumCharsWritten).ToString());
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8Tests.netcoreapp.cs
deleted file mode 100644 (file)
index f57c769..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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)
-                };
-            }
-        }
-    }
-}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8UtilityTests.ValidateBytes.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8UtilityTests.ValidateBytes.cs
new file mode 100644 (file)
index 0000000..5289f03
--- /dev/null
@@ -0,0 +1,418 @@
+// 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 System.Reflection;
+using System.Runtime.InteropServices;
+using Xunit;
+
+namespace System.Text.Unicode.Tests
+{
+    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();
+
+        private const string X = "58"; // U+0058 LATIN CAPITAL LETTER X, 1 byte
+        private const string Y = "59"; // U+0058 LATIN CAPITAL LETTER Y, 1 byte
+        private const string Z = "5A"; // U+0058 LATIN CAPITAL LETTER Z, 1 byte
+        private const string E_ACUTE = "C3A9"; // U+00E9 LATIN SMALL LETTER E WITH ACUTE, 2 bytes
+        private const string EURO_SYMBOL = "E282AC"; // U+20AC EURO SIGN, 3 bytes
+        private const string GRINNING_FACE = "F09F9880"; // U+1F600 GRINNING FACE, 4 bytes
+
+        [Theory]
+        [InlineData("", 0, 0)] // empty string is OK
+        [InlineData(X, 1, 0)]
+        [InlineData(X + Y, 2, 0)]
+        [InlineData(X + Y + Z, 3, 0)]
+        [InlineData(E_ACUTE, 1, 0)]
+        [InlineData(X + E_ACUTE, 2, 0)]
+        [InlineData(E_ACUTE + X, 2, 0)]
+        [InlineData(EURO_SYMBOL, 1, 0)]
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithSmallValidBuffers(string input, int expectedRuneCount, int expectedSurrogatePairCount)
+        {
+            // These test cases are for the "slow processing" code path at the end of GetIndexOfFirstInvalidUtf8Sequence,
+            // so inputs should be less than 4 bytes.
+
+            Assert.InRange(input.Length, 0, 6);
+
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(input, -1 /* expectedRetVal */, expectedRuneCount, expectedSurrogatePairCount);
+        }
+
+        [Theory]
+        [InlineData("80", 0, 0, 0)] // sequence cannot begin with continuation character
+        [InlineData("8182", 0, 0, 0)] // sequence cannot begin with continuation character
+        [InlineData("838485", 0, 0, 0)] // sequence cannot begin with continuation character
+        [InlineData(X + "80", 1, 1, 0)] // sequence cannot begin with continuation character
+        [InlineData(X + "8182", 1, 1, 0)] // sequence cannot begin with continuation character
+        [InlineData("C0", 0, 0, 0)] // [ C0 ] is always invalid
+        [InlineData("C080", 0, 0, 0)] // [ C0 ] is always invalid
+        [InlineData("C08081", 0, 0, 0)] // [ C0 ] is always invalid
+        [InlineData(X + "C1", 1, 1, 0)] // [ C1 ] is always invalid
+        [InlineData(X + "C180", 1, 1, 0)] // [ C1 ] is always invalid
+        [InlineData("C2", 0, 0, 0)] // [ C2 ] is improperly terminated
+        [InlineData(X + "C27F", 1, 1, 0)] // [ C2 ] is improperly terminated
+        [InlineData(X + "E282", 1, 1, 0)] // [ E2 82 ] is improperly terminated
+        [InlineData("E2827F", 0, 0, 0)] // [ E2 82 ] is improperly terminated
+        [InlineData("E09F80", 0, 0, 0)] // [ E0 9F ... ] is overlong
+        [InlineData("E0C080", 0, 0, 0)] // [ E0 ] is improperly terminated
+        [InlineData("ED7F80", 0, 0, 0)] // [ ED ] is improperly terminated
+        [InlineData("EDA080", 0, 0, 0)] // [ ED A0 ... ] is surrogate
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithSmallInvalidBuffers(string input, int expectedRetVal, int expectedRuneCount, int expectedSurrogatePairCount)
+        {
+            // These test cases are for the "slow processing" code path at the end of GetIndexOfFirstInvalidUtf8Sequence,
+            // so inputs should be less than 4 bytes.
+
+            Assert.InRange(input.Length, 0, 6);
+
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(input, expectedRetVal, expectedRuneCount, expectedSurrogatePairCount);
+        }
+
+        [Theory]
+        [InlineData(E_ACUTE + "21222324" + "303132333435363738393A3B3C3D3E3F", 21, 0)] // Loop unrolling at end of buffer
+        [InlineData(E_ACUTE + "21222324" + "303132333435363738393A3B3C3D3E3F" + "3031323334353637" + E_ACUTE + "38393A3B3C3D3E3F", 38, 0)] // Loop unrolling interrupted by non-ASCII
+        [InlineData("212223" + E_ACUTE + "30313233", 8, 0)] // 3 ASCII bytes followed by non-ASCII
+        [InlineData("2122" + E_ACUTE + "30313233", 7, 0)] // 2 ASCII bytes followed by non-ASCII
+        [InlineData("21" + E_ACUTE + "30313233", 6, 0)] // 1 ASCII byte followed by non-ASCII
+        [InlineData(E_ACUTE + E_ACUTE + E_ACUTE + E_ACUTE, 4, 0)] // 4x 2-byte sequences, exercises optimization code path in 2-byte sequence processing
+        [InlineData(E_ACUTE + E_ACUTE + E_ACUTE + "5051", 5, 0)] // 3x 2-byte sequences + 2 ASCII bytes, exercises optimization code path in 2-byte sequence processing
+        [InlineData(E_ACUTE + "5051", 3, 0)] // single 2-byte sequence + 2 trailing ASCII bytes, exercises draining logic in 2-byte sequence processing
+        [InlineData(E_ACUTE + "50" + E_ACUTE + "304050", 6, 0)] // single 2-byte sequences + 1 trailing ASCII byte + 2-byte sequence, exercises draining logic in 2-byte sequence processing
+        [InlineData(EURO_SYMBOL + "20", 2, 0)] // single 3-byte sequence + 1 trailing ASCII byte, exercises draining logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL + "203040", 4, 0)] // single 3-byte sequence + 3 trailing ASCII byte, exercises draining logic and "running out of data" logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL + EURO_SYMBOL + EURO_SYMBOL, 3, 0)] // 3x 3-byte sequences, exercises "stay within 3-byte loop" logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL + EURO_SYMBOL + EURO_SYMBOL + EURO_SYMBOL, 4, 0)] // 4x 3-byte sequences, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL + EURO_SYMBOL + EURO_SYMBOL + E_ACUTE, 4, 0)] // 3x 3-byte sequences + single 2-byte sequence, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
+        [InlineData(EURO_SYMBOL + EURO_SYMBOL + E_ACUTE + E_ACUTE + E_ACUTE + E_ACUTE, 6, 0)] // 2x 3-byte sequences + 4x 2-byte sequences, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
+        [InlineData(GRINNING_FACE + GRINNING_FACE, 2, 2)] // 2x 4-byte sequences, exercises 4-byte sequence processing
+        [InlineData(GRINNING_FACE + "303132", 4, 1)] // single 4-byte sequence + 3 ASCII bytes, exercises 4-byte sequence processing and draining logic
+        [InlineData("F09FA4B8" + "F09F8FBD" + "E2808D" + "E29980" + "EFB88F", 5, 2)] // U+1F938 U+1F3FD U+200D U+2640 U+FE0F WOMAN CARTWHEELING: MEDIUM SKIN TONE, exercising switching between multiple sequence lengths
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithLargeValidBuffers(string input, int expectedRuneCount, int expectedSurrogatePairCount)
+        {
+            // These test cases are for the "fast processing" code which is the main loop of GetIndexOfFirstInvalidUtf8Sequence,
+            // so inputs should be less >= 4 bytes.
+
+            Assert.True(input.Length >= 8);
+
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(input, -1 /* expectedRetVal */, expectedRuneCount, expectedSurrogatePairCount);
+        }
+
+        [Theory]
+        [InlineData("3031" + "80" + "202122232425", 2, 2, 0)] // Continuation character at start of sequence should match no bitmask
+        [InlineData("3031" + "C080" + "2021222324", 2, 2, 0)] // Overlong 2-byte sequence at start of DWORD
+        [InlineData("3031" + "C180" + "2021222324", 2, 2, 0)] // Overlong 2-byte sequence at start of DWORD
+        [InlineData("C280" + "C180", 2, 1, 0)] // Overlong 2-byte sequence at end of DWORD
+        [InlineData("C27F" + "C280", 0, 0, 0)] // Improperly terminated 2-byte sequence at start of DWORD
+        [InlineData("C2C0" + "C280", 0, 0, 0)] // Improperly terminated 2-byte sequence at start of DWORD
+        [InlineData("C280" + "C27F", 2, 1, 0)] // Improperly terminated 2-byte sequence at end of DWORD
+        [InlineData("C280" + "C2C0", 2, 1, 0)] // Improperly terminated 2-byte sequence at end of DWORD
+        [InlineData("C280" + "C280" + "80203040", 4, 2, 0)] // Continuation character at start of sequence, within "stay in 2-byte processing" optimization
+        [InlineData("C280" + "C280" + "C180" + "C280", 4, 2, 0)] // Overlong 2-byte sequence at start of DWORD, within "stay in 2-byte processing" optimization
+        [InlineData("C280" + "C280" + "C280" + "C180", 6, 3, 0)] // Overlong 2-byte sequence at end of DWORD, within "stay in 2-byte processing" optimization
+        [InlineData("3031" + "E09F80" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Overlong 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E07F80" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Improperly terminated 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E0C080" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Improperly terminated 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E17F80" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Improperly terminated 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E1C080" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Improperly terminated 3-byte sequence at start of DWORD
+        [InlineData("3031" + "EDA080" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Surrogate 3-byte sequence at start of DWORD
+        [InlineData("3031" + "E69C88" + "E59B" + "E69C88", 5, 3, 0)] // Incomplete 3-byte sequence surrounded by valid 3-byte sequences
+        [InlineData("E78B80" + "80", 3, 1, 0)] // Valid 3-byte sequence followed by standalone continuation byte
+        [InlineData("3031" + "F5808080", 2, 2, 0)] // [ F5 ] is always invalid
+        [InlineData("3031" + "F6808080", 2, 2, 0)] // [ F6 ] is always invalid
+        [InlineData("3031" + "F7808080", 2, 2, 0)] // [ F7 ] is always invalid
+        [InlineData("3031" + "F8808080", 2, 2, 0)] // [ F8 ] is always invalid
+        [InlineData("3031" + "F9808080", 2, 2, 0)] // [ F9 ] is always invalid
+        [InlineData("3031" + "FA808080", 2, 2, 0)] // [ FA ] is always invalid
+        [InlineData("3031" + "FB808080", 2, 2, 0)] // [ FB ] is always invalid
+        [InlineData("3031" + "FC808080", 2, 2, 0)] // [ FC ] is always invalid
+        [InlineData("3031" + "FD808080", 2, 2, 0)] // [ FD ] is always invalid
+        [InlineData("3031" + "FE808080", 2, 2, 0)] // [ FE ] is always invalid
+        [InlineData("3031" + "FF808080", 2, 2, 0)] // [ FF ] is always invalid
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithLargeInvalidBuffers(string input, int expectedRetVal, int expectedRuneCount, int expectedSurrogatePairCount)
+        {
+            // These test cases are for the "fast processing" code which is the main loop of GetIndexOfFirstInvalidUtf8Sequence,
+            // so inputs should be less >= 4 bytes.
+
+            Assert.True(input.Length >= 8);
+
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(input, expectedRetVal, expectedRuneCount, expectedSurrogatePairCount);
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithOverlongTwoByteSequences_ReturnsInvalid()
+        {
+            // [ C0 ] is never a valid byte, indicates overlong 2-byte sequence
+            // We'll test that [ C0 ] [ 00..FF ] is treated as invalid
+
+            for (int i = 0; i < 256; i++)
+            {
+                AssertIsInvalidTwoByteSequence(new byte[] { 0xC0, (byte)i });
+            }
+
+            // [ C1 ] is never a valid byte, indicates overlong 2-byte sequence
+            // We'll test that [ C1 ] [ 00..FF ] is treated as invalid
+
+            for (int i = 0; i < 256; i++)
+            {
+                AssertIsInvalidTwoByteSequence(new byte[] { 0xC1, (byte)i });
+            }
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithImproperlyTerminatedTwoByteSequences_ReturnsInvalid()
+        {
+            // Test [ C2..DF ] [ 00..7F ] and [ C2..DF ] [ C0..FF ]
+
+            for (int i = 0xC2; i < 0xDF; i++)
+            {
+                for (int j = 0; j < 0x80; j++)
+                {
+                    AssertIsInvalidTwoByteSequence(new byte[] { (byte)i, (byte)j });
+                }
+                for (int j = 0xC0; j < 0x100; j++)
+                {
+                    AssertIsInvalidTwoByteSequence(new byte[] { (byte)i, (byte)j });
+                }
+            }
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithOverlongThreeByteSequences_ReturnsInvalid()
+        {
+            // [ E0 ] [ 80..9F ] [ 80..BF ] is overlong 3-byte sequence
+
+            for (int i = 0x00; i < 0xA0; i++)
+            {
+                AssertIsInvalidThreeByteSequence(new byte[] { 0xE0, (byte)i, 0x80 });
+            }
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithSurrogateThreeByteSequences_ReturnsInvalid()
+        {
+            // [ ED ] [ A0..BF ] [ 80..BF ] is surrogate 3-byte sequence
+
+            for (int i = 0xA0; i < 0x100; i++)
+            {
+                AssertIsInvalidThreeByteSequence(new byte[] { 0xED, (byte)i, 0x80 });
+            }
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithImproperlyTerminatedThreeByteSequence_ReturnsInvalid()
+        {
+            // [ E0..EF ] [ 80..BF ] [ !(80..BF) ] is improperly terminated 3-byte sequence
+
+            for (int i = 0xE0; i < 0xF0; i++)
+            {
+                for (int j = 0x00; j < 0x80; j++)
+                {
+                    // Use both '9F' and 'A0' to make sure at least one isn't caught by overlong / surrogate checks
+                    AssertIsInvalidThreeByteSequence(new byte[] { (byte)i, 0x9F, (byte)j });
+                    AssertIsInvalidThreeByteSequence(new byte[] { (byte)i, 0xA0, (byte)j });
+                }
+                for (int j = 0xC0; j < 0x100; j++)
+                {
+                    // Use both '9F' and 'A0' to make sure at least one isn't caught by overlong / surrogate checks
+                    AssertIsInvalidThreeByteSequence(new byte[] { (byte)i, 0x9F, (byte)j });
+                    AssertIsInvalidThreeByteSequence(new byte[] { (byte)i, 0xA0, (byte)j });
+                }
+            }
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithOverlongFourByteSequences_ReturnsInvalid()
+        {
+            // [ F0 ] [ 80..8F ] [ 80..BF ] [ 80..BF ] is overlong 4-byte sequence
+
+            for (int i = 0x00; i < 0x90; i++)
+            {
+                AssertIsInvalidFourByteSequence(new byte[] { 0xF0, (byte)i, 0x80, 0x80 });
+            }
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithOutOfRangeFourByteSequences_ReturnsInvalid()
+        {
+            // [ F4 ] [ 90..BF ] [ 80..BF ] [ 80..BF ] is out-of-range 4-byte sequence
+
+            for (int i = 0x90; i < 0x100; i++)
+            {
+                AssertIsInvalidFourByteSequence(new byte[] { 0xF4, (byte)i, 0x80, 0x80 });
+            }
+        }
+
+        [Fact]
+        public void GetIndexOfFirstInvalidUtf8Sequence_WithInvalidFourByteSequence_ReturnsInvalid()
+        {
+            // [ F0..F4 ] [ !(80..BF) ] [ !(80..BF) ] [ !(80..BF) ] is improperly terminated 4-byte sequence
+
+            for (int i = 0xF0; i < 0xF5; i++)
+            {
+                for (int j = 0x00; j < 0x80; j++)
+                {
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, (byte)j, 0x80, 0x80 });
+
+                    // Use both '8F' and '90' to make sure at least one isn't caught by overlong / out-of-range checks
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0x9F, (byte)j, 0x80 });
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0xA0, (byte)j, 0x80 });
+
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0x9F, 0x80, (byte)j });
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0xA0, 0x80, (byte)j });
+                }
+                for (int j = 0xC0; j < 0x100; j++)
+                {
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, (byte)j, 0x80, 0x80 });
+
+                    // Use both '8F' and '90' to make sure at least one isn't caught by overlong / out-of-range checks
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0x9F, (byte)j, 0x80 });
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0xA0, (byte)j, 0x80 });
+
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0x9F, 0x80, (byte)j });
+                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0xA0, 0x80, (byte)j });
+                }
+            }
+        }
+
+        private static void AssertIsInvalidTwoByteSequence(byte[] invalidSequence)
+        {
+            Assert.Equal(2, invalidSequence.Length);
+
+            byte[] knownGoodBytes = Utf8Tests.DecodeHex(E_ACUTE);
+
+            byte[] toTest = invalidSequence.Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at start of first DWORD
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 0, 0, 0);
+
+            toTest = knownGoodBytes.Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at end of first DWORD
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 2, 1, 0);
+
+            // Run the same tests but with extra data at the beginning so that we're inside one of
+            // the 2-byte processing "hot loop" code paths.
+
+            toTest = knownGoodBytes.Concat(knownGoodBytes).Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at start of next DWORD
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 4, 2, 0);
+
+            toTest = knownGoodBytes.Concat(knownGoodBytes).Concat(knownGoodBytes).Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at end of next DWORD
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 6, 3, 0);
+        }
+
+        private static void AssertIsInvalidThreeByteSequence(byte[] invalidSequence)
+        {
+            Assert.Equal(3, invalidSequence.Length);
+
+            byte[] knownGoodBytes = Utf8Tests.DecodeHex(EURO_SYMBOL);
+
+            byte[] toTest = invalidSequence.Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at start of first DWORD
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 0, 0, 0);
+
+            // Run the same tests but with extra data at the beginning so that we're inside one of
+            // the 3-byte processing "hot loop" code paths.
+
+            toTest = knownGoodBytes.Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // straddling first and second DWORDs
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 3, 1, 0);
+
+            toTest = knownGoodBytes.Concat(knownGoodBytes).Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // straddling second and third DWORDs
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 6, 2, 0);
+
+            toTest = knownGoodBytes.Concat(knownGoodBytes).Concat(knownGoodBytes).Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at end of third DWORD
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 9, 3, 0);
+        }
+
+        private static void AssertIsInvalidFourByteSequence(byte[] invalidSequence)
+        {
+            Assert.Equal(4, invalidSequence.Length);
+
+            byte[] knownGoodBytes = Utf8Tests.DecodeHex(GRINNING_FACE);
+
+            byte[] toTest = invalidSequence.Concat(invalidSequence).Concat(knownGoodBytes).ToArray();
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 0, 0, 0);
+
+            toTest = knownGoodBytes.Concat(invalidSequence).Concat(knownGoodBytes).ToArray();
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 4, 1, 1);
+        }
+
+        private static void GetIndexOfFirstInvalidUtf8Sequence_Test_Core(string inputHex, int expectedRetVal, int expectedRuneCount, int expectedSurrogatePairCount)
+        {
+            byte[] inputBytes = Utf8Tests.DecodeHex(inputHex);
+
+            // Run the test normally
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(inputBytes, expectedRetVal, expectedRuneCount, expectedSurrogatePairCount);
+
+            // Then run the test with a bunch of ASCII data at the beginning (to exercise the vectorized code paths)
+            inputBytes = Enumerable.Repeat((byte)'x', 128).Concat(inputBytes).ToArray();
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(inputBytes, (expectedRetVal < 0) ? expectedRetVal : (expectedRetVal + 128), expectedRuneCount + 128, expectedSurrogatePairCount);
+
+            // Then put a few more ASCII bytes at the beginning (to test that offsets are properly handled)
+            inputBytes = Enumerable.Repeat((byte)'x', 7).Concat(inputBytes).ToArray();
+            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(inputBytes, (expectedRetVal < 0) ? expectedRetVal : (expectedRetVal + 135), expectedRuneCount + 135, expectedSurrogatePairCount);
+        }
+
+        private static unsafe void GetIndexOfFirstInvalidUtf8Sequence_Test_Core(byte[] input, int expectedRetVal, int expectedRuneCount, int expectedSurrogatePairCount)
+        {
+            // Arrange
+
+            using BoundedMemory<byte> boundedMemory = BoundedMemory.AllocateFromExistingData(input);
+            boundedMemory.MakeReadonly();
+
+            // Act
+
+            int actualRetVal;
+            int actualSurrogatePairCount;
+            int actualRuneCount;
+
+            fixed (byte* pInputBuffer = &MemoryMarshal.GetReference(boundedMemory.Span))
+            {
+                byte* pFirstInvalidByte = _getPointerToFirstInvalidByteFn.Value(pInputBuffer, input.Length, out int utf16CodeUnitCountAdjustment, out int scalarCountAdjustment);
+
+                long ptrDiff = pFirstInvalidByte - pInputBuffer;
+                Assert.True((ulong)ptrDiff <= (uint)input.Length, "ptrDiff was outside expected range.");
+
+                Assert.True(utf16CodeUnitCountAdjustment <= 0, "UTF-16 code unit count adjustment must be 0 or negative.");
+                Assert.True(scalarCountAdjustment <= 0, "Scalar count adjustment must be 0 or negative.");
+
+                actualRetVal = (ptrDiff == input.Length) ? -1 : (int)ptrDiff;
+
+                // The last two 'out' parameters are:
+                // a) The number to be added to the "bytes processed" return value to come up with the total UTF-16 code unit count, and
+                // b) The number to be added to the "total UTF-16 code unit count" value to come up with the total scalar count.
+
+                int totalUtf16CodeUnitCount = (int)ptrDiff + utf16CodeUnitCountAdjustment;
+                actualRuneCount = totalUtf16CodeUnitCount + scalarCountAdjustment;
+
+                // Surrogate pair count is number of UTF-16 code units less the number of scalars.
+
+                actualSurrogatePairCount = totalUtf16CodeUnitCount - actualRuneCount;
+            }
+
+            // Assert
+
+            Assert.Equal(expectedRetVal, actualRetVal);
+            Assert.Equal(expectedRuneCount, actualRuneCount);
+            Assert.Equal(expectedSurrogatePairCount, actualSurrogatePairCount);
+        }
+
+        private static Lazy<GetPointerToFirstInvalidByteDel> CreateGetPointerToFirstInvalidByteFn()
+        {
+            return new Lazy<GetPointerToFirstInvalidByteDel>(() =>
+            {
+                Type utf8UtilityType = typeof(Utf8).Assembly.GetType("System.Text.Unicode.Utf8Utility");
+
+                if (utf8UtilityType is null)
+                {
+                    throw new Exception("Couldn't find Utf8Utility type in System.Private.CoreLib.");
+                }
+
+                MethodInfo methodInfo = utf8UtilityType.GetMethod("GetPointerToFirstInvalidByte", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+
+                if (methodInfo is null)
+                {
+                    throw new Exception("Couldn't find GetPointerToFirstInvalidByte method on Utf8Utility.");
+                }
+
+                return (GetPointerToFirstInvalidByteDel)methodInfo.CreateDelegate(typeof(GetPointerToFirstInvalidByteDel));
+            });
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8UtilityTests.ValidateBytes.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Text/Unicode/Utf8UtilityTests.ValidateBytes.netcoreapp.cs
deleted file mode 100644 (file)
index 3f1517f..0000000
+++ /dev/null
@@ -1,418 +0,0 @@
-// 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 System.Reflection;
-using System.Runtime.InteropServices;
-using Xunit;
-
-namespace System.Text.Unicode.Tests
-{
-    public partial class Utf8UtilityTests
-    {
-        private unsafe delegate byte* GetPointerToFirstInvalidByteDel(byte* pInputBuffer, int inputLength, out int utf16CodeUnitCountAdjustment, out int scalarCountAdjustment);
-        private static readonly Lazy<GetPointerToFirstInvalidByteDel> _getPointerToFirstInvalidByteFn = CreateGetPointerToFirstInvalidByteFn();
-
-        private const string X = "58"; // U+0058 LATIN CAPITAL LETTER X, 1 byte
-        private const string Y = "59"; // U+0058 LATIN CAPITAL LETTER Y, 1 byte
-        private const string Z = "5A"; // U+0058 LATIN CAPITAL LETTER Z, 1 byte
-        private const string E_ACUTE = "C3A9"; // U+00E9 LATIN SMALL LETTER E WITH ACUTE, 2 bytes
-        private const string EURO_SYMBOL = "E282AC"; // U+20AC EURO SIGN, 3 bytes
-        private const string GRINNING_FACE = "F09F9880"; // U+1F600 GRINNING FACE, 4 bytes
-
-        [Theory]
-        [InlineData("", 0, 0)] // empty string is OK
-        [InlineData(X, 1, 0)]
-        [InlineData(X + Y, 2, 0)]
-        [InlineData(X + Y + Z, 3, 0)]
-        [InlineData(E_ACUTE, 1, 0)]
-        [InlineData(X + E_ACUTE, 2, 0)]
-        [InlineData(E_ACUTE + X, 2, 0)]
-        [InlineData(EURO_SYMBOL, 1, 0)]
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithSmallValidBuffers(string input, int expectedRuneCount, int expectedSurrogatePairCount)
-        {
-            // These test cases are for the "slow processing" code path at the end of GetIndexOfFirstInvalidUtf8Sequence,
-            // so inputs should be less than 4 bytes.
-
-            Assert.InRange(input.Length, 0, 6);
-
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(input, -1 /* expectedRetVal */, expectedRuneCount, expectedSurrogatePairCount);
-        }
-
-        [Theory]
-        [InlineData("80", 0, 0, 0)] // sequence cannot begin with continuation character
-        [InlineData("8182", 0, 0, 0)] // sequence cannot begin with continuation character
-        [InlineData("838485", 0, 0, 0)] // sequence cannot begin with continuation character
-        [InlineData(X + "80", 1, 1, 0)] // sequence cannot begin with continuation character
-        [InlineData(X + "8182", 1, 1, 0)] // sequence cannot begin with continuation character
-        [InlineData("C0", 0, 0, 0)] // [ C0 ] is always invalid
-        [InlineData("C080", 0, 0, 0)] // [ C0 ] is always invalid
-        [InlineData("C08081", 0, 0, 0)] // [ C0 ] is always invalid
-        [InlineData(X + "C1", 1, 1, 0)] // [ C1 ] is always invalid
-        [InlineData(X + "C180", 1, 1, 0)] // [ C1 ] is always invalid
-        [InlineData("C2", 0, 0, 0)] // [ C2 ] is improperly terminated
-        [InlineData(X + "C27F", 1, 1, 0)] // [ C2 ] is improperly terminated
-        [InlineData(X + "E282", 1, 1, 0)] // [ E2 82 ] is improperly terminated
-        [InlineData("E2827F", 0, 0, 0)] // [ E2 82 ] is improperly terminated
-        [InlineData("E09F80", 0, 0, 0)] // [ E0 9F ... ] is overlong
-        [InlineData("E0C080", 0, 0, 0)] // [ E0 ] is improperly terminated
-        [InlineData("ED7F80", 0, 0, 0)] // [ ED ] is improperly terminated
-        [InlineData("EDA080", 0, 0, 0)] // [ ED A0 ... ] is surrogate
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithSmallInvalidBuffers(string input, int expectedRetVal, int expectedRuneCount, int expectedSurrogatePairCount)
-        {
-            // These test cases are for the "slow processing" code path at the end of GetIndexOfFirstInvalidUtf8Sequence,
-            // so inputs should be less than 4 bytes.
-
-            Assert.InRange(input.Length, 0, 6);
-
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(input, expectedRetVal, expectedRuneCount, expectedSurrogatePairCount);
-        }
-
-        [Theory]
-        [InlineData(E_ACUTE + "21222324" + "303132333435363738393A3B3C3D3E3F", 21, 0)] // Loop unrolling at end of buffer
-        [InlineData(E_ACUTE + "21222324" + "303132333435363738393A3B3C3D3E3F" + "3031323334353637" + E_ACUTE + "38393A3B3C3D3E3F", 38, 0)] // Loop unrolling interrupted by non-ASCII
-        [InlineData("212223" + E_ACUTE + "30313233", 8, 0)] // 3 ASCII bytes followed by non-ASCII
-        [InlineData("2122" + E_ACUTE + "30313233", 7, 0)] // 2 ASCII bytes followed by non-ASCII
-        [InlineData("21" + E_ACUTE + "30313233", 6, 0)] // 1 ASCII byte followed by non-ASCII
-        [InlineData(E_ACUTE + E_ACUTE + E_ACUTE + E_ACUTE, 4, 0)] // 4x 2-byte sequences, exercises optimization code path in 2-byte sequence processing
-        [InlineData(E_ACUTE + E_ACUTE + E_ACUTE + "5051", 5, 0)] // 3x 2-byte sequences + 2 ASCII bytes, exercises optimization code path in 2-byte sequence processing
-        [InlineData(E_ACUTE + "5051", 3, 0)] // single 2-byte sequence + 2 trailing ASCII bytes, exercises draining logic in 2-byte sequence processing
-        [InlineData(E_ACUTE + "50" + E_ACUTE + "304050", 6, 0)] // single 2-byte sequences + 1 trailing ASCII byte + 2-byte sequence, exercises draining logic in 2-byte sequence processing
-        [InlineData(EURO_SYMBOL + "20", 2, 0)] // single 3-byte sequence + 1 trailing ASCII byte, exercises draining logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL + "203040", 4, 0)] // single 3-byte sequence + 3 trailing ASCII byte, exercises draining logic and "running out of data" logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL + EURO_SYMBOL + EURO_SYMBOL, 3, 0)] // 3x 3-byte sequences, exercises "stay within 3-byte loop" logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL + EURO_SYMBOL + EURO_SYMBOL + EURO_SYMBOL, 4, 0)] // 4x 3-byte sequences, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL + EURO_SYMBOL + EURO_SYMBOL + E_ACUTE, 4, 0)] // 3x 3-byte sequences + single 2-byte sequence, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
-        [InlineData(EURO_SYMBOL + EURO_SYMBOL + E_ACUTE + E_ACUTE + E_ACUTE + E_ACUTE, 6, 0)] // 2x 3-byte sequences + 4x 2-byte sequences, exercises "consume multiple bytes at a time" logic in 3-byte sequence processing
-        [InlineData(GRINNING_FACE + GRINNING_FACE, 2, 2)] // 2x 4-byte sequences, exercises 4-byte sequence processing
-        [InlineData(GRINNING_FACE + "303132", 4, 1)] // single 4-byte sequence + 3 ASCII bytes, exercises 4-byte sequence processing and draining logic
-        [InlineData("F09FA4B8" + "F09F8FBD" + "E2808D" + "E29980" + "EFB88F", 5, 2)] // U+1F938 U+1F3FD U+200D U+2640 U+FE0F WOMAN CARTWHEELING: MEDIUM SKIN TONE, exercising switching between multiple sequence lengths
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithLargeValidBuffers(string input, int expectedRuneCount, int expectedSurrogatePairCount)
-        {
-            // These test cases are for the "fast processing" code which is the main loop of GetIndexOfFirstInvalidUtf8Sequence,
-            // so inputs should be less >= 4 bytes.
-
-            Assert.True(input.Length >= 8);
-
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(input, -1 /* expectedRetVal */, expectedRuneCount, expectedSurrogatePairCount);
-        }
-
-        [Theory]
-        [InlineData("3031" + "80" + "202122232425", 2, 2, 0)] // Continuation character at start of sequence should match no bitmask
-        [InlineData("3031" + "C080" + "2021222324", 2, 2, 0)] // Overlong 2-byte sequence at start of DWORD
-        [InlineData("3031" + "C180" + "2021222324", 2, 2, 0)] // Overlong 2-byte sequence at start of DWORD
-        [InlineData("C280" + "C180", 2, 1, 0)] // Overlong 2-byte sequence at end of DWORD
-        [InlineData("C27F" + "C280", 0, 0, 0)] // Improperly terminated 2-byte sequence at start of DWORD
-        [InlineData("C2C0" + "C280", 0, 0, 0)] // Improperly terminated 2-byte sequence at start of DWORD
-        [InlineData("C280" + "C27F", 2, 1, 0)] // Improperly terminated 2-byte sequence at end of DWORD
-        [InlineData("C280" + "C2C0", 2, 1, 0)] // Improperly terminated 2-byte sequence at end of DWORD
-        [InlineData("C280" + "C280" + "80203040", 4, 2, 0)] // Continuation character at start of sequence, within "stay in 2-byte processing" optimization
-        [InlineData("C280" + "C280" + "C180" + "C280", 4, 2, 0)] // Overlong 2-byte sequence at start of DWORD, within "stay in 2-byte processing" optimization
-        [InlineData("C280" + "C280" + "C280" + "C180", 6, 3, 0)] // Overlong 2-byte sequence at end of DWORD, within "stay in 2-byte processing" optimization
-        [InlineData("3031" + "E09F80" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Overlong 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E07F80" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Improperly terminated 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E0C080" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Improperly terminated 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E17F80" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Improperly terminated 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E1C080" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Improperly terminated 3-byte sequence at start of DWORD
-        [InlineData("3031" + "EDA080" + EURO_SYMBOL + EURO_SYMBOL, 2, 2, 0)] // Surrogate 3-byte sequence at start of DWORD
-        [InlineData("3031" + "E69C88" + "E59B" + "E69C88", 5, 3, 0)] // Incomplete 3-byte sequence surrounded by valid 3-byte sequences
-        [InlineData("E78B80" + "80", 3, 1, 0)] // Valid 3-byte sequence followed by standalone continuation byte
-        [InlineData("3031" + "F5808080", 2, 2, 0)] // [ F5 ] is always invalid
-        [InlineData("3031" + "F6808080", 2, 2, 0)] // [ F6 ] is always invalid
-        [InlineData("3031" + "F7808080", 2, 2, 0)] // [ F7 ] is always invalid
-        [InlineData("3031" + "F8808080", 2, 2, 0)] // [ F8 ] is always invalid
-        [InlineData("3031" + "F9808080", 2, 2, 0)] // [ F9 ] is always invalid
-        [InlineData("3031" + "FA808080", 2, 2, 0)] // [ FA ] is always invalid
-        [InlineData("3031" + "FB808080", 2, 2, 0)] // [ FB ] is always invalid
-        [InlineData("3031" + "FC808080", 2, 2, 0)] // [ FC ] is always invalid
-        [InlineData("3031" + "FD808080", 2, 2, 0)] // [ FD ] is always invalid
-        [InlineData("3031" + "FE808080", 2, 2, 0)] // [ FE ] is always invalid
-        [InlineData("3031" + "FF808080", 2, 2, 0)] // [ FF ] is always invalid
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithLargeInvalidBuffers(string input, int expectedRetVal, int expectedRuneCount, int expectedSurrogatePairCount)
-        {
-            // These test cases are for the "fast processing" code which is the main loop of GetIndexOfFirstInvalidUtf8Sequence,
-            // so inputs should be less >= 4 bytes.
-
-            Assert.True(input.Length >= 8);
-
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(input, expectedRetVal, expectedRuneCount, expectedSurrogatePairCount);
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithOverlongTwoByteSequences_ReturnsInvalid()
-        {
-            // [ C0 ] is never a valid byte, indicates overlong 2-byte sequence
-            // We'll test that [ C0 ] [ 00..FF ] is treated as invalid
-
-            for (int i = 0; i < 256; i++)
-            {
-                AssertIsInvalidTwoByteSequence(new byte[] { 0xC0, (byte)i });
-            }
-
-            // [ C1 ] is never a valid byte, indicates overlong 2-byte sequence
-            // We'll test that [ C1 ] [ 00..FF ] is treated as invalid
-
-            for (int i = 0; i < 256; i++)
-            {
-                AssertIsInvalidTwoByteSequence(new byte[] { 0xC1, (byte)i });
-            }
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithImproperlyTerminatedTwoByteSequences_ReturnsInvalid()
-        {
-            // Test [ C2..DF ] [ 00..7F ] and [ C2..DF ] [ C0..FF ]
-
-            for (int i = 0xC2; i < 0xDF; i++)
-            {
-                for (int j = 0; j < 0x80; j++)
-                {
-                    AssertIsInvalidTwoByteSequence(new byte[] { (byte)i, (byte)j });
-                }
-                for (int j = 0xC0; j < 0x100; j++)
-                {
-                    AssertIsInvalidTwoByteSequence(new byte[] { (byte)i, (byte)j });
-                }
-            }
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithOverlongThreeByteSequences_ReturnsInvalid()
-        {
-            // [ E0 ] [ 80..9F ] [ 80..BF ] is overlong 3-byte sequence
-
-            for (int i = 0x00; i < 0xA0; i++)
-            {
-                AssertIsInvalidThreeByteSequence(new byte[] { 0xE0, (byte)i, 0x80 });
-            }
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithSurrogateThreeByteSequences_ReturnsInvalid()
-        {
-            // [ ED ] [ A0..BF ] [ 80..BF ] is surrogate 3-byte sequence
-
-            for (int i = 0xA0; i < 0x100; i++)
-            {
-                AssertIsInvalidThreeByteSequence(new byte[] { 0xED, (byte)i, 0x80 });
-            }
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithImproperlyTerminatedThreeByteSequence_ReturnsInvalid()
-        {
-            // [ E0..EF ] [ 80..BF ] [ !(80..BF) ] is improperly terminated 3-byte sequence
-
-            for (int i = 0xE0; i < 0xF0; i++)
-            {
-                for (int j = 0x00; j < 0x80; j++)
-                {
-                    // Use both '9F' and 'A0' to make sure at least one isn't caught by overlong / surrogate checks
-                    AssertIsInvalidThreeByteSequence(new byte[] { (byte)i, 0x9F, (byte)j });
-                    AssertIsInvalidThreeByteSequence(new byte[] { (byte)i, 0xA0, (byte)j });
-                }
-                for (int j = 0xC0; j < 0x100; j++)
-                {
-                    // Use both '9F' and 'A0' to make sure at least one isn't caught by overlong / surrogate checks
-                    AssertIsInvalidThreeByteSequence(new byte[] { (byte)i, 0x9F, (byte)j });
-                    AssertIsInvalidThreeByteSequence(new byte[] { (byte)i, 0xA0, (byte)j });
-                }
-            }
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithOverlongFourByteSequences_ReturnsInvalid()
-        {
-            // [ F0 ] [ 80..8F ] [ 80..BF ] [ 80..BF ] is overlong 4-byte sequence
-
-            for (int i = 0x00; i < 0x90; i++)
-            {
-                AssertIsInvalidFourByteSequence(new byte[] { 0xF0, (byte)i, 0x80, 0x80 });
-            }
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithOutOfRangeFourByteSequences_ReturnsInvalid()
-        {
-            // [ F4 ] [ 90..BF ] [ 80..BF ] [ 80..BF ] is out-of-range 4-byte sequence
-
-            for (int i = 0x90; i < 0x100; i++)
-            {
-                AssertIsInvalidFourByteSequence(new byte[] { 0xF4, (byte)i, 0x80, 0x80 });
-            }
-        }
-
-        [Fact]
-        public void GetIndexOfFirstInvalidUtf8Sequence_WithInvalidFourByteSequence_ReturnsInvalid()
-        {
-            // [ F0..F4 ] [ !(80..BF) ] [ !(80..BF) ] [ !(80..BF) ] is improperly terminated 4-byte sequence
-
-            for (int i = 0xF0; i < 0xF5; i++)
-            {
-                for (int j = 0x00; j < 0x80; j++)
-                {
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, (byte)j, 0x80, 0x80 });
-
-                    // Use both '8F' and '90' to make sure at least one isn't caught by overlong / out-of-range checks
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0x9F, (byte)j, 0x80 });
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0xA0, (byte)j, 0x80 });
-
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0x9F, 0x80, (byte)j });
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0xA0, 0x80, (byte)j });
-                }
-                for (int j = 0xC0; j < 0x100; j++)
-                {
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, (byte)j, 0x80, 0x80 });
-
-                    // Use both '8F' and '90' to make sure at least one isn't caught by overlong / out-of-range checks
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0x9F, (byte)j, 0x80 });
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0xA0, (byte)j, 0x80 });
-
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0x9F, 0x80, (byte)j });
-                    AssertIsInvalidFourByteSequence(new byte[] { (byte)i, 0xA0, 0x80, (byte)j });
-                }
-            }
-        }
-
-        private static void AssertIsInvalidTwoByteSequence(byte[] invalidSequence)
-        {
-            Assert.Equal(2, invalidSequence.Length);
-
-            byte[] knownGoodBytes = Utf8Tests.DecodeHex(E_ACUTE);
-
-            byte[] toTest = invalidSequence.Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at start of first DWORD
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 0, 0, 0);
-
-            toTest = knownGoodBytes.Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at end of first DWORD
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 2, 1, 0);
-
-            // Run the same tests but with extra data at the beginning so that we're inside one of
-            // the 2-byte processing "hot loop" code paths.
-
-            toTest = knownGoodBytes.Concat(knownGoodBytes).Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at start of next DWORD
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 4, 2, 0);
-
-            toTest = knownGoodBytes.Concat(knownGoodBytes).Concat(knownGoodBytes).Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at end of next DWORD
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 6, 3, 0);
-        }
-
-        private static void AssertIsInvalidThreeByteSequence(byte[] invalidSequence)
-        {
-            Assert.Equal(3, invalidSequence.Length);
-
-            byte[] knownGoodBytes = Utf8Tests.DecodeHex(EURO_SYMBOL);
-
-            byte[] toTest = invalidSequence.Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at start of first DWORD
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 0, 0, 0);
-
-            // Run the same tests but with extra data at the beginning so that we're inside one of
-            // the 3-byte processing "hot loop" code paths.
-
-            toTest = knownGoodBytes.Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // straddling first and second DWORDs
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 3, 1, 0);
-
-            toTest = knownGoodBytes.Concat(knownGoodBytes).Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // straddling second and third DWORDs
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 6, 2, 0);
-
-            toTest = knownGoodBytes.Concat(knownGoodBytes).Concat(knownGoodBytes).Concat(invalidSequence).Concat(knownGoodBytes).ToArray(); // at end of third DWORD
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 9, 3, 0);
-        }
-
-        private static void AssertIsInvalidFourByteSequence(byte[] invalidSequence)
-        {
-            Assert.Equal(4, invalidSequence.Length);
-
-            byte[] knownGoodBytes = Utf8Tests.DecodeHex(GRINNING_FACE);
-
-            byte[] toTest = invalidSequence.Concat(invalidSequence).Concat(knownGoodBytes).ToArray();
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 0, 0, 0);
-
-            toTest = knownGoodBytes.Concat(invalidSequence).Concat(knownGoodBytes).ToArray();
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(toTest, 4, 1, 1);
-        }
-
-        private static void GetIndexOfFirstInvalidUtf8Sequence_Test_Core(string inputHex, int expectedRetVal, int expectedRuneCount, int expectedSurrogatePairCount)
-        {
-            byte[] inputBytes = Utf8Tests.DecodeHex(inputHex);
-
-            // Run the test normally
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(inputBytes, expectedRetVal, expectedRuneCount, expectedSurrogatePairCount);
-
-            // Then run the test with a bunch of ASCII data at the beginning (to exercise the vectorized code paths)
-            inputBytes = Enumerable.Repeat((byte)'x', 128).Concat(inputBytes).ToArray();
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(inputBytes, (expectedRetVal < 0) ? expectedRetVal : (expectedRetVal + 128), expectedRuneCount + 128, expectedSurrogatePairCount);
-
-            // Then put a few more ASCII bytes at the beginning (to test that offsets are properly handled)
-            inputBytes = Enumerable.Repeat((byte)'x', 7).Concat(inputBytes).ToArray();
-            GetIndexOfFirstInvalidUtf8Sequence_Test_Core(inputBytes, (expectedRetVal < 0) ? expectedRetVal : (expectedRetVal + 135), expectedRuneCount + 135, expectedSurrogatePairCount);
-        }
-
-        private static unsafe void GetIndexOfFirstInvalidUtf8Sequence_Test_Core(byte[] input, int expectedRetVal, int expectedRuneCount, int expectedSurrogatePairCount)
-        {
-            // Arrange
-
-            using BoundedMemory<byte> boundedMemory = BoundedMemory.AllocateFromExistingData(input);
-            boundedMemory.MakeReadonly();
-
-            // Act
-
-            int actualRetVal;
-            int actualSurrogatePairCount;
-            int actualRuneCount;
-
-            fixed (byte* pInputBuffer = &MemoryMarshal.GetReference(boundedMemory.Span))
-            {
-                byte* pFirstInvalidByte = _getPointerToFirstInvalidByteFn.Value(pInputBuffer, input.Length, out int utf16CodeUnitCountAdjustment, out int scalarCountAdjustment);
-
-                long ptrDiff = pFirstInvalidByte - pInputBuffer;
-                Assert.True((ulong)ptrDiff <= (uint)input.Length, "ptrDiff was outside expected range.");
-
-                Assert.True(utf16CodeUnitCountAdjustment <= 0, "UTF-16 code unit count adjustment must be 0 or negative.");
-                Assert.True(scalarCountAdjustment <= 0, "Scalar count adjustment must be 0 or negative.");
-
-                actualRetVal = (ptrDiff == input.Length) ? -1 : (int)ptrDiff;
-
-                // The last two 'out' parameters are:
-                // a) The number to be added to the "bytes processed" return value to come up with the total UTF-16 code unit count, and
-                // b) The number to be added to the "total UTF-16 code unit count" value to come up with the total scalar count.
-
-                int totalUtf16CodeUnitCount = (int)ptrDiff + utf16CodeUnitCountAdjustment;
-                actualRuneCount = totalUtf16CodeUnitCount + scalarCountAdjustment;
-
-                // Surrogate pair count is number of UTF-16 code units less the number of scalars.
-
-                actualSurrogatePairCount = totalUtf16CodeUnitCount - actualRuneCount;
-            }
-
-            // Assert
-
-            Assert.Equal(expectedRetVal, actualRetVal);
-            Assert.Equal(expectedRuneCount, actualRuneCount);
-            Assert.Equal(expectedSurrogatePairCount, actualSurrogatePairCount);
-        }
-
-        private static Lazy<GetPointerToFirstInvalidByteDel> CreateGetPointerToFirstInvalidByteFn()
-        {
-            return new Lazy<GetPointerToFirstInvalidByteDel>(() =>
-            {
-                Type utf8UtilityType = typeof(Utf8).Assembly.GetType("System.Text.Unicode.Utf8Utility");
-
-                if (utf8UtilityType is null)
-                {
-                    throw new Exception("Couldn't find Utf8Utility type in System.Private.CoreLib.");
-                }
-
-                MethodInfo methodInfo = utf8UtilityType.GetMethod("GetPointerToFirstInvalidByte", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
-
-                if (methodInfo is null)
-                {
-                    throw new Exception("Couldn't find GetPointerToFirstInvalidByte method on Utf8Utility.");
-                }
-
-                return (GetPointerToFirstInvalidByteDel)methodInfo.CreateDelegate(typeof(GetPointerToFirstInvalidByteDel));
-            });
-        }
-    }
-}
index b5596675fca52c5ed320bd9fa90a033afba67990..965e5ae8e622b7912fbe036c7772ef2b7cf18585 100644 (file)
@@ -9,7 +9,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class TimeSpanTests
+    public class TimeSpanTests
     {
         [Fact]
         public static void MaxValue()
@@ -1070,5 +1070,320 @@ namespace System.Tests
         {
             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);
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/TimeSpanTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/TimeSpanTests.netcoreapp.cs
deleted file mode 100644 (file)
index 13b7969..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-// 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);
-        }
-    }
-}
index 01fb958fabf6801dcc651b04e957138f29a03359..480ebb11b6fd2e06566c027c4b49f78693d461b5 100644 (file)
@@ -7,7 +7,7 @@ using Xunit;
 
 namespace System.Tests.Types
 {
-    public abstract partial class TypePropertyTestBase
+    public abstract class TypePropertyTestBase
     {
         public abstract Type CreateType();
 
@@ -311,6 +311,42 @@ namespace System.Tests.Types
         {
             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
diff --git a/src/libraries/System.Runtime/tests/System/Type/TypePropertyTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Type/TypePropertyTests.netcoreapp.cs
deleted file mode 100644 (file)
index 169b2ad..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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);
-        }
-    }
-}
index f14da219a2e8385ad87289578531288cd1b58c80..d95c9b9a72d0af07857211f38f926d4a49f0a708 100644 (file)
@@ -5,7 +5,9 @@
 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;
 
@@ -37,6 +39,27 @@ namespace System.Tests
 {
     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()
         {
@@ -285,6 +308,262 @@ namespace System.Tests
             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    {
@@ -478,3 +757,5 @@ namespace System.Tests
     public interface GenericInterface<T> { }
     public interface GenericInterface<T, U> { }
 }
+
+internal class DummyGenericClassForTypeTests<T> { }
diff --git a/src/libraries/System.Runtime/tests/System/Type/TypeTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/Type/TypeTests.netcoreapp.cs
deleted file mode 100644 (file)
index 85d0943..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-// 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> { }
index ef837a570d3f029fbe0681dd87b9dad292b45655..ccc9f478093308cf45cc42a381087e0c7556eb85 100644 (file)
@@ -8,7 +8,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class UInt16Tests
+    public class UInt16Tests
     {
         [Fact]
         public static void Ctor_Empty()
@@ -290,5 +290,105 @@ namespace System.Tests
             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));
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/UInt16Tests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/UInt16Tests.netcoreapp.cs
deleted file mode 100644 (file)
index a6e8301..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-// 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));
-            }
-        }
-    }
-}
index 9265c137bcb68d5daf8046c01155ee61cb13ec72..a31df0e22f42b70ce6696b0f0e64379732861435 100644 (file)
@@ -9,7 +9,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class UInt32Tests
+    public class UInt32Tests
     {
         [Fact]
         public static void Ctor_Empty()
@@ -308,5 +308,105 @@ namespace System.Tests
             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));
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/UInt32Tests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/UInt32Tests.netcoreapp.cs
deleted file mode 100644 (file)
index 1225062..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-// 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));
-            }
-        }
-    }
-}
index 5976972e8f6caef3971d9f8ebf87f0efb5682ac8..3c8b0c5d050aa63549c959540603f36a0fdb428a 100644 (file)
@@ -9,7 +9,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class UInt64Tests
+    public class UInt64Tests
     {
         [Fact]
         public static void Ctor_Empty()
@@ -319,5 +319,104 @@ namespace System.Tests
             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));
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/UInt64Tests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/UInt64Tests.netcoreapp.cs
deleted file mode 100644 (file)
index d10e757..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// 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));
-            }
-        }
-    }
-}
index f4c922e09f624364dd4f3196d4b72f45e3725f4f..53cd55b979d45778c50226b2c92a6b8b41c3f598 100644 (file)
@@ -8,7 +8,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public static partial class UIntPtrTests
+    public static class UIntPtrTests
     {
         private static unsafe bool Is64Bit => sizeof(void*) == 8;
 
@@ -113,6 +113,9 @@ namespace System.Tests
                 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());
diff --git a/src/libraries/System.Runtime/tests/System/UIntPtrTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/UIntPtrTests.netcoreapp.cs
deleted file mode 100644 (file)
index d55a968..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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));
-        }
-    }
-}
index 423652fb11100b9f675a36ada957d80555f18f74..b9f3a4a694196c527444b357553d6975081dfbe7 100644 (file)
@@ -7,7 +7,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public partial class VersionTests
+    public class VersionTests
     {
         [Fact]
         public void Ctor_Default()
@@ -322,5 +322,89 @@ namespace System.Tests
             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
+        }
     }
 }
diff --git a/src/libraries/System.Runtime/tests/System/VersionTests.netcoreapp.cs b/src/libraries/System.Runtime/tests/System/VersionTests.netcoreapp.cs
deleted file mode 100644 (file)
index f33a046..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// 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
-        }
-    }
-}