Consolidate .netcoreapp.cs test files in System.Runtime.Extensions (dotnet/corefx...
authorRoman Marusyk <Marusyk@users.noreply.github.com>
Tue, 29 Oct 2019 00:58:42 +0000 (01:58 +0100)
committerJan Kotas <jkotas@microsoft.com>
Tue, 29 Oct 2019 00:58:42 +0000 (17:58 -0700)
* Consolidate .netcoreapp.cs files because System.Runtime.Extensions project is no longer cross-compiled

* Fix AppDomainTests

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

25 files changed:
src/libraries/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj
src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs
src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/BitConverter.cs
src/libraries/System.Runtime.Extensions/tests/System/BitConverter.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/Convert.cs
src/libraries/System.Runtime.Extensions/tests/System/Convert.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/IO/Path.IsPathFullyQualified.cs
src/libraries/System.Runtime.Extensions/tests/System/IO/Path.IsPathFullyQualified.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.cs
src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/IO/PathTestsBase.cs
src/libraries/System.Runtime.Extensions/tests/System/IO/PathTestsBase.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Join.cs [moved from src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Join.netcoreapp.cs with 100% similarity]
src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Windows.cs
src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Windows.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/Math.cs
src/libraries/System.Runtime.Extensions/tests/System/MathF.cs [moved from src/libraries/System.Runtime.Extensions/tests/System/MathF.netcoreapp.cs with 99% similarity]
src/libraries/System.Runtime.Extensions/tests/System/MathTests.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/Random.cs
src/libraries/System.Runtime.Extensions/tests/System/Random.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/Runtime/ProfileOptimization.cs [moved from src/libraries/System.Runtime.Extensions/tests/System/Runtime/ProfileOptimization.netcoreapp.cs with 97% similarity]
src/libraries/System.Runtime.Extensions/tests/System/StringComparer.cs
src/libraries/System.Runtime.Extensions/tests/System/StringComparer.netcoreapp.cs [deleted file]
src/libraries/System.Runtime.Extensions/tests/System/UnloadingAndProcessExitTests.cs [moved from src/libraries/System.Runtime.Extensions/tests/System/UnloadingAndProcessExitTests.netcoreapp.cs with 100% similarity]

index 0f1eee0..88ef8bd 100644 (file)
@@ -6,24 +6,14 @@
     <IncludeRemoteExecutor>true</IncludeRemoteExecutor>
     <Configurations>netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release</Configurations>
   </PropertyGroup>
-  <ItemGroup Condition="'$(TargetsNetCoreApp)' == 'true'">
-    <Compile Include="System\AppDomainTests.netcoreapp.cs" />
-    <Compile Include="System\Random.netcoreapp.cs" />
-    <Compile Include="System\IO\Path.IsPathFullyQualified.netcoreapp.cs" />
-    <Compile Include="System\IO\PathTestsBase.netcoreapp.cs" />
-    <Compile Include="System\IO\PathTests_Windows.netcoreapp.cs" />
-    <Compile Include="System\IO\PathTests.netcoreapp.cs" />
-    <Compile Include="System\IO\PathTests_Unix.cs" />
-    <Compile Include="System\IO\PathTests_Join.netcoreapp.cs" />
-    <Compile Include="System\Runtime\ProfileOptimization.netcoreapp.cs" />
-    <Compile Include="System\Runtime\CompilerServices\SwitchExpressionExceptionTests.cs" />
-  </ItemGroup>
   <ItemGroup>
     <Compile Include="System\ApplicationIdTests.cs" />
     <Compile Include="System\Convert.cs" />
     <Compile Include="System\EnvironmentTests.cs" />
     <Compile Include="System\IO\PathTests.cs" />
     <Compile Include="System\IO\PathTests_Windows.cs" />
+    <Compile Include="System\IO\PathTests_Unix.cs" />
+    <Compile Include="System\IO\PathTests_Join.cs" />
     <Compile Include="System\OperatingSystemTests.cs" />
     <Compile Include="System\Runtime\Versioning\VersioningHelperTests.cs" />
     <Compile Include="System\AppDomainTests.cs" />
     <Compile Include="System\MarshalByRefObjectTest.cs" />
     <Compile Include="TestHelpers.cs" />
     <Compile Include="System\BitConverterSpan.cs" />
-    <Compile Include="System\BitConverter.netcoreapp.cs" />
-    <Compile Include="System\Convert.netcoreapp.cs" />
     <Compile Include="System\IO\Path.GetRelativePath.cs" />
-    <Compile Include="System\MathTests.netcoreapp.cs" />
-    <Compile Include="System\MathF.netcoreapp.cs" />
+    <Compile Include="System\MathF.cs" />
     <Compile Include="System\Numerics\BitOperationsTests.cs" />
-    <Compile Include="System\StringComparer.netcoreapp.cs" />
-    <Compile Include="System\UnloadingAndProcessExitTests.netcoreapp.cs" />
+    <Compile Include="System\UnloadingAndProcessExitTests.cs" />
     <Compile Include="System\IO\Path.IsPathFullyQualified.cs" />
     <Compile Include="System\BitConverterArray.cs" />
     <Compile Include="System\BitConverterBase.cs" />
@@ -84,6 +70,9 @@
     <Compile Include="System\Progress.cs" />
     <Compile Include="System\Random.cs" />
     <Compile Include="System\StringComparer.cs" />
+    <Compile Include="System\Runtime\ProfileOptimization.cs" />
+    <Compile Include="System\Runtime\CompilerServices\SwitchExpressionExceptionTests.cs" />
+
     <Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetNodeName.cs" Condition="'$(TargetsUnix)' == 'true'">
       <Link>Common\Interop\Unix\System.Native\Interop.GetNodeName.cs</Link>
     </Compile>
index 2ef0b23..a3eb1db 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 System.Diagnostics;
 using System.Globalization;
 using System.IO;
@@ -9,12 +10,15 @@ using System.Net.Http;
 using System.Reflection;
 using System.Resources;
 using System.Runtime.ExceptionServices;
+using System.Runtime.Remoting;
+using System.Security;
+using System.Security.Permissions;
 using Microsoft.DotNet.RemoteExecutor;
 using Xunit;
 
 namespace System.Tests
 {
-    public partial class AppDomainTests : FileCleanupTestBase
+    public class AppDomainTests : FileCleanupTestBase
     {
         [Fact]
         public void CurrentDomain_Not_Null()
@@ -722,6 +726,230 @@ namespace System.Tests
                 File.Copy("TestAppOutsideOfTPA.exe", destTestAssemblyPath, false);
             }
         }
+
+        [Fact]
+        public void GetSetupInformation()
+        {
+            RemoteExecutor.Invoke(() => {
+                Assert.Equal(AppContext.BaseDirectory, AppDomain.CurrentDomain.SetupInformation.ApplicationBase);
+                Assert.Equal(AppContext.TargetFrameworkName, AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName);
+            }).Dispose();
+        }
+
+        [Fact]
+        public static void GetPermissionSet()
+        {
+            RemoteExecutor.Invoke(() => {
+                Assert.Equal(new PermissionSet(PermissionState.Unrestricted), AppDomain.CurrentDomain.PermissionSet);
+            }).Dispose();
+        }
+
+        [Theory]
+        [MemberData(nameof(TestingCreateInstanceFromObjectHandleData))]
+        public static void TestingCreateInstanceFromObjectHandle(string physicalFileName, string assemblyFile, string type, string returnedFullNameType, Type exceptionType)
+        {
+            ObjectHandle oh = null;
+            object obj = null;
+
+            if (exceptionType != null)
+            {
+                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type));
+                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type));
+            }
+            else
+            {
+                oh = AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type);
+                CheckValidity(oh, returnedFullNameType);
+
+                obj = AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type);
+                CheckValidity(obj, returnedFullNameType);
+            }
+
+            if (exceptionType != null)
+            {
+                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, null));
+                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type, null));
+            }
+            else
+            {
+                oh = AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, null);
+                CheckValidity(oh, returnedFullNameType);
+
+                obj = AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type, null);
+                CheckValidity(obj, 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
+            { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", "AssemblyResolveTestApp.PublicClassSample", null },
+            { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", "AssemblyResolveTestApp.PublicClassSample", typeof(TypeLoadException) },
+
+            { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", "AssemblyResolveTestApp.PrivateClassSample", null },
+            { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", "AssemblyResolveTestApp.PrivateClassSample", typeof(TypeLoadException) },
+
+            { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) },
+            { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclassnodefaultconstructorsample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(TypeLoadException) }
+        };
+
+        [Theory]
+        [MemberData(nameof(TestingCreateInstanceObjectHandleData))]
+        public static void TestingCreateInstanceObjectHandle(string assemblyName, string type, string returnedFullNameType, Type exceptionType)
+        {
+            ObjectHandle oh = null;
+            object obj = null;
+
+            if (exceptionType != null)
+            {
+                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type));
+                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type));
+            }
+            else
+            {
+                oh = AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type);
+                CheckValidity(oh, returnedFullNameType);
+
+                obj = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type);
+                CheckValidity(obj, returnedFullNameType);
+            }
+
+            if (exceptionType != null)
+            {
+                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type, null));
+                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type, null));
+            }
+            else
+            {
+                oh = AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type, null);
+                CheckValidity(oh, returnedFullNameType);
+
+                obj = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type, null);
+                CheckValidity(obj, returnedFullNameType);
+            }
+        }
+
+        public static TheoryData<string, string, string, Type> TestingCreateInstanceObjectHandleData => new TheoryData<string, string, string, Type>()
+        {
+            // string assemblyName, string typeName, returnedFullNameType, expectedException
+            { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PublicClassSample", "AssemblyResolveTestApp.PublicClassSample", null },
+            { "assemblyresolvetestapp", "assemblyresolvetestapp.publicclasssample", "AssemblyResolveTestApp.PublicClassSample", typeof(TypeLoadException) },
+
+            { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PrivateClassSample", "AssemblyResolveTestApp.PrivateClassSample", null },
+            { "assemblyresolvetestapp", "assemblyresolvetestapp.privateclasssample", "AssemblyResolveTestApp.PrivateClassSample", typeof(TypeLoadException) },
+
+            { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) },
+            { "assemblyresolvetestapp", "assemblyresolvetestapp.publicclassnodefaultconstructorsample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(TypeLoadException) }
+        };
+
+        [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 = AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
+            CheckValidity(oh, returnedFullNameType);
+
+            object obj = AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
+            CheckValidity(obj, 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[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
+            yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
+            yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
+            yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
+
+            yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
+            yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
+            yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
+            yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.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)
+        {
+            ObjectHandle oh = AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
+            CheckValidity(oh, returnedFullNameType);
+
+            object obj = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
+            CheckValidity(obj, returnedFullNameType);
+        }
+
+        private static void CheckValidity(object instance, string expected)
+        {
+            Assert.NotNull(instance);
+            Assert.Equal(expected, instance.GetType().FullName);
+        }
+
+        private static void CheckValidity(ObjectHandle instance, string expected)
+        {
+            Assert.NotNull(instance);
+            Assert.Equal(expected, instance.Unwrap().GetType().FullName);
+        }
+
+        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[] { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
+            yield return new object[] { "assemblyresolvetestapp", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
+            yield return new object[] { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
+            yield return new object[] { "assemblyresolvetestapp", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
+
+            yield return new object[] { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
+            yield return new object[] { "assemblyresolvetestapp", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
+            yield return new object[] { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
+            yield return new object[] { "assemblyresolvetestapp", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
+        }
+
+        [Fact]
+        public void AssemblyResolve_FirstChanceException()
+        {
+            RemoteExecutor.Invoke(() => {
+                Assembly assembly = typeof(AppDomainTests).Assembly;
+
+                Exception firstChanceExceptionThrown = null;
+
+                EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> firstChanceHandler = (source, args) =>
+                {
+                    firstChanceExceptionThrown = args.Exception;
+                };
+
+                AppDomain.CurrentDomain.FirstChanceException += firstChanceHandler;
+
+                ResolveEventHandler assemblyResolveHandler = (sender, e) =>
+                {
+                    Assert.Equal(assembly, e.RequestingAssembly);
+                    Assert.Null(firstChanceExceptionThrown);
+                    return null;
+                };
+
+                AppDomain.CurrentDomain.AssemblyResolve += assemblyResolveHandler;
+
+                Func<System.Runtime.Loader.AssemblyLoadContext, AssemblyName, Assembly> resolvingHandler = (context, name) =>
+                {
+                    return null;
+                };
+
+                // The issue resolved by coreclr#24450, was only reproduced when there was a Resolving handler present
+                System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += resolvingHandler;
+
+                assembly.GetType("System.Tests.AGenericClass`1[[Bogus, BogusAssembly]]", false);
+                Assert.Null(firstChanceExceptionThrown);
+
+                Exception thrown = Assert.Throws<FileNotFoundException>(() => assembly.GetType("System.Tests.AGenericClass`1[[Bogus, AnotherBogusAssembly]]", true));
+                Assert.Same(firstChanceExceptionThrown, thrown);
+            }).Dispose();
+        }
+    }
+
+    class AGenericClass<T>
+    {
     }
 }
 
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.netcoreapp.cs
deleted file mode 100644 (file)
index 5c4b939..0000000
+++ /dev/null
@@ -1,243 +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.Reflection;
-using System.Runtime.Remoting;
-using System.Security;
-using System.Security.Permissions;
-using Microsoft.DotNet.RemoteExecutor;
-using Xunit;
-
-namespace System.Tests
-{
-    class AGenericClass<T>
-    {
-    }
-
-    public partial class AppDomainTests
-    {
-        [Fact]
-        public void GetSetupInformation()
-        {
-            RemoteExecutor.Invoke(() => {
-                Assert.Equal(AppContext.BaseDirectory, AppDomain.CurrentDomain.SetupInformation.ApplicationBase);
-                Assert.Equal(AppContext.TargetFrameworkName, AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName);
-            }).Dispose();
-        }
-
-        [Fact]
-        public static void GetPermissionSet()
-        {
-            RemoteExecutor.Invoke(() => {
-                Assert.Equal(new PermissionSet(PermissionState.Unrestricted), AppDomain.CurrentDomain.PermissionSet);
-            }).Dispose();
-        }
-
-        [Theory]
-        [MemberData(nameof(TestingCreateInstanceFromObjectHandleData))]
-        public static void TestingCreateInstanceFromObjectHandle(string physicalFileName, string assemblyFile, string type, string returnedFullNameType, Type exceptionType)
-        {
-            ObjectHandle oh = null;
-            object obj = null;
-
-            if (exceptionType != null)
-            {
-                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type));
-                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type));
-            }
-            else
-            {
-                oh = AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type);
-                CheckValidity(oh, returnedFullNameType);
-
-                obj = AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type);
-                CheckValidity(obj, returnedFullNameType);
-            }
-
-            if (exceptionType != null)
-            {
-                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, null));
-                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type, null));
-            }
-            else
-            {
-                oh = AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, null);
-                CheckValidity(oh, returnedFullNameType);
-
-                obj = AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type, null);
-                CheckValidity(obj, 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
-            { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", "AssemblyResolveTestApp.PublicClassSample", null },
-            { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", "AssemblyResolveTestApp.PublicClassSample", typeof(TypeLoadException) },
-
-            { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", "AssemblyResolveTestApp.PrivateClassSample", null },
-            { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", "AssemblyResolveTestApp.PrivateClassSample", typeof(TypeLoadException) },
-
-            { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) },
-            { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclassnodefaultconstructorsample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(TypeLoadException) }
-        };
-
-        [Theory]
-        [MemberData(nameof(TestingCreateInstanceObjectHandleData))]
-        public static void TestingCreateInstanceObjectHandle(string assemblyName, string type, string returnedFullNameType, Type exceptionType)
-        {
-            ObjectHandle oh = null;
-            object obj = null;
-
-            if (exceptionType != null)
-            {
-                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type));
-                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type));
-            }
-            else
-            {
-                oh = AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type);
-                CheckValidity(oh, returnedFullNameType);
-
-                obj = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type);
-                CheckValidity(obj, returnedFullNameType);
-            }
-
-            if (exceptionType != null)
-            {
-                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type, null));
-                Assert.Throws(exceptionType, () => AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type, null));
-            }
-            else
-            {
-                oh = AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type, null);
-                CheckValidity(oh, returnedFullNameType);
-
-                obj = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type, null);
-                CheckValidity(obj, returnedFullNameType);
-            }
-        }
-
-        public static TheoryData<string, string, string, Type> TestingCreateInstanceObjectHandleData => new TheoryData<string, string, string, Type>()
-        {
-            // string assemblyName, string typeName, returnedFullNameType, expectedException
-            { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PublicClassSample", "AssemblyResolveTestApp.PublicClassSample", null },
-            { "assemblyresolvetestapp", "assemblyresolvetestapp.publicclasssample", "AssemblyResolveTestApp.PublicClassSample", typeof(TypeLoadException) },
-
-            { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PrivateClassSample", "AssemblyResolveTestApp.PrivateClassSample", null },
-            { "assemblyresolvetestapp", "assemblyresolvetestapp.privateclasssample", "AssemblyResolveTestApp.PrivateClassSample", typeof(TypeLoadException) },
-
-            { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) },
-            { "assemblyresolvetestapp", "assemblyresolvetestapp.publicclassnodefaultconstructorsample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(TypeLoadException) }
-        };
-
-        [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 = AppDomain.CurrentDomain.CreateInstanceFrom(assemblyFile: assemblyFile, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
-            CheckValidity(oh, returnedFullNameType);
-
-            object obj = AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyFile: assemblyFile, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
-            CheckValidity(obj, 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[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
-            yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
-            yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
-            yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
-
-            yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
-            yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
-            yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
-            yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.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)
-        {
-            ObjectHandle oh = AppDomain.CurrentDomain.CreateInstance(assemblyName: assemblyName, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
-            CheckValidity(oh, returnedFullNameType);
-
-            object obj = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName: assemblyName, typeName: type, ignoreCase: ignoreCase, bindingAttr: bindingAttr, binder: binder, args: args, culture: culture, activationAttributes: activationAttributes);
-            CheckValidity(obj, returnedFullNameType);
-        }
-
-        private static void CheckValidity(object instance, string expected)
-        {
-            Assert.NotNull(instance);
-            Assert.Equal(expected, instance.GetType().FullName);
-        }
-
-        private static void CheckValidity(ObjectHandle instance, string expected)
-        {
-            Assert.NotNull(instance);
-            Assert.Equal(expected, instance.Unwrap().GetType().FullName);
-        }
-
-        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[] { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
-            yield return new object[] { "assemblyresolvetestapp", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
-            yield return new object[] { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
-            yield return new object[] { "assemblyresolvetestapp", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" };
-
-            yield return new object[] { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
-            yield return new object[] { "assemblyresolvetestapp", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
-            yield return new object[] { "AssemblyResolveTestApp", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
-            yield return new object[] { "assemblyresolvetestapp", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" };
-        }
-
-        [Fact]
-        public void AssemblyResolve_FirstChanceException()
-        {
-            RemoteExecutor.Invoke(() => {
-                Assembly assembly = typeof(AppDomainTests).Assembly;
-
-                Exception firstChanceExceptionThrown = null;
-
-                EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> firstChanceHandler = (source, args) =>
-                {
-                    firstChanceExceptionThrown = args.Exception;
-                };
-
-                AppDomain.CurrentDomain.FirstChanceException += firstChanceHandler;
-
-                ResolveEventHandler assemblyResolveHandler = (sender, e) =>
-                {
-                    Assert.Equal(assembly, e.RequestingAssembly);
-                    Assert.Null(firstChanceExceptionThrown);
-                    return null;
-                };
-
-                AppDomain.CurrentDomain.AssemblyResolve += assemblyResolveHandler;
-
-                Func<System.Runtime.Loader.AssemblyLoadContext, AssemblyName, Assembly> resolvingHandler = (context, name) =>
-                {
-                    return null;
-                };
-
-                // The issue resolved by coreclr#24450, was only reproduced when there was a Resolving handler present
-                System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += resolvingHandler;
-
-                assembly.GetType("System.Tests.AGenericClass`1[[Bogus, BogusAssembly]]", false);
-                Assert.Null(firstChanceExceptionThrown);
-
-                Exception thrown = Assert.Throws<FileNotFoundException>(() => assembly.GetType("System.Tests.AGenericClass`1[[Bogus, AnotherBogusAssembly]]", true));
-                Assert.Same(firstChanceExceptionThrown, thrown);
-            }).Dispose();
-        }
-    }
-}
index 86261a2..31dc4af 100644 (file)
@@ -8,7 +8,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public static partial class BitConverterTests
+    public static class BitConverterTests
     {
         [Fact]
         public static unsafe void IsLittleEndian()
@@ -262,5 +262,15 @@ namespace System.Tests
             Array.Copy(bytes, 0, longerBytes, 1, bytes.Length);
             Assert.Equal(input, convertBack(longerBytes, 1));
         }
+
+        [Fact]
+        public static void SingleToInt32Bits()
+        {
+            float input = 12345.63f;
+            int result = BitConverter.SingleToInt32Bits(input);
+            Assert.Equal(1178658437, result);
+            float roundtripped = BitConverter.Int32BitsToSingle(result);
+            Assert.Equal(input, roundtripped);
+        }
     }
 }
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/BitConverter.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/BitConverter.netcoreapp.cs
deleted file mode 100644 (file)
index a903484..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 Xunit;
-
-namespace System.Tests
-{
-    public static partial class BitConverterTests
-    {
-        [Fact]
-        public static void SingleToInt32Bits()
-        {
-            float input = 12345.63f;
-            int result = BitConverter.SingleToInt32Bits(input);
-            Assert.Equal(1178658437, result);
-            float roundtripped = BitConverter.Int32BitsToSingle(result);
-            Assert.Equal(input, roundtripped);
-        }
-    }
-}
\ No newline at end of file
index 5ad4ab5..8f155a9 100644 (file)
@@ -2,13 +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;
 using System.Globalization;
 using Xunit;
+using System.Linq;
+using System.Text;
+using System.Collections.Generic;
+
+using Test.Cryptography;
 
 namespace System.Tests
 {
-    public partial class ConvertTests
+    public class ConvertTests
     {
         [Fact]
         public static void ChangeTypeTest()
@@ -160,5 +164,340 @@ namespace System.Tests
         {
             Assert.Throws<InvalidCastException>(() => Convert.ToUInt64(DateTime.MaxValue));
         }
+
+        [Theory]
+        [InlineData(new byte[0], "")]
+        [InlineData(new byte[] { 5, 6, 7, 8 }, "BQYHCA==")]
+        public void ToBase64String_Span_ProducesExpectedOutput(byte[] input, string expected)
+        {
+            Assert.Equal(expected, Convert.ToBase64String(input.AsSpan()));
+            Assert.Equal(expected, Convert.ToBase64String(input.AsSpan(), Base64FormattingOptions.None));
+            Assert.Equal(expected, Convert.ToBase64String(input.AsSpan(), Base64FormattingOptions.InsertLineBreaks));
+        }
+
+        [Fact]
+        public void ToBase64String_Span_LongWithOptions_ProducesExpectedOutput()
+        {
+            byte[] input = Enumerable.Range(0, 120).Select(i => (byte)i).ToArray();
+
+            Assert.Equal(
+                "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4" +
+                "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx" +
+                "cnN0dXZ3",
+                Convert.ToBase64String(input));
+
+            Assert.Equal(
+                "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4" +
+                "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx" +
+                "cnN0dXZ3",
+                Convert.ToBase64String(input, Base64FormattingOptions.None));
+
+            Assert.Equal(
+                "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4\r\n" +
+                "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx\r\n" +
+                "cnN0dXZ3",
+                Convert.ToBase64String(input, Base64FormattingOptions.InsertLineBreaks));
+        }
+
+        [Theory]
+        [InlineData((Base64FormattingOptions)(-1))]
+        [InlineData((Base64FormattingOptions)(2))]
+        public void ToBase64String_Span_InvalidOptions_Throws(Base64FormattingOptions invalidOption)
+        {
+            AssertExtensions.Throws<ArgumentException>("options", () => Convert.ToBase64String(new byte[0].AsSpan(), invalidOption));
+        }
+
+        [Theory]
+        [InlineData(new byte[0], "")]
+        [InlineData(new byte[] { 5, 6, 7, 8 }, "BQYHCA==")]
+        public void TryToBase64Chars_ProducesExpectedOutput(byte[] input, string expected)
+        {
+            Span<char> dest;
+
+            // Just right
+            dest = new char[expected.Length];
+            Assert.True(Convert.TryToBase64Chars(input.AsSpan(), dest, out int charsWritten));
+            Assert.Equal(expected.Length, charsWritten);
+            Assert.Equal<char>(expected.ToCharArray(), dest.ToArray());
+
+            // Too short
+            if (expected.Length > 0)
+            {
+                dest = new char[expected.Length - 1];
+                Assert.False(Convert.TryToBase64Chars(input.AsSpan(), dest, out charsWritten));
+                Assert.Equal(0, charsWritten);
+            }
+
+            // Longer than needed
+            dest = new char[expected.Length + 1];
+            Assert.True(Convert.TryToBase64Chars(input.AsSpan(), dest, out charsWritten));
+            Assert.Equal(expected.Length, charsWritten);
+            Assert.Equal<char>(expected.ToCharArray(), dest.Slice(0, expected.Length).ToArray());
+            Assert.Equal(0, dest[dest.Length - 1]);
+        }
+
+        [Theory]
+        [InlineData((Base64FormattingOptions)(-1))]
+        [InlineData((Base64FormattingOptions)(2))]
+        public void TryToBase64Chars_InvalidOptions_Throws(Base64FormattingOptions invalidOption)
+        {
+            AssertExtensions.Throws<ArgumentException>("options",
+                () => Convert.TryToBase64Chars(new byte[0].AsSpan(), new char[0].AsSpan(), out int charsWritten, invalidOption));
+        }
+
+        [Theory]
+        [MemberData(nameof(Base64TestData))]
+        public static void TryFromBase64String(string encoded, byte[] expected)
+        {
+            if (expected == null)
+            {
+                Span<byte> actual = new byte[1000];
+                bool success = Convert.TryFromBase64String(encoded, actual, out int bytesWritten);
+                Assert.False(success);
+                Assert.Equal(0, bytesWritten);
+            }
+            else
+            {
+                // Exact-sized buffer
+                {
+                    byte[] actual = new byte[expected.Length];
+                    bool success = Convert.TryFromBase64String(encoded, actual, out int bytesWritten);
+                    Assert.True(success);
+                    Assert.Equal<byte>(expected, actual);
+                    Assert.Equal(expected.Length, bytesWritten);
+                }
+
+                // Buffer too short
+                if (expected.Length != 0)
+                {
+                    byte[] actual = new byte[expected.Length - 1];
+                    bool success = Convert.TryFromBase64String(encoded, actual, out int bytesWritten);
+                    Assert.False(success);
+                    Assert.Equal(0, bytesWritten);
+                }
+
+                // Buffer larger than needed
+                {
+                    byte[] actual = new byte[expected.Length + 1];
+                    actual[expected.Length] = 99;
+                    bool success = Convert.TryFromBase64String(encoded, actual, out int bytesWritten);
+                    Assert.True(success);
+                    Assert.Equal(99, actual[expected.Length]);
+                    Assert.Equal<byte>(expected, actual.Take(expected.Length));
+                    Assert.Equal(expected.Length, bytesWritten);
+                }
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(Base64TestData))]
+        public static void TryFromBase64Chars(string encodedAsString, byte[] expected)
+        {
+            ReadOnlySpan<char> encoded = encodedAsString;  // Executing the conversion to ROS here so people debugging don't have to step through it at the api callsite.
+            if (expected == null)
+            {
+                Span<byte> actual = new byte[1000];
+                bool success = Convert.TryFromBase64Chars(encoded, actual, out int bytesWritten);
+                Assert.False(success);
+                Assert.Equal(0, bytesWritten);
+            }
+            else
+            {
+                // Exact-sized buffer
+                {
+                    byte[] actual = new byte[expected.Length];
+                    bool success = Convert.TryFromBase64Chars(encoded, actual, out int bytesWritten);
+                    Assert.True(success);
+                    Assert.Equal<byte>(expected, actual);
+                    Assert.Equal(expected.Length, bytesWritten);
+                }
+
+                // Buffer too short
+                if (expected.Length != 0)
+                {
+                    byte[] actual = new byte[expected.Length - 1];
+                    bool success = Convert.TryFromBase64Chars(encoded, actual, out int bytesWritten);
+                    Assert.False(success);
+                    Assert.Equal(0, bytesWritten);
+                }
+
+                // Buffer larger than needed
+                {
+                    byte[] actual = new byte[expected.Length + 1];
+                    actual[expected.Length] = 99;
+                    bool success = Convert.TryFromBase64Chars(encoded, actual, out int bytesWritten);
+                    Assert.True(success);
+                    Assert.Equal(99, actual[expected.Length]);
+                    Assert.Equal<byte>(expected, actual.Take(expected.Length));
+                    Assert.Equal(expected.Length, bytesWritten);
+                }
+            }
+        }
+
+        public static IEnumerable<object[]> Base64TestData
+        {
+            get
+            {
+                foreach (Tuple<string, byte[]> tuple in Base64TestDataSeed)
+                {
+                    yield return new object[] { tuple.Item1, tuple.Item2 };
+                    yield return new object[] { InsertSpaces(tuple.Item1, 1), tuple.Item2 };
+                    yield return new object[] { InsertSpaces(tuple.Item1, 4), tuple.Item2 };
+                }
+            }
+        }
+
+        public static IEnumerable<Tuple<string, byte[]>> Base64TestDataSeed
+        {
+            get
+            {
+                // Empty
+                yield return Tuple.Create<string, byte[]>("", Array.Empty<byte>());
+
+                // All whitespace characters.
+                yield return Tuple.Create<string, byte[]>(" \t\r\n", Array.Empty<byte>());
+
+                // Pad characters
+                yield return Tuple.Create<string, byte[]>("BQYHCAZ=", "0506070806".HexToByteArray());
+                yield return Tuple.Create<string, byte[]>("BQYHCA==", "05060708".HexToByteArray());
+
+                // Typical
+                yield return Tuple.Create<string, byte[]>(
+                    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0" +
+                    "BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3",
+
+                    ("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" +
+                     "3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677").HexToByteArray()
+                );
+
+                // Input length not multiple of 4
+                yield return Tuple.Create<string, byte[]>("A", null);
+                yield return Tuple.Create<string, byte[]>("AA", null);
+                yield return Tuple.Create<string, byte[]>("AAA", null);
+                yield return Tuple.Create<string, byte[]>("AAAAA", null);
+                yield return Tuple.Create<string, byte[]>("AAAAAA", null);
+                yield return Tuple.Create<string, byte[]>("AAAAAAA", null);
+
+                // Cannot continue past end pad
+                yield return Tuple.Create<string, byte[]>("AAA=BBBB", null);
+                yield return Tuple.Create<string, byte[]>("AA==BBBB", null);
+
+                // Cannot have more than two end pads
+                yield return Tuple.Create<string, byte[]>("A===", null);
+                yield return Tuple.Create<string, byte[]>("====", null);
+
+                // Verify negative entries of charmap.
+                for (int i = 0; i < 256; i++)
+                {
+                    char c = (char)i;
+                    if (!IsValidBase64Char(c))
+                    {
+                        string text = new string(c, 1) + "AAA";
+                        yield return Tuple.Create<string, byte[]>(text, null);
+                    }
+                }
+
+                // Verify >255 character handling.
+                string largerThanByte = new string((char)256, 1);
+                yield return Tuple.Create<string, byte[]>(largerThanByte + "AAA", null);
+                yield return Tuple.Create<string, byte[]>("A" + largerThanByte + "AA", null);
+                yield return Tuple.Create<string, byte[]>("AA" + largerThanByte + "A", null);
+                yield return Tuple.Create<string, byte[]>("AAA" + largerThanByte, null);
+                yield return Tuple.Create<string, byte[]>("AAAA" + largerThanByte + "AAA", null);
+                yield return Tuple.Create<string, byte[]>("AAAA" + "A" + largerThanByte + "AA", null);
+                yield return Tuple.Create<string, byte[]>("AAAA" + "AA" + largerThanByte + "A", null);
+                yield return Tuple.Create<string, byte[]>("AAAA" + "AAA" + largerThanByte, null);
+
+                // Verify positive entries of charmap.
+                yield return Tuple.Create<string, byte[]>("+A==", new byte[] { 0xf8 });
+                yield return Tuple.Create<string, byte[]>("/A==", new byte[] { 0xfc });
+                yield return Tuple.Create<string, byte[]>("0A==", new byte[] { 0xd0 });
+                yield return Tuple.Create<string, byte[]>("1A==", new byte[] { 0xd4 });
+                yield return Tuple.Create<string, byte[]>("2A==", new byte[] { 0xd8 });
+                yield return Tuple.Create<string, byte[]>("3A==", new byte[] { 0xdc });
+                yield return Tuple.Create<string, byte[]>("4A==", new byte[] { 0xe0 });
+                yield return Tuple.Create<string, byte[]>("5A==", new byte[] { 0xe4 });
+                yield return Tuple.Create<string, byte[]>("6A==", new byte[] { 0xe8 });
+                yield return Tuple.Create<string, byte[]>("7A==", new byte[] { 0xec });
+                yield return Tuple.Create<string, byte[]>("8A==", new byte[] { 0xf0 });
+                yield return Tuple.Create<string, byte[]>("9A==", new byte[] { 0xf4 });
+                yield return Tuple.Create<string, byte[]>("AA==", new byte[] { 0x00 });
+                yield return Tuple.Create<string, byte[]>("BA==", new byte[] { 0x04 });
+                yield return Tuple.Create<string, byte[]>("CA==", new byte[] { 0x08 });
+                yield return Tuple.Create<string, byte[]>("DA==", new byte[] { 0x0c });
+                yield return Tuple.Create<string, byte[]>("EA==", new byte[] { 0x10 });
+                yield return Tuple.Create<string, byte[]>("FA==", new byte[] { 0x14 });
+                yield return Tuple.Create<string, byte[]>("GA==", new byte[] { 0x18 });
+                yield return Tuple.Create<string, byte[]>("HA==", new byte[] { 0x1c });
+                yield return Tuple.Create<string, byte[]>("IA==", new byte[] { 0x20 });
+                yield return Tuple.Create<string, byte[]>("JA==", new byte[] { 0x24 });
+                yield return Tuple.Create<string, byte[]>("KA==", new byte[] { 0x28 });
+                yield return Tuple.Create<string, byte[]>("LA==", new byte[] { 0x2c });
+                yield return Tuple.Create<string, byte[]>("MA==", new byte[] { 0x30 });
+                yield return Tuple.Create<string, byte[]>("NA==", new byte[] { 0x34 });
+                yield return Tuple.Create<string, byte[]>("OA==", new byte[] { 0x38 });
+                yield return Tuple.Create<string, byte[]>("PA==", new byte[] { 0x3c });
+                yield return Tuple.Create<string, byte[]>("QA==", new byte[] { 0x40 });
+                yield return Tuple.Create<string, byte[]>("RA==", new byte[] { 0x44 });
+                yield return Tuple.Create<string, byte[]>("SA==", new byte[] { 0x48 });
+                yield return Tuple.Create<string, byte[]>("TA==", new byte[] { 0x4c });
+                yield return Tuple.Create<string, byte[]>("UA==", new byte[] { 0x50 });
+                yield return Tuple.Create<string, byte[]>("VA==", new byte[] { 0x54 });
+                yield return Tuple.Create<string, byte[]>("WA==", new byte[] { 0x58 });
+                yield return Tuple.Create<string, byte[]>("XA==", new byte[] { 0x5c });
+                yield return Tuple.Create<string, byte[]>("YA==", new byte[] { 0x60 });
+                yield return Tuple.Create<string, byte[]>("ZA==", new byte[] { 0x64 });
+                yield return Tuple.Create<string, byte[]>("aA==", new byte[] { 0x68 });
+                yield return Tuple.Create<string, byte[]>("bA==", new byte[] { 0x6c });
+                yield return Tuple.Create<string, byte[]>("cA==", new byte[] { 0x70 });
+                yield return Tuple.Create<string, byte[]>("dA==", new byte[] { 0x74 });
+                yield return Tuple.Create<string, byte[]>("eA==", new byte[] { 0x78 });
+                yield return Tuple.Create<string, byte[]>("fA==", new byte[] { 0x7c });
+                yield return Tuple.Create<string, byte[]>("gA==", new byte[] { 0x80 });
+                yield return Tuple.Create<string, byte[]>("hA==", new byte[] { 0x84 });
+                yield return Tuple.Create<string, byte[]>("iA==", new byte[] { 0x88 });
+                yield return Tuple.Create<string, byte[]>("jA==", new byte[] { 0x8c });
+                yield return Tuple.Create<string, byte[]>("kA==", new byte[] { 0x90 });
+                yield return Tuple.Create<string, byte[]>("lA==", new byte[] { 0x94 });
+                yield return Tuple.Create<string, byte[]>("mA==", new byte[] { 0x98 });
+                yield return Tuple.Create<string, byte[]>("nA==", new byte[] { 0x9c });
+                yield return Tuple.Create<string, byte[]>("oA==", new byte[] { 0xa0 });
+                yield return Tuple.Create<string, byte[]>("pA==", new byte[] { 0xa4 });
+                yield return Tuple.Create<string, byte[]>("qA==", new byte[] { 0xa8 });
+                yield return Tuple.Create<string, byte[]>("rA==", new byte[] { 0xac });
+                yield return Tuple.Create<string, byte[]>("sA==", new byte[] { 0xb0 });
+                yield return Tuple.Create<string, byte[]>("tA==", new byte[] { 0xb4 });
+                yield return Tuple.Create<string, byte[]>("uA==", new byte[] { 0xb8 });
+                yield return Tuple.Create<string, byte[]>("vA==", new byte[] { 0xbc });
+                yield return Tuple.Create<string, byte[]>("wA==", new byte[] { 0xc0 });
+                yield return Tuple.Create<string, byte[]>("xA==", new byte[] { 0xc4 });
+                yield return Tuple.Create<string, byte[]>("yA==", new byte[] { 0xc8 });
+                yield return Tuple.Create<string, byte[]>("zA==", new byte[] { 0xcc });
+            }
+        }
+
+        private static string InsertSpaces(string text, int period)
+        {
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < text.Length; i++)
+            {
+                if ((i % period) == 0)
+                {
+                    sb.Append("  ");
+                }
+                sb.Append(text[i]);
+            }
+            sb.Append("  ");
+            return sb.ToString();
+        }
+
+        private static bool IsValidBase64Char(char c)
+        {
+            return c >= 'A' && c <= 'Z'
+                || c >= 'a' && c <= 'z'
+                || c >= '0' && c <= '9'
+                || c == '+'
+                || c == '/';
+        }
     }
 }
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Convert.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/Convert.netcoreapp.cs
deleted file mode 100644 (file)
index 1d63ca7..0000000
+++ /dev/null
@@ -1,351 +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.Linq;
-using System.Text;
-using System.Collections.Generic;
-using Xunit;
-
-using Test.Cryptography;
-
-namespace System.Tests
-{
-    public partial class ConvertTests
-    {
-        [Theory]
-        [InlineData(new byte[0], "")]
-        [InlineData(new byte[] { 5, 6, 7, 8 }, "BQYHCA==")]
-        public void ToBase64String_Span_ProducesExpectedOutput(byte[] input, string expected)
-        {
-            Assert.Equal(expected, Convert.ToBase64String(input.AsSpan()));
-            Assert.Equal(expected, Convert.ToBase64String(input.AsSpan(), Base64FormattingOptions.None));
-            Assert.Equal(expected, Convert.ToBase64String(input.AsSpan(), Base64FormattingOptions.InsertLineBreaks));
-        }
-
-        [Fact]
-        public void ToBase64String_Span_LongWithOptions_ProducesExpectedOutput()
-        {
-            byte[] input = Enumerable.Range(0, 120).Select(i => (byte)i).ToArray();
-
-            Assert.Equal(
-                "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4" +
-                "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx" +
-                "cnN0dXZ3",
-                Convert.ToBase64String(input));
-
-            Assert.Equal(
-                "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4" +
-                "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx" +
-                "cnN0dXZ3",
-                Convert.ToBase64String(input, Base64FormattingOptions.None));
-
-            Assert.Equal(
-                "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4\r\n" +
-                "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx\r\n" +
-                "cnN0dXZ3",
-                Convert.ToBase64String(input, Base64FormattingOptions.InsertLineBreaks));
-        }
-
-        [Theory]
-        [InlineData((Base64FormattingOptions)(-1))]
-        [InlineData((Base64FormattingOptions)(2))]
-        public void ToBase64String_Span_InvalidOptions_Throws(Base64FormattingOptions invalidOption)
-        {
-            AssertExtensions.Throws<ArgumentException>("options", () => Convert.ToBase64String(new byte[0].AsSpan(), invalidOption));
-        }
-
-        [Theory]
-        [InlineData(new byte[0], "")]
-        [InlineData(new byte[] { 5, 6, 7, 8 }, "BQYHCA==")]
-        public void TryToBase64Chars_ProducesExpectedOutput(byte[] input, string expected)
-        {
-            Span<char> dest;
-
-            // Just right
-            dest = new char[expected.Length];
-            Assert.True(Convert.TryToBase64Chars(input.AsSpan(), dest, out int charsWritten));
-            Assert.Equal(expected.Length, charsWritten);
-            Assert.Equal<char>(expected.ToCharArray(), dest.ToArray());
-
-            // Too short
-            if (expected.Length > 0)
-            {
-                dest = new char[expected.Length - 1];
-                Assert.False(Convert.TryToBase64Chars(input.AsSpan(), dest, out charsWritten));
-                Assert.Equal(0, charsWritten);
-            }
-
-            // Longer than needed
-            dest = new char[expected.Length + 1];
-            Assert.True(Convert.TryToBase64Chars(input.AsSpan(), dest, out charsWritten));
-            Assert.Equal(expected.Length, charsWritten);
-            Assert.Equal<char>(expected.ToCharArray(), dest.Slice(0, expected.Length).ToArray());
-            Assert.Equal(0, dest[dest.Length - 1]);
-        }
-
-        [Theory]
-        [InlineData((Base64FormattingOptions)(-1))]
-        [InlineData((Base64FormattingOptions)(2))]
-        public void TryToBase64Chars_InvalidOptions_Throws(Base64FormattingOptions invalidOption)
-        {
-            AssertExtensions.Throws<ArgumentException>("options",
-                () => Convert.TryToBase64Chars(new byte[0].AsSpan(), new char[0].AsSpan(), out int charsWritten, invalidOption));
-        }
-
-        [Theory]
-        [MemberData(nameof(Base64TestData))]
-        public static void TryFromBase64String(string encoded, byte[] expected)
-        {
-            if (expected == null)
-            {
-                Span<byte> actual = new byte[1000];
-                bool success = Convert.TryFromBase64String(encoded, actual, out int bytesWritten);
-                Assert.False(success);
-                Assert.Equal(0, bytesWritten);
-            }
-            else
-            {
-                // Exact-sized buffer
-                {
-                    byte[] actual = new byte[expected.Length];
-                    bool success = Convert.TryFromBase64String(encoded, actual, out int bytesWritten);
-                    Assert.True(success);
-                    Assert.Equal<byte>(expected, actual);
-                    Assert.Equal(expected.Length, bytesWritten);
-                }
-
-                // Buffer too short
-                if (expected.Length != 0)
-                {
-                    byte[] actual = new byte[expected.Length - 1];
-                    bool success = Convert.TryFromBase64String(encoded, actual, out int bytesWritten);
-                    Assert.False(success);
-                    Assert.Equal(0, bytesWritten);
-                }
-
-                // Buffer larger than needed
-                {
-                    byte[] actual = new byte[expected.Length + 1];
-                    actual[expected.Length] = 99;
-                    bool success = Convert.TryFromBase64String(encoded, actual, out int bytesWritten);
-                    Assert.True(success);
-                    Assert.Equal(99, actual[expected.Length]);
-                    Assert.Equal<byte>(expected, actual.Take(expected.Length));
-                    Assert.Equal(expected.Length, bytesWritten);
-                }
-            }
-        }
-
-        [Theory]
-        [MemberData(nameof(Base64TestData))]
-        public static void TryFromBase64Chars(string encodedAsString, byte[] expected)
-        {
-            ReadOnlySpan<char> encoded = encodedAsString;  // Executing the conversion to ROS here so people debugging don't have to step through it at the api callsite.
-            if (expected == null)
-            {
-                Span<byte> actual = new byte[1000];
-                bool success = Convert.TryFromBase64Chars(encoded, actual, out int bytesWritten);
-                Assert.False(success);
-                Assert.Equal(0, bytesWritten);
-            }
-            else
-            {
-                // Exact-sized buffer
-                {
-                    byte[] actual = new byte[expected.Length];
-                    bool success = Convert.TryFromBase64Chars(encoded, actual, out int bytesWritten);
-                    Assert.True(success);
-                    Assert.Equal<byte>(expected, actual);
-                    Assert.Equal(expected.Length, bytesWritten);
-                }
-
-                // Buffer too short
-                if (expected.Length != 0)
-                {
-                    byte[] actual = new byte[expected.Length - 1];
-                    bool success = Convert.TryFromBase64Chars(encoded, actual, out int bytesWritten);
-                    Assert.False(success);
-                    Assert.Equal(0, bytesWritten);
-                }
-
-                // Buffer larger than needed
-                {
-                    byte[] actual = new byte[expected.Length + 1];
-                    actual[expected.Length] = 99;
-                    bool success = Convert.TryFromBase64Chars(encoded, actual, out int bytesWritten);
-                    Assert.True(success);
-                    Assert.Equal(99, actual[expected.Length]);
-                    Assert.Equal<byte>(expected, actual.Take(expected.Length));
-                    Assert.Equal(expected.Length, bytesWritten);
-                }
-            }
-        }
-
-        public static IEnumerable<object[]> Base64TestData
-        {
-            get
-            {
-                foreach (Tuple<string, byte[]> tuple in Base64TestDataSeed)
-                {
-                    yield return new object[] { tuple.Item1, tuple.Item2 };
-                    yield return new object[] { InsertSpaces(tuple.Item1, 1), tuple.Item2 };
-                    yield return new object[] { InsertSpaces(tuple.Item1, 4), tuple.Item2 };
-                }
-            }
-        }
-
-        public static IEnumerable<Tuple<string, byte[]>> Base64TestDataSeed
-        {
-            get
-            {
-                // Empty
-                yield return Tuple.Create<string, byte[]>("", Array.Empty<byte>());
-
-                // All whitespace characters.
-                yield return Tuple.Create<string, byte[]>(" \t\r\n", Array.Empty<byte>());
-
-                // Pad characters
-                yield return Tuple.Create<string, byte[]>("BQYHCAZ=", "0506070806".HexToByteArray());
-                yield return Tuple.Create<string, byte[]>("BQYHCA==", "05060708".HexToByteArray());
-
-                // Typical
-                yield return Tuple.Create<string, byte[]>(
-                    "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0" +
-                    "BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3",
-
-                    ("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E" +
-                     "3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677").HexToByteArray()
-                );
-
-                // Input length not multiple of 4
-                yield return Tuple.Create<string, byte[]>("A", null);
-                yield return Tuple.Create<string, byte[]>("AA", null);
-                yield return Tuple.Create<string, byte[]>("AAA", null);
-                yield return Tuple.Create<string, byte[]>("AAAAA", null);
-                yield return Tuple.Create<string, byte[]>("AAAAAA", null);
-                yield return Tuple.Create<string, byte[]>("AAAAAAA", null);
-
-                // Cannot continue past end pad
-                yield return Tuple.Create<string, byte[]>("AAA=BBBB", null);
-                yield return Tuple.Create<string, byte[]>("AA==BBBB", null);
-
-                // Cannot have more than two end pads
-                yield return Tuple.Create<string, byte[]>("A===", null);
-                yield return Tuple.Create<string, byte[]>("====", null);
-
-                // Verify negative entries of charmap.
-                for (int i = 0; i < 256; i++)
-                {
-                    char c = (char)i;
-                    if (!IsValidBase64Char(c))
-                    {
-                        string text = new string(c, 1) + "AAA";
-                        yield return Tuple.Create<string, byte[]>(text, null);
-                    }
-                }
-
-                // Verify >255 character handling.
-                string largerThanByte = new string((char)256, 1);
-                yield return Tuple.Create<string, byte[]>(largerThanByte + "AAA", null);
-                yield return Tuple.Create<string, byte[]>("A" + largerThanByte + "AA", null);
-                yield return Tuple.Create<string, byte[]>("AA" + largerThanByte + "A", null);
-                yield return Tuple.Create<string, byte[]>("AAA" + largerThanByte, null);
-                yield return Tuple.Create<string, byte[]>("AAAA" + largerThanByte + "AAA", null);
-                yield return Tuple.Create<string, byte[]>("AAAA" + "A" + largerThanByte + "AA", null);
-                yield return Tuple.Create<string, byte[]>("AAAA" + "AA" + largerThanByte + "A", null);
-                yield return Tuple.Create<string, byte[]>("AAAA" + "AAA" + largerThanByte, null);
-
-                // Verify positive entries of charmap.
-                yield return Tuple.Create<string, byte[]>("+A==", new byte[] { 0xf8 });
-                yield return Tuple.Create<string, byte[]>("/A==", new byte[] { 0xfc });
-                yield return Tuple.Create<string, byte[]>("0A==", new byte[] { 0xd0 });
-                yield return Tuple.Create<string, byte[]>("1A==", new byte[] { 0xd4 });
-                yield return Tuple.Create<string, byte[]>("2A==", new byte[] { 0xd8 });
-                yield return Tuple.Create<string, byte[]>("3A==", new byte[] { 0xdc });
-                yield return Tuple.Create<string, byte[]>("4A==", new byte[] { 0xe0 });
-                yield return Tuple.Create<string, byte[]>("5A==", new byte[] { 0xe4 });
-                yield return Tuple.Create<string, byte[]>("6A==", new byte[] { 0xe8 });
-                yield return Tuple.Create<string, byte[]>("7A==", new byte[] { 0xec });
-                yield return Tuple.Create<string, byte[]>("8A==", new byte[] { 0xf0 });
-                yield return Tuple.Create<string, byte[]>("9A==", new byte[] { 0xf4 });
-                yield return Tuple.Create<string, byte[]>("AA==", new byte[] { 0x00 });
-                yield return Tuple.Create<string, byte[]>("BA==", new byte[] { 0x04 });
-                yield return Tuple.Create<string, byte[]>("CA==", new byte[] { 0x08 });
-                yield return Tuple.Create<string, byte[]>("DA==", new byte[] { 0x0c });
-                yield return Tuple.Create<string, byte[]>("EA==", new byte[] { 0x10 });
-                yield return Tuple.Create<string, byte[]>("FA==", new byte[] { 0x14 });
-                yield return Tuple.Create<string, byte[]>("GA==", new byte[] { 0x18 });
-                yield return Tuple.Create<string, byte[]>("HA==", new byte[] { 0x1c });
-                yield return Tuple.Create<string, byte[]>("IA==", new byte[] { 0x20 });
-                yield return Tuple.Create<string, byte[]>("JA==", new byte[] { 0x24 });
-                yield return Tuple.Create<string, byte[]>("KA==", new byte[] { 0x28 });
-                yield return Tuple.Create<string, byte[]>("LA==", new byte[] { 0x2c });
-                yield return Tuple.Create<string, byte[]>("MA==", new byte[] { 0x30 });
-                yield return Tuple.Create<string, byte[]>("NA==", new byte[] { 0x34 });
-                yield return Tuple.Create<string, byte[]>("OA==", new byte[] { 0x38 });
-                yield return Tuple.Create<string, byte[]>("PA==", new byte[] { 0x3c });
-                yield return Tuple.Create<string, byte[]>("QA==", new byte[] { 0x40 });
-                yield return Tuple.Create<string, byte[]>("RA==", new byte[] { 0x44 });
-                yield return Tuple.Create<string, byte[]>("SA==", new byte[] { 0x48 });
-                yield return Tuple.Create<string, byte[]>("TA==", new byte[] { 0x4c });
-                yield return Tuple.Create<string, byte[]>("UA==", new byte[] { 0x50 });
-                yield return Tuple.Create<string, byte[]>("VA==", new byte[] { 0x54 });
-                yield return Tuple.Create<string, byte[]>("WA==", new byte[] { 0x58 });
-                yield return Tuple.Create<string, byte[]>("XA==", new byte[] { 0x5c });
-                yield return Tuple.Create<string, byte[]>("YA==", new byte[] { 0x60 });
-                yield return Tuple.Create<string, byte[]>("ZA==", new byte[] { 0x64 });
-                yield return Tuple.Create<string, byte[]>("aA==", new byte[] { 0x68 });
-                yield return Tuple.Create<string, byte[]>("bA==", new byte[] { 0x6c });
-                yield return Tuple.Create<string, byte[]>("cA==", new byte[] { 0x70 });
-                yield return Tuple.Create<string, byte[]>("dA==", new byte[] { 0x74 });
-                yield return Tuple.Create<string, byte[]>("eA==", new byte[] { 0x78 });
-                yield return Tuple.Create<string, byte[]>("fA==", new byte[] { 0x7c });
-                yield return Tuple.Create<string, byte[]>("gA==", new byte[] { 0x80 });
-                yield return Tuple.Create<string, byte[]>("hA==", new byte[] { 0x84 });
-                yield return Tuple.Create<string, byte[]>("iA==", new byte[] { 0x88 });
-                yield return Tuple.Create<string, byte[]>("jA==", new byte[] { 0x8c });
-                yield return Tuple.Create<string, byte[]>("kA==", new byte[] { 0x90 });
-                yield return Tuple.Create<string, byte[]>("lA==", new byte[] { 0x94 });
-                yield return Tuple.Create<string, byte[]>("mA==", new byte[] { 0x98 });
-                yield return Tuple.Create<string, byte[]>("nA==", new byte[] { 0x9c });
-                yield return Tuple.Create<string, byte[]>("oA==", new byte[] { 0xa0 });
-                yield return Tuple.Create<string, byte[]>("pA==", new byte[] { 0xa4 });
-                yield return Tuple.Create<string, byte[]>("qA==", new byte[] { 0xa8 });
-                yield return Tuple.Create<string, byte[]>("rA==", new byte[] { 0xac });
-                yield return Tuple.Create<string, byte[]>("sA==", new byte[] { 0xb0 });
-                yield return Tuple.Create<string, byte[]>("tA==", new byte[] { 0xb4 });
-                yield return Tuple.Create<string, byte[]>("uA==", new byte[] { 0xb8 });
-                yield return Tuple.Create<string, byte[]>("vA==", new byte[] { 0xbc });
-                yield return Tuple.Create<string, byte[]>("wA==", new byte[] { 0xc0 });
-                yield return Tuple.Create<string, byte[]>("xA==", new byte[] { 0xc4 });
-                yield return Tuple.Create<string, byte[]>("yA==", new byte[] { 0xc8 });
-                yield return Tuple.Create<string, byte[]>("zA==", new byte[] { 0xcc });
-            }
-        }
-
-        private static string InsertSpaces(string text, int period)
-        {
-            StringBuilder sb = new StringBuilder();
-            for (int i = 0; i < text.Length; i++)
-            {
-                if ((i % period) == 0)
-                {
-                    sb.Append("  ");
-                }
-                sb.Append(text[i]);
-            }
-            sb.Append("  ");
-            return sb.ToString();
-        }
-
-        private static bool IsValidBase64Char(char c)
-        {
-            return c >= 'A' && c <= 'Z'
-                || c >= 'a' && c <= 'z'
-                || c >= '0' && c <= '9'
-                || c == '+'
-                || c == '/';
-        }
-    }
-}
index a240eb3..5f9039c 100644 (file)
@@ -18,6 +18,7 @@ namespace System.IO.Tests
         public static void IsPathFullyQualified_Empty()
         {
             Assert.False(Path.IsPathFullyQualified(""));
+            Assert.False(Path.IsPathFullyQualified(ReadOnlySpan<char>.Empty));
         }
 
         [PlatformSpecific(TestPlatforms.Windows)]
@@ -30,6 +31,7 @@ namespace System.IO.Tests
         public static void IsPathFullyQualified_Windows_Invalid(string path)
         {
             Assert.False(Path.IsPathFullyQualified(path));
+            Assert.False(Path.IsPathFullyQualified(path.AsSpan()));
         }
 
         [PlatformSpecific(TestPlatforms.Windows)]
@@ -51,6 +53,7 @@ namespace System.IO.Tests
         public static void IsPathFullyQualified_Windows_Valid(string path)
         {
             Assert.True(Path.IsPathFullyQualified(path));
+            Assert.True(Path.IsPathFullyQualified(path.AsSpan()));
         }
 
         [PlatformSpecific(TestPlatforms.AnyUnix)]
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/IO/Path.IsPathFullyQualified.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/IO/Path.IsPathFullyQualified.netcoreapp.cs
deleted file mode 100644 (file)
index f70ba42..0000000
+++ /dev/null
@@ -1,50 +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.IO.Tests
-{
-    public static class GetFullyQualifiedPathSpanTests
-    {
-        [Fact]
-        public static void IsPathFullyQualified_Empty()
-        {
-            Assert.False(Path.IsPathFullyQualified(ReadOnlySpan<char>.Empty));
-        }
-
-        [PlatformSpecific(TestPlatforms.Windows)]
-        [Theory]
-        [InlineData("/")]
-        [InlineData(@"\")]
-        [InlineData(".")]
-        [InlineData("C:")]
-        [InlineData("C:foo.txt")]
-        public static void IsPathFullyQualified_Windows_Invalid(string path)
-        {
-            Assert.False(Path.IsPathFullyQualified(path.AsSpan()));
-        }
-
-        [PlatformSpecific(TestPlatforms.Windows)]
-        [Theory]
-        [InlineData(@"\\")]
-        [InlineData(@"\\\")]
-        [InlineData(@"\\Server")]
-        [InlineData(@"\\Server\Foo.txt")]
-        [InlineData(@"\\Server\Share\Foo.txt")]
-        [InlineData(@"\\Server\Share\Test\Foo.txt")]
-        [InlineData(@"C:\")]
-        [InlineData(@"C:\foo1")]
-        [InlineData(@"C:\\")]
-        [InlineData(@"C:\\foo2")]
-        [InlineData(@"C:/")]
-        [InlineData(@"C:/foo1")]
-        [InlineData(@"C://")]
-        [InlineData(@"C://foo2")]
-        public static void IsPathFullyQualified_Windows_Valid(string path)
-        {
-            Assert.True(Path.IsPathFullyQualified(path.AsSpan()));
-        }
-    }
-}
index b9107b1..a9a3c78 100644 (file)
@@ -8,7 +8,7 @@ using Xunit;
 
 namespace System.IO.Tests
 {
-    public partial class PathTests : PathTestsBase
+    public class PathTests : PathTestsBase
     {
         [Theory,
             InlineData(null, null, null),
@@ -266,5 +266,238 @@ namespace System.IO.Tests
         {
             Assert.Equal(expected, Path.GetFullPath(path));
         }
+
+        [Fact]
+        public void GetDirectoryName_EmptyReturnsNull()
+        {
+            // In NetFX this throws argument exception
+            Assert.Null(Path.GetDirectoryName(string.Empty));
+        }
+
+        [Theory, MemberData(nameof(TestData_Spaces))]
+        public void GetDirectoryName_Spaces(string path)
+        {
+            if (PlatformDetection.IsWindows)
+            {
+                // In Windows spaces are eaten by Win32, making them effectively empty
+                Assert.Null(Path.GetDirectoryName(path));
+            }
+            else
+            {
+                Assert.Empty(Path.GetDirectoryName(path));
+            }
+        }
+
+        [Theory, MemberData(nameof(TestData_Spaces))]
+        public void GetDirectoryName_Span_Spaces(string path)
+        {
+            PathAssert.Empty(Path.GetDirectoryName(path.AsSpan()));
+        }
+
+        [Theory,
+            MemberData(nameof(TestData_EmbeddedNull)),
+            MemberData(nameof(TestData_ControlChars)),
+            MemberData(nameof(TestData_UnicodeWhiteSpace))]
+        public void GetDirectoryName_NetFxInvalid(string path)
+        {
+            Assert.Empty(Path.GetDirectoryName(path));
+            Assert.Equal(path, Path.GetDirectoryName(Path.Combine(path, path)));
+            PathAssert.Empty(Path.GetDirectoryName(path.AsSpan()));
+            PathAssert.Equal(path, new string(Path.GetDirectoryName(Path.Combine(path, path).AsSpan())));
+        }
+
+        [Theory, MemberData(nameof(TestData_GetDirectoryName))]
+        public void GetDirectoryName_Span(string path, string expected)
+        {
+            PathAssert.Equal(expected ?? ReadOnlySpan<char>.Empty, Path.GetDirectoryName(path.AsSpan()));
+        }
+
+        [Fact]
+        public void GetDirectoryName_Span_CurrentDirectory()
+        {
+            string curDir = Directory.GetCurrentDirectory();
+            PathAssert.Equal(curDir, Path.GetDirectoryName(Path.Combine(curDir, "baz").AsSpan()));
+            PathAssert.Empty(Path.GetDirectoryName(Path.GetPathRoot(curDir).AsSpan()));
+        }
+
+        [Theory,
+            InlineData(@" C:\dir/baz", @" C:\dir")]
+        public void GetDirectoryName_SkipSpaces(string path, string expected)
+        {
+            // We no longer trim leading spaces for any path
+            Assert.Equal(expected, Path.GetDirectoryName(path));
+        }
+
+        [Theory, MemberData(nameof(TestData_GetExtension))]
+        public void GetExtension_Span(string path, string expected)
+        {
+            PathAssert.Equal(expected, Path.GetExtension(path.AsSpan()));
+            Assert.Equal(!string.IsNullOrEmpty(expected), Path.HasExtension(path.AsSpan()));
+        }
+
+        [Theory, MemberData(nameof(TestData_GetFileName))]
+        public void GetFileName_Span(string path, string expected)
+        {
+            PathAssert.Equal(expected, Path.GetFileName(path.AsSpan()));
+        }
+
+        public static IEnumerable<object[]> TestData_GetFileName_Volume()
+        {
+            yield return new object[] { ":", ":" };
+            yield return new object[] { ".:", ".:" };
+            yield return new object[] { ".:.", ".:." };     // Not a valid drive letter
+            yield return new object[] { "file:", "file:" };
+            yield return new object[] { ":file", ":file" };
+            yield return new object[] { "file:exe", "file:exe" };
+            yield return new object[] { Path.Combine("baz", "file:exe"), "file:exe" };
+            yield return new object[] { Path.Combine("bar", "baz", "file:exe"), "file:exe" };
+        }
+
+        [Theory, MemberData(nameof(TestData_GetFileName_Volume))]
+        public void GetFileName_Volume(string path, string expected)
+        {
+            // We used to break on ':' on Windows. This is a valid file name character for alternate data streams.
+            // Additionally the character can show up on unix volumes mounted to Windows.
+            Assert.Equal(expected, Path.GetFileName(path));
+            PathAssert.Equal(expected, Path.GetFileName(path.AsSpan()));
+        }
+
+        [Theory, MemberData(nameof(TestData_GetFileNameWithoutExtension))]
+        public void GetFileNameWithoutExtension_Span(string path, string expected)
+        {
+            PathAssert.Equal(expected, Path.GetFileNameWithoutExtension(path.AsSpan()));
+        }
+
+        [Fact]
+        public void GetPathRoot_Empty()
+        {
+            Assert.Null(Path.GetPathRoot(string.Empty));
+        }
+
+        [Fact]
+        public void GetPathRoot_Empty_Span()
+        {
+            PathAssert.Empty(Path.GetPathRoot(ReadOnlySpan<char>.Empty));
+        }
+
+        [Theory,
+            InlineData(nameof(TestData_Spaces)),
+            InlineData(nameof(TestData_ControlChars)),
+            InlineData(nameof(TestData_EmbeddedNull)),
+            InlineData(nameof(TestData_InvalidDriveLetters)),
+            InlineData(nameof(TestData_UnicodeWhiteSpace)),
+            InlineData(nameof(TestData_EmptyString))]
+        public void IsPathRooted_NegativeCases(string path)
+        {
+            Assert.False(Path.IsPathRooted(path));
+            Assert.False(Path.IsPathRooted(path.AsSpan()));
+        }
+
+        [Fact]
+        public void GetInvalidPathChars()
+        {
+            Assert.All(Path.GetInvalidPathChars(), c =>
+            {
+                string bad = c.ToString();
+                Assert.Equal(bad + ".ok", Path.ChangeExtension(bad, "ok"));
+                Assert.Equal(bad + Path.DirectorySeparatorChar + "ok", Path.Combine(bad, "ok"));
+                Assert.Equal("ok" + Path.DirectorySeparatorChar + "ok" + Path.DirectorySeparatorChar + bad, Path.Combine("ok", "ok", bad));
+                Assert.Equal("ok" + Path.DirectorySeparatorChar + "ok" + Path.DirectorySeparatorChar + bad + Path.DirectorySeparatorChar + "ok", Path.Combine("ok", "ok", bad, "ok"));
+                Assert.Equal(bad + Path.DirectorySeparatorChar + bad + Path.DirectorySeparatorChar + bad + Path.DirectorySeparatorChar + bad + Path.DirectorySeparatorChar + bad, Path.Combine(bad, bad, bad, bad, bad));
+                Assert.Equal("", Path.GetDirectoryName(bad));
+                Assert.Equal(string.Empty, Path.GetExtension(bad));
+                Assert.Equal(bad, Path.GetFileName(bad));
+                Assert.Equal(bad, Path.GetFileNameWithoutExtension(bad));
+                if (bad[0] == '\0')
+                {
+                    Assert.Throws<ArgumentException>("path", () => Path.GetFullPath(bad));
+                }
+                else
+                {
+                    Assert.EndsWith(bad, Path.GetFullPath(bad));
+                }
+                Assert.Equal(string.Empty, Path.GetPathRoot(bad));
+                Assert.False(Path.IsPathRooted(bad));
+            });
+        }
+
+        [Fact]
+        public void GetInvalidPathChars_Span()
+        {
+            Assert.All(Path.GetInvalidPathChars(), c =>
+            {
+                string bad = c.ToString();
+                Assert.Equal(string.Empty, new string(Path.GetDirectoryName(bad.AsSpan())));
+                Assert.Equal(string.Empty, new string(Path.GetExtension(bad.AsSpan())));
+                Assert.Equal(bad, new string(Path.GetFileName(bad.AsSpan())));
+                Assert.Equal(bad, new string(Path.GetFileNameWithoutExtension(bad.AsSpan())));
+                Assert.Equal(string.Empty, new string(Path.GetPathRoot(bad.AsSpan())));
+                Assert.False(Path.IsPathRooted(bad.AsSpan()));
+            });
+        }
+
+        [Theory,
+            InlineData("http://www.microsoft.com"),
+            InlineData("file://somefile")]
+        public void GetFullPath_URIsAsFileNames(string uriAsFileName)
+        {
+            // URIs are valid filenames, though the multiple slashes will be consolidated in GetFullPath
+            Assert.Equal(
+                Path.Combine(Directory.GetCurrentDirectory(), uriAsFileName.Replace("//", Path.DirectorySeparatorChar.ToString())),
+                Path.GetFullPath(uriAsFileName));
+        }
+
+        [Theory, MemberData(nameof(TestData_NonDriveColonPaths))]
+        public void GetFullPath_NowSupportedColons(string path)
+        {
+            // Used to throw on Windows, now should never throw
+            Path.GetFullPath(path);
+        }
+
+        [Theory, MemberData(nameof(TestData_InvalidUnc))]
+        public static void GetFullPath_UNC_Invalid(string path)
+        {
+            // These UNCs used to throw on Windows
+            Path.GetFullPath(path);
+        }
+
+        [Theory,
+            MemberData(nameof(TestData_Wildcards)),
+            MemberData(nameof(TestData_ExtendedWildcards))]
+        public void GetFullPath_Wildcards(string wildcard)
+        {
+            string path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + wildcard + "ing");
+            Assert.Equal(path, Path.GetFullPath(path));
+        }
+
+        public static TheoryData<string, string, string> GetFullPathBasePath_ArgumentNullException => new TheoryData<string, string, string>
+        {
+            { @"", null, "basePath" },
+            { @"tmp",null, "basePath" },
+            { @"\home", null, "basePath"},
+            { null, @"foo\bar", "path"},
+            { null, @"foo\bar", "path"},
+        };
+
+        [Theory,
+            MemberData(nameof(GetFullPathBasePath_ArgumentNullException))]
+        public static void GetFullPath_BasePath_NullInput(string path, string basePath, string paramName)
+        {
+            Assert.Throws<ArgumentNullException>(paramName, () => Path.GetFullPath(path, basePath));
+        }
+
+        public static TheoryData<string, string, string> GetFullPathBasePath_ArgumentException => new TheoryData<string, string, string>
+        {
+            { @"", @"foo\bar", "basePath"},
+            { @"tmp", @"foo\bar", "basePath"},
+            { @"\home", @"foo\bar", "basePath"},
+        };
+
+        [Theory,
+            MemberData(nameof(GetFullPathBasePath_ArgumentException))]
+        public static void GetFullPath_BasePath_Input(string path, string basePath, string paramName)
+        {
+            Assert.Throws<ArgumentException>(paramName, () => Path.GetFullPath(path, basePath));
+        }
     }
 }
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests.netcoreapp.cs
deleted file mode 100644 (file)
index 4cc7db7..0000000
+++ /dev/null
@@ -1,245 +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.IO.Tests
-{
-    public partial class PathTests : PathTestsBase
-    {
-        [Fact]
-        public void GetDirectoryName_EmptyReturnsNull()
-        {
-            // In NetFX this throws argument exception
-            Assert.Null(Path.GetDirectoryName(string.Empty));
-        }
-
-        [Theory, MemberData(nameof(TestData_Spaces))]
-        public void GetDirectoryName_Spaces(string path)
-        {
-            if (PlatformDetection.IsWindows)
-            {
-                // In Windows spaces are eaten by Win32, making them effectively empty
-                Assert.Null(Path.GetDirectoryName(path));
-            }
-            else
-            {
-                Assert.Empty(Path.GetDirectoryName(path));
-            }
-        }
-
-        [Theory, MemberData(nameof(TestData_Spaces))]
-        public void GetDirectoryName_Span_Spaces(string path)
-        {
-            PathAssert.Empty(Path.GetDirectoryName(path.AsSpan()));
-        }
-
-        [Theory,
-            MemberData(nameof(TestData_EmbeddedNull)),
-            MemberData(nameof(TestData_ControlChars)),
-            MemberData(nameof(TestData_UnicodeWhiteSpace))]
-        public void GetDirectoryName_NetFxInvalid(string path)
-        {
-            Assert.Empty(Path.GetDirectoryName(path));
-            Assert.Equal(path, Path.GetDirectoryName(Path.Combine(path, path)));
-            PathAssert.Empty(Path.GetDirectoryName(path.AsSpan()));
-            PathAssert.Equal(path, new string(Path.GetDirectoryName(Path.Combine(path, path).AsSpan())));
-        }
-
-        [Theory, MemberData(nameof(TestData_GetDirectoryName))]
-        public void GetDirectoryName_Span(string path, string expected)
-        {
-            PathAssert.Equal(expected ?? ReadOnlySpan<char>.Empty, Path.GetDirectoryName(path.AsSpan()));
-        }
-
-        [Fact]
-        public void GetDirectoryName_Span_CurrentDirectory()
-        {
-            string curDir = Directory.GetCurrentDirectory();
-            PathAssert.Equal(curDir, Path.GetDirectoryName(Path.Combine(curDir, "baz").AsSpan()));
-            PathAssert.Empty(Path.GetDirectoryName(Path.GetPathRoot(curDir).AsSpan()));
-        }
-
-        [Theory,
-            InlineData(@" C:\dir/baz", @" C:\dir")]
-        public void GetDirectoryName_SkipSpaces(string path, string expected)
-        {
-            // We no longer trim leading spaces for any path
-            Assert.Equal(expected, Path.GetDirectoryName(path));
-        }
-
-        [Theory, MemberData(nameof(TestData_GetExtension))]
-        public void GetExtension_Span(string path, string expected)
-        {
-            PathAssert.Equal(expected, Path.GetExtension(path.AsSpan()));
-            Assert.Equal(!string.IsNullOrEmpty(expected), Path.HasExtension(path.AsSpan()));
-        }
-
-        [Theory, MemberData(nameof(TestData_GetFileName))]
-        public void GetFileName_Span(string path, string expected)
-        {
-            PathAssert.Equal(expected, Path.GetFileName(path.AsSpan()));
-        }
-
-        public static IEnumerable<object[]> TestData_GetFileName_Volume()
-        {
-            yield return new object[] { ":", ":" };
-            yield return new object[] { ".:", ".:" };
-            yield return new object[] { ".:.", ".:." };     // Not a valid drive letter
-            yield return new object[] { "file:", "file:" };
-            yield return new object[] { ":file", ":file" };
-            yield return new object[] { "file:exe", "file:exe" };
-            yield return new object[] { Path.Combine("baz", "file:exe"), "file:exe" };
-            yield return new object[] { Path.Combine("bar", "baz", "file:exe"), "file:exe" };
-        }
-
-        [Theory, MemberData(nameof(TestData_GetFileName_Volume))]
-        public void GetFileName_Volume(string path, string expected)
-        {
-            // We used to break on ':' on Windows. This is a valid file name character for alternate data streams.
-            // Additionally the character can show up on unix volumes mounted to Windows.
-            Assert.Equal(expected, Path.GetFileName(path));
-            PathAssert.Equal(expected, Path.GetFileName(path.AsSpan()));
-        }
-
-        [Theory, MemberData(nameof(TestData_GetFileNameWithoutExtension))]
-        public void GetFileNameWithoutExtension_Span(string path, string expected)
-        {
-            PathAssert.Equal(expected, Path.GetFileNameWithoutExtension(path.AsSpan()));
-        }
-
-        [Fact]
-        public void GetPathRoot_Empty()
-        {
-            Assert.Null(Path.GetPathRoot(string.Empty));
-        }
-
-        [Fact]
-        public void GetPathRoot_Empty_Span()
-        {
-            PathAssert.Empty(Path.GetPathRoot(ReadOnlySpan<char>.Empty));
-        }
-
-        [Theory,
-            InlineData(nameof(TestData_Spaces)),
-            InlineData(nameof(TestData_ControlChars)),
-            InlineData(nameof(TestData_EmbeddedNull)),
-            InlineData(nameof(TestData_InvalidDriveLetters)),
-            InlineData(nameof(TestData_UnicodeWhiteSpace)),
-            InlineData(nameof(TestData_EmptyString))]
-        public void IsPathRooted_NegativeCases(string path)
-        {
-            Assert.False(Path.IsPathRooted(path));
-            Assert.False(Path.IsPathRooted(path.AsSpan()));
-        }
-
-        [Fact]
-        public void GetInvalidPathChars()
-        {
-            Assert.All(Path.GetInvalidPathChars(), c =>
-            {
-                string bad = c.ToString();
-                Assert.Equal(bad + ".ok", Path.ChangeExtension(bad, "ok"));
-                Assert.Equal(bad + Path.DirectorySeparatorChar + "ok", Path.Combine(bad, "ok"));
-                Assert.Equal("ok" + Path.DirectorySeparatorChar + "ok" + Path.DirectorySeparatorChar + bad, Path.Combine("ok", "ok", bad));
-                Assert.Equal("ok" + Path.DirectorySeparatorChar + "ok" + Path.DirectorySeparatorChar + bad + Path.DirectorySeparatorChar + "ok", Path.Combine("ok", "ok", bad, "ok"));
-                Assert.Equal(bad + Path.DirectorySeparatorChar + bad + Path.DirectorySeparatorChar + bad + Path.DirectorySeparatorChar + bad + Path.DirectorySeparatorChar + bad, Path.Combine(bad, bad, bad, bad, bad));
-                Assert.Equal("", Path.GetDirectoryName(bad));
-                Assert.Equal(string.Empty, Path.GetExtension(bad));
-                Assert.Equal(bad, Path.GetFileName(bad));
-                Assert.Equal(bad, Path.GetFileNameWithoutExtension(bad));
-                if (bad[0] == '\0')
-                {
-                    Assert.Throws<ArgumentException>("path", () => Path.GetFullPath(bad));
-                }
-                else
-                {
-                    Assert.EndsWith(bad, Path.GetFullPath(bad));
-                }
-                Assert.Equal(string.Empty, Path.GetPathRoot(bad));
-                Assert.False(Path.IsPathRooted(bad));
-            });
-        }
-
-        [Fact]
-        public void GetInvalidPathChars_Span()
-        {
-            Assert.All(Path.GetInvalidPathChars(), c =>
-            {
-                string bad = c.ToString();
-                Assert.Equal(string.Empty, new string(Path.GetDirectoryName(bad.AsSpan())));
-                Assert.Equal(string.Empty, new string(Path.GetExtension(bad.AsSpan())));
-                Assert.Equal(bad, new string(Path.GetFileName(bad.AsSpan())));
-                Assert.Equal(bad, new string(Path.GetFileNameWithoutExtension(bad.AsSpan())));
-                Assert.Equal(string.Empty, new string(Path.GetPathRoot(bad.AsSpan())));
-                Assert.False(Path.IsPathRooted(bad.AsSpan()));
-            });
-        }
-
-        [Theory,
-            InlineData("http://www.microsoft.com"),
-            InlineData("file://somefile")]
-        public void GetFullPath_URIsAsFileNames(string uriAsFileName)
-        {
-            // URIs are valid filenames, though the multiple slashes will be consolidated in GetFullPath
-            Assert.Equal(
-                Path.Combine(Directory.GetCurrentDirectory(), uriAsFileName.Replace("//", Path.DirectorySeparatorChar.ToString())),
-                Path.GetFullPath(uriAsFileName));
-        }
-
-        [Theory, MemberData(nameof(TestData_NonDriveColonPaths))]
-        public void GetFullPath_NowSupportedColons(string path)
-        {
-            // Used to throw on Windows, now should never throw
-            Path.GetFullPath(path);
-        }
-
-        [Theory, MemberData(nameof(TestData_InvalidUnc))]
-        public static void GetFullPath_UNC_Invalid(string path)
-        {
-            // These UNCs used to throw on Windows
-            Path.GetFullPath(path);
-        }
-
-        [Theory,
-            MemberData(nameof(TestData_Wildcards)),
-            MemberData(nameof(TestData_ExtendedWildcards))]
-        public void GetFullPath_Wildcards(string wildcard)
-        {
-            string path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + wildcard + "ing");
-            Assert.Equal(path, Path.GetFullPath(path));
-        }
-
-        public static TheoryData<string, string, string> GetFullPathBasePath_ArgumentNullException => new TheoryData<string, string, string>
-        {
-            { @"", null, "basePath" },
-            { @"tmp",null, "basePath" },
-            { @"\home", null, "basePath"},
-            { null, @"foo\bar", "path"},
-            { null, @"foo\bar", "path"},
-        };
-
-        [Theory,
-            MemberData(nameof(GetFullPathBasePath_ArgumentNullException))]
-        public static void GetFullPath_BasePath_NullInput(string path, string basePath, string paramName)
-        {
-            Assert.Throws<ArgumentNullException>(paramName, () => Path.GetFullPath(path, basePath));
-        }
-
-        public static TheoryData<string, string, string> GetFullPathBasePath_ArgumentException => new TheoryData<string, string, string>
-        {
-            { @"", @"foo\bar", "basePath"},
-            { @"tmp", @"foo\bar", "basePath"},
-            { @"\home", @"foo\bar", "basePath"},
-        };
-
-        [Theory,
-            MemberData(nameof(GetFullPathBasePath_ArgumentException))]
-        public static void GetFullPath_BasePath_Input(string path, string basePath, string paramName)
-        {
-            Assert.Throws<ArgumentException>(paramName, () => Path.GetFullPath(path, basePath));
-        }
-    }
-}
index ad4d067..b070203 100644 (file)
@@ -2,12 +2,11 @@
 // 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 Xunit;
 
 namespace System.IO.Tests
 {
-    public partial class PathTestsBase
+    public class PathTestsBase
     {
         protected static string Sep = Path.DirectorySeparatorChar.ToString();
         protected static string AltSep = Path.AltDirectorySeparatorChar.ToString();
@@ -222,5 +221,20 @@ namespace System.IO.Tests
                 Assert.Equal(original, Path.GetTempPath());
             }
         }
+
+        protected static class PathAssert
+        {
+            public static void Equal(ReadOnlySpan<char> expected, ReadOnlySpan<char> actual)
+            {
+                if (!actual.SequenceEqual(expected))
+                    throw new Xunit.Sdk.EqualException(new string(expected), new string(actual));
+            }
+
+            public static void Empty(ReadOnlySpan<char> actual)
+            {
+                if (actual.Length > 0)
+                    throw new Xunit.Sdk.NotEmptyException();
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTestsBase.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTestsBase.netcoreapp.cs
deleted file mode 100644 (file)
index 0c5781c..0000000
+++ /dev/null
@@ -1,24 +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.
-
-namespace System.IO.Tests
-{
-    public partial class PathTestsBase
-    {
-        protected static class PathAssert
-        {
-            public static void Equal(ReadOnlySpan<char> expected, ReadOnlySpan<char> actual)
-            {
-                if (!actual.SequenceEqual(expected))
-                    throw new Xunit.Sdk.EqualException(new string(expected), new string(actual));
-            }
-
-            public static void Empty(ReadOnlySpan<char> actual)
-            {
-                if (actual.Length > 0)
-                    throw new Xunit.Sdk.NotEmptyException();
-            }
-        }
-    }
-}
index 2deb511..2b9d10f 100644 (file)
@@ -12,7 +12,7 @@ using Xunit;
 namespace System.IO.Tests
 {
     [PlatformSpecific(TestPlatforms.Windows)]
-    public partial class PathTests_Windows : PathTestsBase
+    public class PathTests_Windows : PathTestsBase
     {
         [Fact]
         public void GetDirectoryName_DevicePath()
@@ -364,6 +364,338 @@ namespace System.IO.Tests
             }
         }
 
+        [Theory,
+            MemberData(nameof(TestData_GetPathRoot_Windows)),
+            MemberData(nameof(TestData_GetPathRoot_Unc)),
+            MemberData(nameof(TestData_GetPathRoot_DevicePaths))]
+        public void GetPathRoot_Span(string value, string expected)
+        {
+            Assert.Equal(expected, new string(Path.GetPathRoot(value.AsSpan())));
+            Assert.True(Path.IsPathRooted(value.AsSpan()));
+        }
+
+        [Theory, MemberData(nameof(TestData_UnicodeWhiteSpace))]
+        public void GetFullPath_UnicodeWhiteSpaceStays(string component)
+        {
+            // When not NetFX full path should not cut off component
+            string path = "C:\\Test" + component;
+            Assert.Equal(path, Path.GetFullPath(path));
+        }
+
+        [Theory, MemberData(nameof(TestData_Periods))]
+        public void GetFullPath_TrailingPeriodsCut(string component)
+        {
+            // Windows cuts off any simple white space added to a path
+            string path = "C:\\Test" + component;
+            Assert.Equal("C:\\Test", Path.GetFullPath(path));
+        }
+
+        public static TheoryData<string, string, string> GetFullPath_Windows_FullyQualified => new TheoryData<string, string, string>
+        {
+            { @"C:\git\corefx", @"C:\git\corefx", @"C:\git\corefx" },
+            { @"C:\git\corefx.\.\.\.\.\.", @"C:\git\corefx", @"C:\git\corefx" },
+            { @"C:\git\corefx\\\.", @"C:\git\corefx", @"C:\git\corefx" },
+            { @"C:\git\corefx\..\corefx\.\..\corefx", @"C:\git\corefx", @"C:\git\corefx" },
+            { @"C:\somedir\..", @"C:\git\corefx", @"C:\" },
+            { @"C:\", @"C:\git\corefx", @"C:\" },
+            { @"..\..\..\..", @"C:\git\corefx", @"C:\" },
+            { @"C:\\\", @"C:\git\corefx", @"C:\" },
+            { @"C:\..\..\", @"C:\git\corefx", @"C:\" },
+            { @"C:\..\git\..\.\", @"C:\git\corefx", @"C:\" },
+            { @"C:\git\corefx\..\..\..\", @"C:\git\corefx", @"C:\" },
+            { @"C:\.\corefx\", @"C:\git\corefx", @"C:\corefx\" },
+        };
+
+        [Theory,
+            MemberData(nameof(GetFullPath_Windows_FullyQualified))]
+        public void GetFullPath_BasicExpansions_Windows(string path, string basePath, string expected)
+        {
+            Assert.Equal(expected, Path.GetFullPath(path, basePath));
+        }
+
+        public static TheoryData<string, string, string> GetFullPath_Windows_PathIsDevicePath => new TheoryData<string, string, string>
+        {
+            // Device Paths with \\?\ wont get normalized i.e. relative segments wont get removed.
+            { @"\\?\C:\git\corefx.\.\.\.\.\.", @"C:\git\corefx", @"\\?\C:\git\corefx.\.\.\.\.\." },
+            { @"\\?\C:\git\corefx\\\.", @"C:\git\corefx", @"\\?\C:\git\corefx\\\." },
+            { @"\\?\C:\git\corefx\..\corefx\.\..\corefx", @"C:\git\corefx", @"\\?\C:\git\corefx\..\corefx\.\..\corefx" },
+            { @"\\?\\somedir\..", @"C:\git\corefx", @"\\?\\somedir\.." },
+            { @"\\?\", @"C:\git\corefx", @"\\?\" },
+            { @"\\?\..\..\..\..", @"C:\git\corefx", @"\\?\..\..\..\.." },
+            { @"\\?\\\\" , @"C:\git\corefx", @"\\?\\\\" },
+            { @"\\?\C:\Foo." , @"C:\git\corefx", @"\\?\C:\Foo." },
+            { @"\\?\C:\Foo " , @"C:\git\corefx", @"\\?\C:\Foo " },
+
+            { @"\\.\C:\git\corefx.\.\.\.\.\.", @"C:\git\corefx", @"\\.\C:\git\corefx" },
+            { @"\\.\C:\git\corefx\\\.", @"C:\git\corefx", @"\\.\C:\git\corefx" },
+            { @"\\.\C:\git\corefx\..\corefx\.\..\corefx", @"C:\git\corefx", @"\\.\C:\git\corefx" },
+            { @"\\.\\somedir\..", @"C:\git\corefx", @"\\.\" },
+            { @"\\.\", @"C:\git\corefx", @"\\.\" },
+            { @"\\.\..\..\..\..", @"C:\git\corefx", @"\\.\" },
+            { @"\\.\", @"C:\git\corefx", @"\\.\" },
+            { @"\\.\C:\Foo." , @"C:\git\corefx", @"\\.\C:\Foo" },
+            { @"\\.\C:\Foo " , @"C:\git\corefx", @"\\.\C:\Foo" },
+        };
+
+        [Theory,
+            MemberData(nameof(GetFullPath_Windows_PathIsDevicePath))]
+        public void GetFullPath_BasicExpansions_Windows_PathIsDevicePath(string path, string basePath, string expected)
+        {
+            Assert.Equal(expected, Path.GetFullPath(path, basePath));
+            Assert.Equal(expected, Path.GetFullPath(path, @"\\.\" + basePath));
+            Assert.Equal(expected, Path.GetFullPath(path, @"\\?\" + basePath));
+        }
+
+        public static TheoryData<string, string, string> GetFullPath_Windows_UNC => new TheoryData<string, string, string>
+        {
+            { @"foo", @"", @"foo" },
+            { @"foo", @"server1", @"server1\foo" },
+            { @"\foo", @"server2", @"server2\foo" },
+            { @"foo", @"server3\", @"server3\foo" },
+            { @"..\foo", @"server4", @"server4\..\foo" },
+            { @".\foo", @"server5\share", @"server5\share\foo" },
+            { @"..\foo", @"server6\share", @"server6\share\foo" },
+            { @"\foo", @"a\b\\", @"a\b\foo" },
+            { @"foo", @"LOCALHOST\share8\test.txt.~SS", @"LOCALHOST\share8\test.txt.~SS\foo" },
+            { @"foo", @"LOCALHOST\share9", @"LOCALHOST\share9\foo" },
+            { @"foo", @"LOCALHOST\shareA\dir", @"LOCALHOST\shareA\dir\foo" },
+            { @". \foo", @"LOCALHOST\shareB\", @"LOCALHOST\shareB\. \foo" },
+            { @".. \foo", @"LOCALHOST\shareC\", @"LOCALHOST\shareC\.. \foo" },
+            { @"    \foo", @"LOCALHOST\shareD\", @"LOCALHOST\shareD\    \foo" },
+
+            { "foo", @"LOCALHOST\  shareE\", @"LOCALHOST\  shareE\foo" },
+            { "foo", @"LOCALHOST\shareF\test.txt.~SS", @"LOCALHOST\shareF\test.txt.~SS\foo" },
+            { "foo", @"LOCALHOST\shareG", @"LOCALHOST\shareG\foo" },
+            { "foo", @"LOCALHOST\shareH\dir", @"LOCALHOST\shareH\dir\foo" },
+            { "foo", @"LOCALHOST\shareK\", @"LOCALHOST\shareK\foo" },
+            { "foo", @"LOCALHOST\  shareL\", @"LOCALHOST\  shareL\foo" },
+
+            // Relative segments eating into the root
+            { @".\..\foo\..\", @"server\share", @"server\share\" },
+            { @"..\foo\tmp\..\..\", @"server\share", @"server\share\" },
+            { @"..\..\..\foo", @"server\share", @"server\share\foo" },
+            { @"..\foo\..\..\tmp", @"server\share", @"server\share\tmp" },
+            { @"..\foo", @"server\share", @"server\share\foo" },
+            { @"...\\foo", @"server\share", @"server\share\...\foo" },
+            { @"...\..\.\foo", @"server\share", @"server\share\foo" },
+            { @"..\foo\tmp\..\..\..\..\..\", @"server\share", @"server\share\" },
+            { @"..\..\..\..\foo", @"server\share", @"server\share\foo" },
+        };
+
+        [Theory,
+           MemberData(nameof(GetFullPath_Windows_UNC))]
+        public void GetFullPath_CommonUnc_Windows(string path, string basePath, string expected)
+        {
+            Assert.Equal(@"\\" + expected, Path.GetFullPath(path, @"\\" + basePath));
+            Assert.Equal(@"\\.\UNC\" + expected, Path.GetFullPath(path, @"\\.\UNC\" + basePath));
+            Assert.Equal(@"\\?\UNC\" + expected, Path.GetFullPath(path, @"\\?\UNC\" + basePath));
+        }
+
+        public static TheoryData<string, string, string> GetFullPath_Windows_CommonDevicePaths => new TheoryData<string, string, string>
+        {
+            // Device paths
+            { "foo", @"C:\ ", @"C:\ \foo" },
+            { @" \ \foo", @"C:\", @"C:\ \ \foo" },
+            { @" .\foo", @"C:\", @"C:\ .\foo" },
+            { @" ..\foo", @"C:\", @"C:\ ..\foo" },
+            { @"...\foo", @"C:\", @"C:\...\foo" },
+
+            { @"foo", @"C:\\", @"C:\foo" },
+            { @"foo.", @"C:\\", @"C:\foo." },
+            { @"foo \git", @"C:\\", @"C:\foo \git" },
+            { @"foo. \git", @"C:\\", @"C:\foo. \git" },
+            { @" foo \git", @"C:\\", @"C:\ foo \git" },
+            { @"foo ", @"C:\\", @"C:\foo " },
+            { @"|\foo", @"C:\", @"C:\|\foo" },
+            { @".\foo", @"C:\", @"C:\foo" },
+            { @"..\foo", @"C:\", @"C:\foo" },
+
+            { @"\Foo1\.\foo", @"C:\", @"C:\Foo1\foo" },
+            { @"\Foo2\..\foo", @"C:\", @"C:\foo" },
+
+            { @"foo", @"GLOBALROOT\", @"GLOBALROOT\foo" },
+            { @"foo", @"", @"foo" },
+            { @".\foo", @"", @".\foo" },
+            { @"..\foo", @"", @"..\foo" },
+            { @"C:", @"", @"C:\"},
+
+            // Relative segments eating into the root
+            { @"foo", @"GLOBALROOT\", @"GLOBALROOT\foo" },
+            { @"..\..\foo\..\..\", @"", @"..\" },
+            { @".\..\..\..\..\foo", @"", @".\foo" },
+            { @"..\foo\..\..\..\", @"", @"..\" },
+            { @"\.\.\..\", @"C:\", @"C:\"},
+            { @"..\..\..\foo", @"GLOBALROOT\", @"GLOBALROOT\foo" },
+            { @"foo\..\..\", @"", @"foo\" },
+            { @".\.\foo\..\", @"", @".\" },
+        };
+
+        [Theory,
+           MemberData(nameof(GetFullPath_Windows_CommonDevicePaths))]
+        public void GetFullPath_CommonDevice_Windows(string path, string basePath, string expected)
+        {
+            Assert.Equal(@"\\.\" + expected, Path.GetFullPath(path, @"\\.\" + basePath));
+            Assert.Equal(@"\\?\" + expected, Path.GetFullPath(path, @"\\?\" + basePath));
+        }
+
+        public static TheoryData<string, string, string> GetFullPath_CommonRootedWindowsData => new TheoryData<string, string, string>
+        {
+            { "", @"C:\git\corefx", @"C:\git\corefx" },
+            { "..", @"C:\git\corefx", @"C:\git" },
+
+            // Current drive rooted
+            { @"\tmp\bar", @"C:\git\corefx", @"C:\tmp\bar" },
+            { @"\.\bar", @"C:\git\corefx", @"C:\bar" },
+            { @"\tmp\..", @"C:\git\corefx", @"C:\" },
+            { @"\tmp\bar\..", @"C:\git\corefx", @"C:\tmp" },
+            { @"\tmp\bar\..", @"C:\git\corefx", @"C:\tmp" },
+            { @"\", @"C:\git\corefx", @"C:\" },
+
+            { @"..\..\tmp\bar", @"C:\git\corefx", @"C:\tmp\bar" },
+            { @"..\..\.\bar", @"C:\git\corefx", @"C:\bar" },
+            { @"..\..\..\..\tmp\..", @"C:\git\corefx", @"C:\" },
+            { @"\tmp\..\bar..\..\..", @"C:\git\corefx", @"C:\" },
+            { @"\tmp\..\bar\..", @"C:\git\corefx", @"C:\" },
+            { @"\.\.\..\..\", @"C:\git\corefx", @"C:\" },
+
+            // Specific drive rooted
+            { @"C:tmp\foo\..", @"C:\git\corefx", @"C:\git\corefx\tmp" },
+            { @"C:tmp\foo\.", @"C:\git\corefx", @"C:\git\corefx\tmp\foo" },
+            { @"C:tmp\foo\..", @"C:\git\corefx", @"C:\git\corefx\tmp" },
+            { @"C:tmp", @"C:\git\corefx", @"C:\git\corefx\tmp" },
+            { @"C:", @"C:\git\corefx", @"C:\git\corefx" },
+            { @"C", @"C:\git\corefx", @"C:\git\corefx\C" },
+
+            { @"Z:tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
+            { @"Z:tmp\foo\.", @"C:\git\corefx", @"Z:\tmp\foo" },
+            { @"Z:tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
+            { @"Z:tmp", @"C:\git\corefx", @"Z:\tmp" },
+            { @"Z:", @"C:\git\corefx", @"Z:\" },
+            { @"Z", @"C:\git\corefx", @"C:\git\corefx\Z" },
+
+            // Relative segments eating into the root
+            { @"C:..\..\..\tmp\foo\..", @"C:\git\corefx", @"C:\tmp" },
+            { @"C:tmp\..\..\foo\.", @"C:\git\corefx", @"C:\git\foo" },
+            { @"C:..\..\tmp\foo\..", @"C:\git\corefx", @"C:\tmp" },
+            { @"C:tmp\..\", @"C:\git\corefx", @"C:\git\corefx\" },
+            { @"C:", @"C:\git\corefx", @"C:\git\corefx" },
+            { @"C", @"C:\git\corefx", @"C:\git\corefx\C" },
+
+            { @"C:tmp\..\..\..\..\foo\..", @"C:\git\corefx", @"C:\" },
+            { @"C:tmp\..\..\foo\.", @"C:\", @"C:\foo" },
+            { @"C:..\..\tmp\..\foo\..", @"C:\", @"C:\" },
+            { @"C:tmp\..\", @"C:\", @"C:\" },
+
+            { @"Z:tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
+            { @"Z:tmp\foo\.", @"C:\git\corefx", @"Z:\tmp\foo" },
+            { @"Z:tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
+            { @"Z:tmp", @"C:\git\corefx", @"Z:\tmp" },
+            { @"Z:", @"C:\git\corefx", @"Z:\" },
+            { @"Z", @"C:\git\corefx", @"C:\git\corefx\Z" },
+
+            { @"Z:..\..\..\tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
+            { @"Z:tmp\..\..\foo\.", @"C:\git\corefx", @"Z:\foo" },
+            { @"Z:..\..\tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
+            { @"Z:tmp\..\", @"C:\git\corefx", @"Z:\" },
+            { @"Z:", @"C:\git\corefx", @"Z:\" },
+            { @"Z", @"C:\git\corefx", @"C:\git\corefx\Z" },
+
+            { @"Z:tmp\..\..\..\..\foo\..", @"C:\git\corefx", @"Z:\" },
+            { @"Z:tmp\..\..\foo\.", @"C:\", @"Z:\foo" },
+            { @"Z:..\..\tmp\..\foo\..", @"C:\", @"Z:\" },
+            { @"Z:tmp\..\", @"C:\", @"Z:\" },
+        };
+
+        [Theory,
+            MemberData(nameof(GetFullPath_CommonRootedWindowsData))]
+        public void GetFullPath_CommonUnRooted_Windows(string path, string basePath, string expected)
+        {
+            Assert.Equal(expected, Path.GetFullPath(path, basePath));
+            Assert.Equal(@"\\.\" + expected, Path.GetFullPath(path, @"\\.\" + basePath));
+            Assert.Equal(@"\\?\" + expected, Path.GetFullPath(path, @"\\?\" + basePath));
+        }
+
+        [Fact]
+        public void GetFullPath_ThrowsOnEmbeddedNulls()
+        {
+            Assert.Throws<ArgumentException>(null, () => Path.GetFullPath("/gi\0t", @"C:\foo\bar"));
+        }
+
+        public static TheoryData<string, string> TestData_TrimEndingDirectorySeparator => new TheoryData<string, string>
+        {
+            { @"C:\folder\", @"C:\folder" },
+            { @"C:/folder/", @"C:/folder" },
+            { @"/folder/", @"/folder" },
+            { @"\folder\", @"\folder" },
+            { @"folder\", @"folder" },
+            { @"folder/", @"folder" },
+            { @"C:\", @"C:\" },
+            { @"C:/", @"C:/" },
+            { @"", @"" },
+            { @"/", @"/" },
+            { @"\", @"\" },
+            { @"\\server\share\", @"\\server\share" },
+            { @"\\server\share\folder\", @"\\server\share\folder" },
+            { @"\\?\C:\", @"\\?\C:\" },
+            { @"\\?\C:\folder\", @"\\?\C:\folder" },
+            { @"\\?\UNC\", @"\\?\UNC\" },
+            { @"\\?\UNC\a\", @"\\?\UNC\a\" },
+            { @"\\?\UNC\a\folder\", @"\\?\UNC\a\folder" },
+            { null, null }
+        };
+
+        public static TheoryData<string, bool> TestData_EndsInDirectorySeparator => new TheoryData<string, bool>
+        {
+            { @"\", true },
+            { @"/", true },
+            { @"C:\folder\", true },
+            { @"C:/folder/", true },
+            { @"C:\", true },
+            { @"C:/", true },
+            { @"\\", true },
+            { @"//", true },
+            { @"\\server\share\", true },
+            { @"\\?\UNC\a\", true },
+            { @"\\?\C:\", true },
+            { @"\\?\UNC\", true },
+            { @"folder\", true },
+            { @"folder", false },
+            { @"", false },
+            { null, false }
+        };
+
+        [Theory,
+            MemberData(nameof(TestData_TrimEndingDirectorySeparator))]
+        public void TrimEndingDirectorySeparator_String(string path, string expected)
+        {
+            string trimmed = Path.TrimEndingDirectorySeparator(path);
+            Assert.Equal(expected, trimmed);
+            Assert.Same(trimmed, Path.TrimEndingDirectorySeparator(trimmed));
+        }
+
+        [Theory,
+            MemberData(nameof(TestData_TrimEndingDirectorySeparator))]
+        public void TrimEndingDirectorySeparator_ReadOnlySpan(string path, string expected)
+        {
+            ReadOnlySpan<char> trimmed = Path.TrimEndingDirectorySeparator(path.AsSpan());
+            PathAssert.Equal(expected, trimmed);
+            PathAssert.Equal(trimmed, Path.TrimEndingDirectorySeparator(trimmed));
+        }
+
+        [Theory,
+            MemberData(nameof(TestData_EndsInDirectorySeparator))]
+        public void EndsInDirectorySeparator_String(string path, bool expected)
+        {
+            Assert.Equal(expected, Path.EndsInDirectorySeparator(path));
+        }
+
+        [Theory,
+            MemberData(nameof(TestData_EndsInDirectorySeparator))]
+        public void EndsInDirectorySeparator_ReadOnlySpan(string path, bool expected)
+        {
+            Assert.Equal(expected, Path.EndsInDirectorySeparator(path.AsSpan()));
+        }
+
         // Windows-only P/Invoke to create 8.3 short names from long names
         [DllImport("kernel32.dll", EntryPoint = "GetShortPathNameW", CharSet = CharSet.Unicode)]
         private static extern uint GetShortPathName(string lpszLongPath, StringBuilder lpszShortPath, int cchBuffer);
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Windows.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/IO/PathTests_Windows.netcoreapp.cs
deleted file mode 100644 (file)
index 8a24fa0..0000000
+++ /dev/null
@@ -1,343 +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.IO.Tests
-{
-    public partial class PathTests_Windows : PathTestsBase
-    {
-        [Theory,
-            MemberData(nameof(TestData_GetPathRoot_Windows)),
-            MemberData(nameof(TestData_GetPathRoot_Unc)),
-            MemberData(nameof(TestData_GetPathRoot_DevicePaths))]
-        public void GetPathRoot_Span(string value, string expected)
-        {
-            Assert.Equal(expected, new string(Path.GetPathRoot(value.AsSpan())));
-            Assert.True(Path.IsPathRooted(value.AsSpan()));
-        }
-
-        [Theory, MemberData(nameof(TestData_UnicodeWhiteSpace))]
-        public void GetFullPath_UnicodeWhiteSpaceStays(string component)
-        {
-            // When not NetFX full path should not cut off component
-            string path = "C:\\Test" + component;
-            Assert.Equal(path, Path.GetFullPath(path));
-        }
-
-        [Theory, MemberData(nameof(TestData_Periods))]
-        public void GetFullPath_TrailingPeriodsCut(string component)
-        {
-            // Windows cuts off any simple white space added to a path
-            string path = "C:\\Test" + component;
-            Assert.Equal("C:\\Test", Path.GetFullPath(path));
-        }
-
-        public static TheoryData<string, string, string> GetFullPath_Windows_FullyQualified => new TheoryData<string, string, string>
-        {
-            { @"C:\git\corefx", @"C:\git\corefx", @"C:\git\corefx" },
-            { @"C:\git\corefx.\.\.\.\.\.", @"C:\git\corefx", @"C:\git\corefx" },
-            { @"C:\git\corefx\\\.", @"C:\git\corefx", @"C:\git\corefx" },
-            { @"C:\git\corefx\..\corefx\.\..\corefx", @"C:\git\corefx", @"C:\git\corefx" },
-            { @"C:\somedir\..", @"C:\git\corefx", @"C:\" },
-            { @"C:\", @"C:\git\corefx", @"C:\" },
-            { @"..\..\..\..", @"C:\git\corefx", @"C:\" },
-            { @"C:\\\", @"C:\git\corefx", @"C:\" },
-            { @"C:\..\..\", @"C:\git\corefx", @"C:\" },
-            { @"C:\..\git\..\.\", @"C:\git\corefx", @"C:\" },
-            { @"C:\git\corefx\..\..\..\", @"C:\git\corefx", @"C:\" },
-            { @"C:\.\corefx\", @"C:\git\corefx", @"C:\corefx\" },
-        };
-
-        [Theory,
-            MemberData(nameof(GetFullPath_Windows_FullyQualified))]
-        public void GetFullPath_BasicExpansions_Windows(string path, string basePath, string expected)
-        {
-            Assert.Equal(expected, Path.GetFullPath(path, basePath));
-        }
-
-        public static TheoryData<string, string, string> GetFullPath_Windows_PathIsDevicePath => new TheoryData<string, string, string>
-        {
-            // Device Paths with \\?\ wont get normalized i.e. relative segments wont get removed.
-            { @"\\?\C:\git\corefx.\.\.\.\.\.", @"C:\git\corefx", @"\\?\C:\git\corefx.\.\.\.\.\." },
-            { @"\\?\C:\git\corefx\\\.", @"C:\git\corefx", @"\\?\C:\git\corefx\\\." },
-            { @"\\?\C:\git\corefx\..\corefx\.\..\corefx", @"C:\git\corefx", @"\\?\C:\git\corefx\..\corefx\.\..\corefx" },
-            { @"\\?\\somedir\..", @"C:\git\corefx", @"\\?\\somedir\.." },
-            { @"\\?\", @"C:\git\corefx", @"\\?\" },
-            { @"\\?\..\..\..\..", @"C:\git\corefx", @"\\?\..\..\..\.." },
-            { @"\\?\\\\" , @"C:\git\corefx", @"\\?\\\\" },
-            { @"\\?\C:\Foo." , @"C:\git\corefx", @"\\?\C:\Foo." },
-            { @"\\?\C:\Foo " , @"C:\git\corefx", @"\\?\C:\Foo " },
-
-            { @"\\.\C:\git\corefx.\.\.\.\.\.", @"C:\git\corefx", @"\\.\C:\git\corefx" },
-            { @"\\.\C:\git\corefx\\\.", @"C:\git\corefx", @"\\.\C:\git\corefx" },
-            { @"\\.\C:\git\corefx\..\corefx\.\..\corefx", @"C:\git\corefx", @"\\.\C:\git\corefx" },
-            { @"\\.\\somedir\..", @"C:\git\corefx", @"\\.\" },
-            { @"\\.\", @"C:\git\corefx", @"\\.\" },
-            { @"\\.\..\..\..\..", @"C:\git\corefx", @"\\.\" },
-            { @"\\.\", @"C:\git\corefx", @"\\.\" },
-            { @"\\.\C:\Foo." , @"C:\git\corefx", @"\\.\C:\Foo" },
-            { @"\\.\C:\Foo " , @"C:\git\corefx", @"\\.\C:\Foo" },
-        };
-
-        [Theory,
-            MemberData(nameof(GetFullPath_Windows_PathIsDevicePath))]
-        public void GetFullPath_BasicExpansions_Windows_PathIsDevicePath(string path, string basePath, string expected)
-        {
-            Assert.Equal(expected, Path.GetFullPath(path, basePath));
-            Assert.Equal(expected, Path.GetFullPath(path, @"\\.\" + basePath));
-            Assert.Equal(expected, Path.GetFullPath(path, @"\\?\" + basePath));
-        }
-
-        public static TheoryData<string, string, string> GetFullPath_Windows_UNC => new TheoryData<string, string, string>
-        {
-            { @"foo", @"", @"foo" },
-            { @"foo", @"server1", @"server1\foo" },
-            { @"\foo", @"server2", @"server2\foo" },
-            { @"foo", @"server3\", @"server3\foo" },
-            { @"..\foo", @"server4", @"server4\..\foo" },
-            { @".\foo", @"server5\share", @"server5\share\foo" },
-            { @"..\foo", @"server6\share", @"server6\share\foo" },
-            { @"\foo", @"a\b\\", @"a\b\foo" },
-            { @"foo", @"LOCALHOST\share8\test.txt.~SS", @"LOCALHOST\share8\test.txt.~SS\foo" },
-            { @"foo", @"LOCALHOST\share9", @"LOCALHOST\share9\foo" },
-            { @"foo", @"LOCALHOST\shareA\dir", @"LOCALHOST\shareA\dir\foo" },
-            { @". \foo", @"LOCALHOST\shareB\", @"LOCALHOST\shareB\. \foo" },
-            { @".. \foo", @"LOCALHOST\shareC\", @"LOCALHOST\shareC\.. \foo" },
-            { @"    \foo", @"LOCALHOST\shareD\", @"LOCALHOST\shareD\    \foo" },
-
-            { "foo", @"LOCALHOST\  shareE\", @"LOCALHOST\  shareE\foo" },
-            { "foo", @"LOCALHOST\shareF\test.txt.~SS", @"LOCALHOST\shareF\test.txt.~SS\foo" },
-            { "foo", @"LOCALHOST\shareG", @"LOCALHOST\shareG\foo" },
-            { "foo", @"LOCALHOST\shareH\dir", @"LOCALHOST\shareH\dir\foo" },
-            { "foo", @"LOCALHOST\shareK\", @"LOCALHOST\shareK\foo" },
-            { "foo", @"LOCALHOST\  shareL\", @"LOCALHOST\  shareL\foo" },
-
-            // Relative segments eating into the root
-            { @".\..\foo\..\", @"server\share", @"server\share\" },
-            { @"..\foo\tmp\..\..\", @"server\share", @"server\share\" },
-            { @"..\..\..\foo", @"server\share", @"server\share\foo" },
-            { @"..\foo\..\..\tmp", @"server\share", @"server\share\tmp" },
-            { @"..\foo", @"server\share", @"server\share\foo" },
-            { @"...\\foo", @"server\share", @"server\share\...\foo" },
-            { @"...\..\.\foo", @"server\share", @"server\share\foo" },
-            { @"..\foo\tmp\..\..\..\..\..\", @"server\share", @"server\share\" },
-            { @"..\..\..\..\foo", @"server\share", @"server\share\foo" },
-        };
-
-        [Theory,
-           MemberData(nameof(GetFullPath_Windows_UNC))]
-        public void GetFullPath_CommonUnc_Windows(string path, string basePath, string expected)
-        {
-            Assert.Equal(@"\\" + expected, Path.GetFullPath(path, @"\\" + basePath));
-            Assert.Equal(@"\\.\UNC\" + expected, Path.GetFullPath(path, @"\\.\UNC\" + basePath));
-            Assert.Equal(@"\\?\UNC\" + expected, Path.GetFullPath(path, @"\\?\UNC\" + basePath));
-        }
-
-        public static TheoryData<string, string, string> GetFullPath_Windows_CommonDevicePaths => new TheoryData<string, string, string>
-        {
-            // Device paths
-            { "foo", @"C:\ ", @"C:\ \foo" },
-            { @" \ \foo", @"C:\", @"C:\ \ \foo" },
-            { @" .\foo", @"C:\", @"C:\ .\foo" },
-            { @" ..\foo", @"C:\", @"C:\ ..\foo" },
-            { @"...\foo", @"C:\", @"C:\...\foo" },
-
-            { @"foo", @"C:\\", @"C:\foo" },
-            { @"foo.", @"C:\\", @"C:\foo." },
-            { @"foo \git", @"C:\\", @"C:\foo \git" },
-            { @"foo. \git", @"C:\\", @"C:\foo. \git" },
-            { @" foo \git", @"C:\\", @"C:\ foo \git" },
-            { @"foo ", @"C:\\", @"C:\foo " },
-            { @"|\foo", @"C:\", @"C:\|\foo" },
-            { @".\foo", @"C:\", @"C:\foo" },
-            { @"..\foo", @"C:\", @"C:\foo" },
-
-            { @"\Foo1\.\foo", @"C:\", @"C:\Foo1\foo" },
-            { @"\Foo2\..\foo", @"C:\", @"C:\foo" },
-
-            { @"foo", @"GLOBALROOT\", @"GLOBALROOT\foo" },
-            { @"foo", @"", @"foo" },
-            { @".\foo", @"", @".\foo" },
-            { @"..\foo", @"", @"..\foo" },
-            { @"C:", @"", @"C:\"},
-
-            // Relative segments eating into the root
-            { @"foo", @"GLOBALROOT\", @"GLOBALROOT\foo" },
-            { @"..\..\foo\..\..\", @"", @"..\" },
-            { @".\..\..\..\..\foo", @"", @".\foo" },
-            { @"..\foo\..\..\..\", @"", @"..\" },
-            { @"\.\.\..\", @"C:\", @"C:\"},
-            { @"..\..\..\foo", @"GLOBALROOT\", @"GLOBALROOT\foo" },
-            { @"foo\..\..\", @"", @"foo\" },
-            { @".\.\foo\..\", @"", @".\" },
-        };
-
-        [Theory,
-           MemberData(nameof(GetFullPath_Windows_CommonDevicePaths))]
-        public void GetFullPath_CommonDevice_Windows(string path, string basePath, string expected)
-        {
-            Assert.Equal(@"\\.\" + expected, Path.GetFullPath(path, @"\\.\" + basePath));
-            Assert.Equal(@"\\?\" + expected, Path.GetFullPath(path, @"\\?\" + basePath));
-        }
-
-        public static TheoryData<string, string, string> GetFullPath_CommonRootedWindowsData => new TheoryData<string, string, string>
-        {
-            { "", @"C:\git\corefx", @"C:\git\corefx" },
-            { "..", @"C:\git\corefx", @"C:\git" },
-
-            // Current drive rooted
-            { @"\tmp\bar", @"C:\git\corefx", @"C:\tmp\bar" },
-            { @"\.\bar", @"C:\git\corefx", @"C:\bar" },
-            { @"\tmp\..", @"C:\git\corefx", @"C:\" },
-            { @"\tmp\bar\..", @"C:\git\corefx", @"C:\tmp" },
-            { @"\tmp\bar\..", @"C:\git\corefx", @"C:\tmp" },
-            { @"\", @"C:\git\corefx", @"C:\" },
-
-            { @"..\..\tmp\bar", @"C:\git\corefx", @"C:\tmp\bar" },
-            { @"..\..\.\bar", @"C:\git\corefx", @"C:\bar" },
-            { @"..\..\..\..\tmp\..", @"C:\git\corefx", @"C:\" },
-            { @"\tmp\..\bar..\..\..", @"C:\git\corefx", @"C:\" },
-            { @"\tmp\..\bar\..", @"C:\git\corefx", @"C:\" },
-            { @"\.\.\..\..\", @"C:\git\corefx", @"C:\" },
-
-            // Specific drive rooted
-            { @"C:tmp\foo\..", @"C:\git\corefx", @"C:\git\corefx\tmp" },
-            { @"C:tmp\foo\.", @"C:\git\corefx", @"C:\git\corefx\tmp\foo" },
-            { @"C:tmp\foo\..", @"C:\git\corefx", @"C:\git\corefx\tmp" },
-            { @"C:tmp", @"C:\git\corefx", @"C:\git\corefx\tmp" },
-            { @"C:", @"C:\git\corefx", @"C:\git\corefx" },
-            { @"C", @"C:\git\corefx", @"C:\git\corefx\C" },
-
-            { @"Z:tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
-            { @"Z:tmp\foo\.", @"C:\git\corefx", @"Z:\tmp\foo" },
-            { @"Z:tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
-            { @"Z:tmp", @"C:\git\corefx", @"Z:\tmp" },
-            { @"Z:", @"C:\git\corefx", @"Z:\" },
-            { @"Z", @"C:\git\corefx", @"C:\git\corefx\Z" },
-
-            // Relative segments eating into the root
-            { @"C:..\..\..\tmp\foo\..", @"C:\git\corefx", @"C:\tmp" },
-            { @"C:tmp\..\..\foo\.", @"C:\git\corefx", @"C:\git\foo" },
-            { @"C:..\..\tmp\foo\..", @"C:\git\corefx", @"C:\tmp" },
-            { @"C:tmp\..\", @"C:\git\corefx", @"C:\git\corefx\" },
-            { @"C:", @"C:\git\corefx", @"C:\git\corefx" },
-            { @"C", @"C:\git\corefx", @"C:\git\corefx\C" },
-
-            { @"C:tmp\..\..\..\..\foo\..", @"C:\git\corefx", @"C:\" },
-            { @"C:tmp\..\..\foo\.", @"C:\", @"C:\foo" },
-            { @"C:..\..\tmp\..\foo\..", @"C:\", @"C:\" },
-            { @"C:tmp\..\", @"C:\", @"C:\" },
-
-            { @"Z:tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
-            { @"Z:tmp\foo\.", @"C:\git\corefx", @"Z:\tmp\foo" },
-            { @"Z:tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
-            { @"Z:tmp", @"C:\git\corefx", @"Z:\tmp" },
-            { @"Z:", @"C:\git\corefx", @"Z:\" },
-            { @"Z", @"C:\git\corefx", @"C:\git\corefx\Z" },
-
-            { @"Z:..\..\..\tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
-            { @"Z:tmp\..\..\foo\.", @"C:\git\corefx", @"Z:\foo" },
-            { @"Z:..\..\tmp\foo\..", @"C:\git\corefx", @"Z:\tmp" },
-            { @"Z:tmp\..\", @"C:\git\corefx", @"Z:\" },
-            { @"Z:", @"C:\git\corefx", @"Z:\" },
-            { @"Z", @"C:\git\corefx", @"C:\git\corefx\Z" },
-
-            { @"Z:tmp\..\..\..\..\foo\..", @"C:\git\corefx", @"Z:\" },
-            { @"Z:tmp\..\..\foo\.", @"C:\", @"Z:\foo" },
-            { @"Z:..\..\tmp\..\foo\..", @"C:\", @"Z:\" },
-            { @"Z:tmp\..\", @"C:\", @"Z:\" },
-        };
-
-        [Theory,
-            MemberData(nameof(GetFullPath_CommonRootedWindowsData))]
-        public void GetFullPath_CommonUnRooted_Windows(string path, string basePath, string expected)
-        {
-            Assert.Equal(expected, Path.GetFullPath(path, basePath));
-            Assert.Equal(@"\\.\" + expected, Path.GetFullPath(path, @"\\.\" + basePath));
-            Assert.Equal(@"\\?\" + expected, Path.GetFullPath(path, @"\\?\" + basePath));
-        }
-
-        [Fact]
-        public void GetFullPath_ThrowsOnEmbeddedNulls()
-        {
-            Assert.Throws<ArgumentException>(null, () => Path.GetFullPath("/gi\0t", @"C:\foo\bar"));
-        }
-
-        public static TheoryData<string, string> TestData_TrimEndingDirectorySeparator => new TheoryData<string, string>
-        {
-            { @"C:\folder\", @"C:\folder" },
-            { @"C:/folder/", @"C:/folder" },
-            { @"/folder/", @"/folder" },
-            { @"\folder\", @"\folder" },
-            { @"folder\", @"folder" },
-            { @"folder/", @"folder" },
-            { @"C:\", @"C:\" },
-            { @"C:/", @"C:/" },
-            { @"", @"" },
-            { @"/", @"/" },
-            { @"\", @"\" },
-            { @"\\server\share\", @"\\server\share" },
-            { @"\\server\share\folder\", @"\\server\share\folder" },
-            { @"\\?\C:\", @"\\?\C:\" },
-            { @"\\?\C:\folder\", @"\\?\C:\folder" },
-            { @"\\?\UNC\", @"\\?\UNC\" },
-            { @"\\?\UNC\a\", @"\\?\UNC\a\" },
-            { @"\\?\UNC\a\folder\", @"\\?\UNC\a\folder" },
-            { null, null }
-        };
-
-        public static TheoryData<string, bool> TestData_EndsInDirectorySeparator => new TheoryData<string, bool>
-        {
-            { @"\", true },
-            { @"/", true },
-            { @"C:\folder\", true },
-            { @"C:/folder/", true },
-            { @"C:\", true },
-            { @"C:/", true },
-            { @"\\", true },
-            { @"//", true },
-            { @"\\server\share\", true },
-            { @"\\?\UNC\a\", true },
-            { @"\\?\C:\", true },
-            { @"\\?\UNC\", true },
-            { @"folder\", true },
-            { @"folder", false },
-            { @"", false },
-            { null, false }
-        };
-
-        [Theory,
-            MemberData(nameof(TestData_TrimEndingDirectorySeparator))]
-        public void TrimEndingDirectorySeparator_String(string path, string expected)
-        {
-            string trimmed = Path.TrimEndingDirectorySeparator(path);
-            Assert.Equal(expected, trimmed);
-            Assert.Same(trimmed, Path.TrimEndingDirectorySeparator(trimmed));
-        }
-
-        [Theory,
-            MemberData(nameof(TestData_TrimEndingDirectorySeparator))]
-        public void TrimEndingDirectorySeparator_ReadOnlySpan(string path, string expected)
-        {
-            ReadOnlySpan<char> trimmed = Path.TrimEndingDirectorySeparator(path.AsSpan());
-            PathAssert.Equal(expected, trimmed);
-            PathAssert.Equal(trimmed, Path.TrimEndingDirectorySeparator(trimmed));
-        }
-
-        [Theory,
-            MemberData(nameof(TestData_EndsInDirectorySeparator))]
-        public void EndsInDirectorySeparator_String(string path, bool expected)
-        {
-            Assert.Equal(expected, Path.EndsInDirectorySeparator(path));
-        }
-
-        [Theory,
-            MemberData(nameof(TestData_EndsInDirectorySeparator))]
-        public void EndsInDirectorySeparator_ReadOnlySpan(string path, bool expected)
-        {
-            Assert.Equal(expected, Path.EndsInDirectorySeparator(path.AsSpan()));
-        }
-    }
-}
index a9d8799..fc1922c 100644 (file)
@@ -1747,5 +1747,789 @@ namespace System.Tests
             Assert.Equal(quotient, Math.DivRem(dividend, divisor, out remainder));
             Assert.Equal(expectedRemainder, remainder);
         }
+
+        public static IEnumerable<object[]> Clamp_UnsignedInt_TestData()
+        {
+            yield return new object[] { 1, 1, 3, 1 };
+            yield return new object[] { 2, 1, 3, 2 };
+            yield return new object[] { 3, 1, 3, 3 };
+            yield return new object[] { 1, 1, 1, 1 };
+
+            yield return new object[] { 0, 1, 3, 1 };
+            yield return new object[] { 4, 1, 3, 3 };
+        }
+
+        public static IEnumerable<object[]> Clamp_SignedInt_TestData()
+        {
+            yield return new object[] { -1, -1, 1, -1 };
+            yield return new object[] { 0, -1, 1, 0 };
+            yield return new object[] { 1, -1, 1, 1 };
+            yield return new object[] { 1, -1, 1, 1 };
+
+            yield return new object[] { -2, -1, 1, -1 };
+            yield return new object[] { 2, -1, 1, 1 };
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity, double.NaN,              0.0)]
+        [InlineData(-3.1415926535897932,      double.NaN,              0.0)]                               //                               value: -(pi)
+        [InlineData(-2.7182818284590452,      double.NaN,              0.0)]                               //                               value: -(e)
+        [InlineData(-1.4142135623730950,      double.NaN,              0.0)]                               //                               value: -(sqrt(2))
+        [InlineData(-1.0,                     double.NaN,              0.0)]
+        [InlineData(-0.69314718055994531,     double.NaN,              0.0)]                               //                               value: -(ln(2))
+        [InlineData(-0.43429448190325183,     double.NaN,              0.0)]                               //                               value: -(log10(e))
+        [InlineData(-0.0,                     double.NaN,              0.0)]
+        [InlineData( double.NaN,              double.NaN,              0.0)]
+        [InlineData( 0.0,                     double.NaN,              0.0)]
+        [InlineData( 1.0,                     0.0,                     CrossPlatformMachineEpsilon)]
+        [InlineData( 1.0510897883672876,      0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected:  (1 / pi)
+        [InlineData( 1.0957974645564909,      0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected:  (log10(e))
+        [InlineData( 1.2095794864199787,      0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected:  (2 / pi)
+        [InlineData( 1.25,                    0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected:  (ln(2))
+        [InlineData( 1.2605918365213561,      0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected:  (1 / sqrt(2))
+        [InlineData( 1.3246090892520058,      0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected:  (pi / 4)
+        [InlineData( 1.5430806348152438,      1.0,                     CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 1.7071001431069344,      1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected:  (2 / sqrt(pi))
+        [InlineData( 2.1781835566085709,      1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected:  (sqrt(2))
+        [InlineData( 2.2341880974508023,      1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected:  (log2(e))
+        [InlineData( 2.5091784786580568,      1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi / 2)
+        [InlineData( 5.05,                    2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected:  (ln(10))
+        [InlineData( 7.6101251386622884,      2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected:  (e)
+        [InlineData( 11.591953275521521,      3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi)
+        [InlineData( double.PositiveInfinity, double.PositiveInfinity, 0.0)]
+        public static void Acosh(double value, double expectedResult, double allowedVariance)
+        {
+            AssertEqual(expectedResult, Math.Acosh(value), allowedVariance);
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  double.NegativeInfinity, 0.0)]
+        [InlineData(-11.548739357257748,      -3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi)
+        [InlineData(-7.5441371028169758,      -2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected: -(e)
+        [InlineData(-4.95,                    -2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected: -(ln(10))
+        [InlineData(-2.3012989023072949,      -1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi / 2)
+        [InlineData(-1.9978980091062796,      -1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected: -(log2(e))
+        [InlineData(-1.9350668221743567,      -1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected: -(sqrt(2))
+        [InlineData(-1.3835428792038633,      -1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected: -(2 / sqrt(pi))
+        [InlineData(-1.1752011936438015,      -1,                       CrossPlatformMachineEpsilon * 10)]
+        [InlineData(-0.86867096148600961,     -0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected: -(pi / 4)
+        [InlineData(-0.76752314512611633,     -0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected: -(1 / sqrt(2))
+        [InlineData(-0.75,                    -0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected: -(ln(2))
+        [InlineData(-0.68050167815224332,     -0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected: -(2 / pi)
+        [InlineData(-0.44807597941469025,     -0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected: -(log10(e))
+        [InlineData(-0.32371243907207108,     -0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected: -(1 / pi)
+        [InlineData(-0.0,                     -0.0,                     0.0)]
+        [InlineData( double.NaN,               double.NaN,              0.0)]
+        [InlineData( 0.0,                      0.0,                     0.0)]
+        [InlineData( 0.32371243907207108,      0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected:  (1 / pi)
+        [InlineData( 0.44807597941469025,      0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected:  (log10(e))
+        [InlineData( 0.68050167815224332,      0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected:  (2 / pi)
+        [InlineData( 0.75,                     0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected:  (ln(2))
+        [InlineData( 0.76752314512611633,      0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected:  (1 / sqrt(2))
+        [InlineData( 0.86867096148600961,      0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected:  (pi / 4)
+        [InlineData( 1.1752011936438015,       1.0,                     CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 1.3835428792038633,       1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected:  (2 / sqrt(pi))
+        [InlineData( 1.9350668221743567,       1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected:  (sqrt(2))
+        [InlineData( 1.9978980091062796,       1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected:  (log2(e))
+        [InlineData( 2.3012989023072949,       1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi / 2)
+        [InlineData( 4.95,                     2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected:  (ln(10))
+        [InlineData( 7.5441371028169758,       2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected:  (e)
+        [InlineData( 11.548739357257748,       3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi)
+        [InlineData( double.PositiveInfinity,  double.PositiveInfinity, 0.0)]
+        public static void Asinh(double value, double expectedResult, double allowedVariance)
+        {
+            AssertEqual(expectedResult, Math.Asinh(value), allowedVariance);
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  double.NaN,              0.0)]
+        [InlineData(-3.1415926535897932,       double.NaN,              0.0)]                               //                              value: -(pi)
+        [InlineData(-2.7182818284590452,       double.NaN,              0.0)]                               //                              value: -(e)
+        [InlineData(-1.4142135623730950,       double.NaN,              0.0)]                               //                              value: -(sqrt(2))
+        [InlineData(-1.0,                      double.NegativeInfinity, CrossPlatformMachineEpsilon * 10)]
+        [InlineData(-0.99627207622074994,     -3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi)
+        [InlineData(-0.99132891580059984,     -2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected: -(e)
+        [InlineData(-0.98019801980198020,     -2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected: -(ln(10))
+        [InlineData(-0.91715233566727435,     -1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi / 2)
+        [InlineData(-0.89423894585503855,     -1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected: -(log2(e))
+        [InlineData(-0.88838556158566054,     -1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected: -(sqrt(2))
+        [InlineData(-0.81046380599898809,     -1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected: -(2 / sqrt(pi))
+        [InlineData(-0.76159415595576489,     -1.0,                     CrossPlatformMachineEpsilon * 10)]
+        [InlineData(-0.65579420263267244,     -0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected: -(pi / 4)
+        [InlineData(-0.60885936501391381,     -0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected: -(1 / sqrt(2))
+        [InlineData(-0.6,                     -0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected: -(ln(2))
+        [InlineData(-0.56259360033158334,     -0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected: -(2 / pi)
+        [InlineData(-0.40890401183401433,     -0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected: -(log10(e))
+        [InlineData(-0.30797791269089433,     -0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected: -(1 / pi)
+        [InlineData(-0.0,                     -0.0,                     0.0)]
+        [InlineData( double.NaN,               double.NaN,              0.0)]
+        [InlineData( 0.0,                      0.0,                     0.0)]
+        [InlineData( 0.30797791269089433,      0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected:  (1 / pi)
+        [InlineData( 0.40890401183401433,      0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected:  (log10(e))
+        [InlineData( 0.56259360033158334,      0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected:  (2 / pi)
+        [InlineData( 0.6,                      0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected:  (ln(2))
+        [InlineData( 0.60885936501391381,      0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected:  (1 / sqrt(2))
+        [InlineData( 0.65579420263267244,      0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected:  (pi / 4)
+        [InlineData( 0.76159415595576489,      1.0,                     CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 0.81046380599898809,      1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected:  (2 / sqrt(pi))
+        [InlineData( 0.88838556158566054,      1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected:  (sqrt(2))
+        [InlineData( 0.89423894585503855,      1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected:  (log2(e))
+        [InlineData( 0.91715233566727435,      1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi / 2)
+        [InlineData( 0.98019801980198020,      2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected:  (ln(10))
+        [InlineData( 0.99132891580059984,      2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected:  (e)
+        [InlineData( 0.99627207622074994,      3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi)
+        [InlineData( 1.0,                      double.PositiveInfinity, 0.0)]
+        [InlineData( 1.4142135623730950,       double.NaN,              0.0)]                               //                              value:  (sqrt(2))
+        [InlineData( 2.7182818284590452,       double.NaN,              0.0)]                               //                              value:  (e)
+        [InlineData( 3.1415926535897932,       double.NaN,              0.0)]                               //                              value:  (pi)
+        [InlineData( double.PositiveInfinity,  double.NaN,              0.0)]
+        public static void Atanh(double value, double expectedResult, double allowedVariance)
+        {
+            AssertEqual(expectedResult, Math.Atanh(value), allowedVariance);
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  double.NegativeInfinity)]
+        [InlineData(-3.1415926535897932,      -3.1415926535897936)]     // value: -(pi)
+        [InlineData(-2.7182818284590452,      -2.7182818284590455)]     // value: -(e)
+        [InlineData(-2.3025850929940457,      -2.3025850929940463)]     // value: -(ln(10))
+        [InlineData(-1.5707963267948966,      -1.5707963267948968)]     // value: -(pi / 2)
+        [InlineData(-1.4426950408889634,      -1.4426950408889636)]     // value: -(log2(e))
+        [InlineData(-1.4142135623730950,      -1.4142135623730951)]     // value: -(sqrt(2))
+        [InlineData(-1.1283791670955126,      -1.1283791670955128)]     // value: -(2 / sqrt(pi))
+        [InlineData(-1.0,                     -1.0000000000000002)]
+        [InlineData(-0.78539816339744831,     -0.78539816339744839)]    // value: -(pi / 4)
+        [InlineData(-0.70710678118654752,     -0.70710678118654768)]    // value: -(1 / sqrt(2))
+        [InlineData(-0.69314718055994531,     -0.69314718055994540)]    // value: -(ln(2))
+        [InlineData(-0.63661977236758134,     -0.63661977236758149)]    // value: -(2 / pi)
+        [InlineData(-0.43429448190325183,     -0.43429448190325187)]    // value: -(log10(e))
+        [InlineData(-0.31830988618379067,     -0.31830988618379075)]    // value: -(1 / pi)
+        [InlineData(-0.0,                     -double.Epsilon)]
+        [InlineData( double.NaN,               double.NaN)]
+        [InlineData( 0.0,                     -double.Epsilon)]
+        [InlineData( 0.31830988618379067,      0.31830988618379064)]    // value:  (1 / pi)
+        [InlineData( 0.43429448190325183,      0.43429448190325176)]    // value:  (log10(e))
+        [InlineData( 0.63661977236758134,      0.63661977236758127)]    // value:  (2 / pi)
+        [InlineData( 0.69314718055994531,      0.69314718055994518)]    // value:  (ln(2))
+        [InlineData( 0.70710678118654752,      0.70710678118654746)]    // value:  (1 / sqrt(2))
+        [InlineData( 0.78539816339744831,      0.78539816339744817)]    // value:  (pi / 4)
+        [InlineData( 1.0,                      0.99999999999999989)]
+        [InlineData( 1.1283791670955126,       1.1283791670955123)]     // value:  (2 / sqrt(pi))
+        [InlineData( 1.4142135623730950,       1.4142135623730947)]     // value:  (sqrt(2))
+        [InlineData( 1.4426950408889634,       1.4426950408889632)]     // value:  (log2(e))
+        [InlineData( 1.5707963267948966,       1.5707963267948963)]     // value:  (pi / 2)
+        [InlineData( 2.3025850929940457,       2.3025850929940455)]     // value:  (ln(10))
+        [InlineData( 2.7182818284590452,       2.7182818284590446)]     // value:  (e)
+        [InlineData( 3.1415926535897932,       3.1415926535897927)]     // value:  (pi)
+        [InlineData( double.PositiveInfinity,  double.MaxValue)]
+        public static void BitDecrement(double value, double expectedResult)
+        {
+            AssertEqual(expectedResult, Math.BitDecrement(value), 0.0);
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  double.MinValue)]
+        [InlineData(-3.1415926535897932,      -3.1415926535897927)]     // value: -(pi)
+        [InlineData(-2.7182818284590452,      -2.7182818284590446)]     // value: -(e)
+        [InlineData(-2.3025850929940457,      -2.3025850929940455)]     // value: -(ln(10))
+        [InlineData(-1.5707963267948966,      -1.5707963267948963)]     // value: -(pi / 2)
+        [InlineData(-1.4426950408889634,      -1.4426950408889632)]     // value: -(log2(e))
+        [InlineData(-1.4142135623730950,      -1.4142135623730947)]     // value: -(sqrt(2))
+        [InlineData(-1.1283791670955126,      -1.1283791670955123)]     // value: -(2 / sqrt(pi))
+        [InlineData(-1.0,                     -0.99999999999999989)]
+        [InlineData(-0.78539816339744831,     -0.78539816339744817)]    // value: -(pi / 4)
+        [InlineData(-0.70710678118654752,     -0.70710678118654746)]    // value: -(1 / sqrt(2))
+        [InlineData(-0.69314718055994531,     -0.69314718055994518)]    // value: -(ln(2))
+        [InlineData(-0.63661977236758134,     -0.63661977236758127)]    // value: -(2 / pi)
+        [InlineData(-0.43429448190325183,     -0.43429448190325176)]    // value: -(log10(e))
+        [InlineData(-0.31830988618379067,     -0.31830988618379064)]    // value: -(1 / pi)
+        [InlineData(-0.0,                      double.Epsilon)]
+        [InlineData( double.NaN,               double.NaN)]
+        [InlineData( 0.0,                      double.Epsilon)]
+        [InlineData( 0.31830988618379067,      0.31830988618379075)]    // value:  (1 / pi)
+        [InlineData( 0.43429448190325183,      0.43429448190325187)]    // value:  (log10(e))
+        [InlineData( 0.63661977236758134,      0.63661977236758149)]    // value:  (2 / pi)
+        [InlineData( 0.69314718055994531,      0.69314718055994540)]    // value:  (ln(2))
+        [InlineData( 0.70710678118654752,      0.70710678118654768)]    // value:  (1 / sqrt(2))
+        [InlineData( 0.78539816339744831,      0.78539816339744839)]    // value:  (pi / 4)
+        [InlineData( 1.0,                      1.0000000000000002 )]
+        [InlineData( 1.1283791670955126,       1.1283791670955128 )]     // value:  (2 / sqrt(pi))
+        [InlineData( 1.4142135623730950,       1.4142135623730951 )]     // value:  (sqrt(2))
+        [InlineData( 1.4426950408889634,       1.4426950408889636 )]     // value:  (log2(e))
+        [InlineData( 1.5707963267948966,       1.5707963267948968 )]     // value:  (pi / 2)
+        [InlineData( 2.3025850929940457,       2.3025850929940463 )]     // value:  (ln(10))
+        [InlineData( 2.7182818284590452,       2.7182818284590455 )]     // value:  (e)
+        [InlineData( 3.1415926535897932,       3.1415926535897936 )]     // value:  (pi)
+        [InlineData( double.PositiveInfinity,  double.PositiveInfinity)]
+        public static void BitIncrement(double value, double expectedResult)
+        {
+            AssertEqual(expectedResult, Math.BitIncrement(value), 0.0);
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  double.NegativeInfinity, 0.0)]
+        [InlineData(-3.1415926535897932,      -1.4645918875615233,      CrossPlatformMachineEpsilon * 10)]   // value: -(pi)
+        [InlineData(-2.7182818284590452,      -1.3956124250860895,      CrossPlatformMachineEpsilon * 10)]   // value: -(e)
+        [InlineData(-2.3025850929940457,      -1.3205004784536852,      CrossPlatformMachineEpsilon * 10)]   // value: -(ln(10))
+        [InlineData(-1.5707963267948966,      -1.1624473515096265,      CrossPlatformMachineEpsilon * 10)]   // value: -(pi / 2)
+        [InlineData(-1.4426950408889634,      -1.1299472763373901,      CrossPlatformMachineEpsilon * 10)]   // value: -(log2(e))
+        [InlineData(-1.4142135623730950,      -1.1224620483093730,      CrossPlatformMachineEpsilon * 10)]   // value: -(sqrt(2))
+        [InlineData(-1.1283791670955126,      -1.0410821966965807,      CrossPlatformMachineEpsilon * 10)]   // value: -(2 / sqrt(pi))
+        [InlineData(-1.0,                     -1.0,                     CrossPlatformMachineEpsilon * 10)]
+        [InlineData(-0.78539816339744831,     -0.92263507432201421,     CrossPlatformMachineEpsilon)]        // value: -(pi / 4)
+        [InlineData(-0.70710678118654752,     -0.89089871814033930,     CrossPlatformMachineEpsilon)]        // value: -(1 / sqrt(2))
+        [InlineData(-0.69314718055994531,     -0.88499704450051772,     CrossPlatformMachineEpsilon)]        // value: -(ln(2))
+        [InlineData(-0.63661977236758134,     -0.86025401382809963,     CrossPlatformMachineEpsilon)]        // value: -(2 / pi)
+        [InlineData(-0.43429448190325183,     -0.75728863133090766,     CrossPlatformMachineEpsilon)]        // value: -(log10(e))
+        [InlineData(-0.31830988618379067,     -0.68278406325529568,     CrossPlatformMachineEpsilon)]        // value: -(1 / pi)
+        [InlineData(-0.0,                     -0.0,                     0.0)]
+        [InlineData( double.NaN,               double.NaN,              0.0)]
+        [InlineData( 0.0,                      0.0,                     0.0)]
+        [InlineData( 0.31830988618379067,      0.68278406325529568,     CrossPlatformMachineEpsilon)]        // value:  (1 / pi)
+        [InlineData( 0.43429448190325183,      0.75728863133090766,     CrossPlatformMachineEpsilon)]        // value:  (log10(e))
+        [InlineData( 0.63661977236758134,      0.86025401382809963,     CrossPlatformMachineEpsilon)]        // value:  (2 / pi)
+        [InlineData( 0.69314718055994531,      0.88499704450051772,     CrossPlatformMachineEpsilon)]        // value:  (ln(2))
+        [InlineData( 0.70710678118654752,      0.89089871814033930,     CrossPlatformMachineEpsilon)]        // value:  (1 / sqrt(2))
+        [InlineData( 0.78539816339744831,      0.92263507432201421,     CrossPlatformMachineEpsilon)]        // value:  (pi / 4)
+        [InlineData( 1.0,                      1.0,                     CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 1.1283791670955126,       1.0410821966965807,      CrossPlatformMachineEpsilon * 10)]   // value:  (2 / sqrt(pi))
+        [InlineData( 1.4142135623730950,       1.1224620483093730,      CrossPlatformMachineEpsilon * 10)]   // value:  (sqrt(2))
+        [InlineData( 1.4426950408889634,       1.1299472763373901,      CrossPlatformMachineEpsilon * 10)]   // value:  (log2(e))
+        [InlineData( 1.5707963267948966,       1.1624473515096265,      CrossPlatformMachineEpsilon * 10)]   // value:  (pi / 2)
+        [InlineData( 2.3025850929940457,       1.3205004784536852,      CrossPlatformMachineEpsilon * 10)]   // value:  (ln(10))
+        [InlineData( 2.7182818284590452,       1.3956124250860895,      CrossPlatformMachineEpsilon * 10)]   // value:  (e)
+        [InlineData( 3.1415926535897932,       1.4645918875615233,      CrossPlatformMachineEpsilon * 10)]   // value:  (pi)
+        [InlineData( double.PositiveInfinity,  double.PositiveInfinity, 0.0)]
+        public static void Cbrt(double value, double expectedResult, double allowedVariance)
+        {
+            AssertEqual(expectedResult, Math.Cbrt(value), allowedVariance);
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_SignedInt_TestData))]
+        public static void Clamp_SByte(sbyte value, sbyte min, sbyte max, sbyte expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_UnsignedInt_TestData))]
+        public static void Clamp_Byte(byte value, byte min, byte max, byte expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_SignedInt_TestData))]
+        public static void Clamp_Short(short value, short min, short max, short expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_UnsignedInt_TestData))]
+        public static void Clamp_UShort(ushort value, ushort min, ushort max, ushort expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_SignedInt_TestData))]
+        public static void Clamp_Int(int value, int min, int max, int expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_UnsignedInt_TestData))]
+        public static void Clamp_UInt(uint value, uint min, uint max, uint expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_SignedInt_TestData))]
+        public static void Clamp_Long(long value, long min, long max, long expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_UnsignedInt_TestData))]
+        public static void Clamp_ULong(ulong value, ulong min, ulong max, ulong expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_SignedInt_TestData))]
+        [InlineData(double.NegativeInfinity, double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)]
+        [InlineData(1, double.NegativeInfinity, double.PositiveInfinity, 1)]
+        [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)]
+        [InlineData(1, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity)]
+        [InlineData(1, double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity)]
+        [InlineData(double.NaN, double.NaN, double.NaN, double.NaN)]
+        [InlineData(double.NaN, double.NaN, 1, double.NaN)]
+        [InlineData(double.NaN, 1, double.NaN, double.NaN)]
+        [InlineData(double.NaN, 1, 1, double.NaN)]
+        [InlineData(1, double.NaN, double.NaN, 1)]
+        [InlineData(1, double.NaN, 1, 1)]
+        [InlineData(1, 1, double.NaN, 1)]
+        public static void Clamp_Double(double value, double min, double max, double expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_SignedInt_TestData))]
+        [InlineData(float.NegativeInfinity, float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)]
+        [InlineData(1, float.NegativeInfinity, float.PositiveInfinity, 1)]
+        [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)]
+        [InlineData(1, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity)]
+        [InlineData(1, float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity)]
+        [InlineData(float.NaN, float.NaN, float.NaN, float.NaN)]
+        [InlineData(float.NaN, float.NaN, 1, float.NaN)]
+        [InlineData(float.NaN, 1, float.NaN, float.NaN)]
+        [InlineData(float.NaN, 1, 1, float.NaN)]
+        [InlineData(1, float.NaN, float.NaN, 1)]
+        [InlineData(1, float.NaN, 1, 1)]
+        [InlineData(1, 1, float.NaN, 1)]
+        public static void Clamp_Float(float value, float min, float max, float expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Theory]
+        [MemberData(nameof(Clamp_SignedInt_TestData))]
+        public static void Clamp_Decimal(decimal value, decimal min, decimal max, decimal expected)
+        {
+            Assert.Equal(expected, Math.Clamp(value, min, max));
+        }
+
+        [Fact]
+        public static void Clamp_MinGreaterThanMax_ThrowsArgumentException()
+        {
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((sbyte)1, (sbyte)2, (sbyte)1));
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((byte)1, (byte)2, (byte)1));
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((short)1, (short)2, (short)1));
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((ushort)1, (ushort)2, (ushort)1));
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((int)1, (int)2, (int)1));
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((uint)1, (uint)2, (uint)1));
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((long)1, (long)2, (long)1));
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((ulong)1, (ulong)2, (ulong)1));
+
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((float)1, (float)2, (float)1));
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((double)1, (double)2, (double)1));
+            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((decimal)1, (decimal)2, (decimal)1));
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  double.NegativeInfinity,  double.NegativeInfinity)]
+        [InlineData( double.NegativeInfinity, -3.1415926535897932,       double.NegativeInfinity)]
+        [InlineData( double.NegativeInfinity, -0.0,                      double.NegativeInfinity)]
+        [InlineData( double.NegativeInfinity,  double.NaN,               double.NegativeInfinity)]
+        [InlineData( double.NegativeInfinity,  0.0,                      double.PositiveInfinity)]
+        [InlineData( double.NegativeInfinity,  3.1415926535897932,       double.PositiveInfinity)]
+        [InlineData( double.NegativeInfinity,  double.PositiveInfinity,  double.PositiveInfinity)]
+        [InlineData(-3.1415926535897932,       double.NegativeInfinity, -3.1415926535897932)]
+        [InlineData(-3.1415926535897932,      -3.1415926535897932,      -3.1415926535897932)]
+        [InlineData(-3.1415926535897932,      -0.0,                     -3.1415926535897932)]
+        [InlineData(-3.1415926535897932,       double.NaN,              -3.1415926535897932)]
+        [InlineData(-3.1415926535897932,       0.0,                      3.1415926535897932)]
+        [InlineData(-3.1415926535897932,       3.1415926535897932,       3.1415926535897932)]
+        [InlineData(-3.1415926535897932,       double.PositiveInfinity,  3.1415926535897932)]
+        [InlineData(-0.0,                      double.NegativeInfinity, -0.0)]
+        [InlineData(-0.0,                     -3.1415926535897932,      -0.0)]
+        [InlineData(-0.0,                     -0.0,                     -0.0)]
+        [InlineData(-0.0,                      double.NaN,              -0.0)]
+        [InlineData(-0.0,                      0.0,                      0.0)]
+        [InlineData(-0.0,                      3.1415926535897932,       0.0)]
+        [InlineData(-0.0,                      double.PositiveInfinity,  0.0)]
+        [InlineData( double.NaN,               double.NegativeInfinity,  double.NaN)]
+        [InlineData( double.NaN,              -3.1415926535897932,       double.NaN)]
+        [InlineData( double.NaN,              -0.0,                      double.NaN)]
+        [InlineData( double.NaN,               double.NaN,               double.NaN)]
+        [InlineData( double.NaN,               0.0,                      double.NaN)]
+        [InlineData( double.NaN,               3.1415926535897932,       double.NaN)]
+        [InlineData( double.NaN,               double.PositiveInfinity,  double.NaN)]
+        [InlineData( 0.0,                      double.NegativeInfinity, -0.0)]
+        [InlineData( 0.0,                     -3.1415926535897932,      -0.0)]
+        [InlineData( 0.0,                     -0.0,                     -0.0)]
+        [InlineData( 0.0,                      double.NaN,              -0.0)]
+        [InlineData( 0.0,                      0.0,                      0.0)]
+        [InlineData( 0.0,                      3.1415926535897932,       0.0)]
+        [InlineData( 0.0,                      double.PositiveInfinity,  0.0)]
+        [InlineData( 3.1415926535897932,       double.NegativeInfinity, -3.1415926535897932)]
+        [InlineData( 3.1415926535897932,      -3.1415926535897932,      -3.1415926535897932)]
+        [InlineData( 3.1415926535897932,      -0.0,                     -3.1415926535897932)]
+        [InlineData( 3.1415926535897932,       double.NaN,              -3.1415926535897932)]
+        [InlineData( 3.1415926535897932,       0.0,                      3.1415926535897932)]
+        [InlineData( 3.1415926535897932,       3.1415926535897932,       3.1415926535897932)]
+        [InlineData( 3.1415926535897932,       double.PositiveInfinity,  3.1415926535897932)]
+        [InlineData( double.PositiveInfinity,  double.NegativeInfinity,  double.NegativeInfinity)]
+        [InlineData( double.PositiveInfinity, -3.1415926535897932,       double.NegativeInfinity)]
+        [InlineData( double.PositiveInfinity, -0.0,                      double.NegativeInfinity)]
+        [InlineData( double.PositiveInfinity,  double.NaN,               double.NegativeInfinity)]
+        [InlineData( double.PositiveInfinity,  0.0,                      double.PositiveInfinity)]
+        [InlineData( double.PositiveInfinity,  3.1415926535897932,       double.PositiveInfinity)]
+        [InlineData( double.PositiveInfinity,  double.PositiveInfinity,  double.PositiveInfinity)]
+        public static void CopySign(double x, double y, double expectedResult)
+        {
+            AssertEqual(expectedResult, Math.CopySign(x, y), 0.0);
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  double.NegativeInfinity,  double.NegativeInfinity,  double.NaN)]
+        [InlineData( double.NegativeInfinity, -0.0,                      double.NegativeInfinity,  double.NaN)]
+        [InlineData( double.NegativeInfinity, -0.0,                     -3.1415926535897932,       double.NaN)]
+        [InlineData( double.NegativeInfinity, -0.0,                     -0.0,                      double.NaN)]
+        [InlineData( double.NegativeInfinity, -0.0,                      double.NaN,               double.NaN)]
+        [InlineData( double.NegativeInfinity, -0.0,                      0.0,                      double.NaN)]
+        [InlineData( double.NegativeInfinity, -0.0,                      3.1415926535897932,       double.NaN)]
+        [InlineData( double.NegativeInfinity, -0.0,                      double.PositiveInfinity,  double.NaN)]
+        [InlineData( double.NegativeInfinity,  0.0,                      double.NegativeInfinity,  double.NaN)]
+        [InlineData( double.NegativeInfinity,  0.0,                     -3.1415926535897932,       double.NaN)]
+        [InlineData( double.NegativeInfinity,  0.0,                     -0.0,                      double.NaN)]
+        [InlineData( double.NegativeInfinity,  0.0,                      double.NaN,               double.NaN)]
+        [InlineData( double.NegativeInfinity,  0.0,                      0.0,                      double.NaN)]
+        [InlineData( double.NegativeInfinity,  0.0,                      3.1415926535897932,       double.NaN)]
+        [InlineData( double.NegativeInfinity,  0.0,                      double.PositiveInfinity,  double.NaN)]
+        [InlineData( double.NegativeInfinity,  double.PositiveInfinity,  double.PositiveInfinity,  double.NaN)]
+        [InlineData(-1e308,                    2.0,                      1e308,                   -1e308)]
+        [InlineData(-1e308,                    2.0,                      double.PositiveInfinity,  double.PositiveInfinity)]
+        [InlineData(-5,                        4,                       -3,                       -23)]
+        [InlineData(-0.0,                      double.NegativeInfinity,  double.NegativeInfinity,  double.NaN)]
+        [InlineData(-0.0,                      double.NegativeInfinity, -3.1415926535897932,       double.NaN)]
+        [InlineData(-0.0,                      double.NegativeInfinity, -0.0,                      double.NaN)]
+        [InlineData(-0.0,                      double.NegativeInfinity,  double.NaN,               double.NaN)]
+        [InlineData(-0.0,                      double.NegativeInfinity,  0.0,                      double.NaN)]
+        [InlineData(-0.0,                      double.NegativeInfinity,  3.1415926535897932,       double.NaN)]
+        [InlineData(-0.0,                      double.NegativeInfinity,  double.PositiveInfinity,  double.NaN)]
+        [InlineData(-0.0,                      double.PositiveInfinity,  double.NegativeInfinity,  double.NaN)]
+        [InlineData(-0.0,                      double.PositiveInfinity, -3.1415926535897932,       double.NaN)]
+        [InlineData(-0.0,                      double.PositiveInfinity, -0.0,                      double.NaN)]
+        [InlineData(-0.0,                      double.PositiveInfinity,  double.NaN,               double.NaN)]
+        [InlineData(-0.0,                      double.PositiveInfinity,  0.0,                      double.NaN)]
+        [InlineData(-0.0,                      double.PositiveInfinity,  3.1415926535897932,       double.NaN)]
+        [InlineData(-0.0,                      double.PositiveInfinity,  double.PositiveInfinity,  double.NaN)]
+        [InlineData( 0.0,                      double.NegativeInfinity,  double.NegativeInfinity,  double.NaN)]
+        [InlineData( 0.0,                      double.NegativeInfinity, -3.1415926535897932,       double.NaN)]
+        [InlineData( 0.0,                      double.NegativeInfinity, -0.0,                      double.NaN)]
+        [InlineData( 0.0,                      double.NegativeInfinity,  double.NaN,               double.NaN)]
+        [InlineData( 0.0,                      double.NegativeInfinity,  0.0,                      double.NaN)]
+        [InlineData( 0.0,                      double.NegativeInfinity,  3.1415926535897932,       double.NaN)]
+        [InlineData( 0.0,                      double.NegativeInfinity,  double.PositiveInfinity,  double.NaN)]
+        [InlineData( 0.0,                      double.PositiveInfinity,  double.NegativeInfinity,  double.NaN)]
+        [InlineData( 0.0,                      double.PositiveInfinity, -3.1415926535897932,       double.NaN)]
+        [InlineData( 0.0,                      double.PositiveInfinity, -0.0,                      double.NaN)]
+        [InlineData( 0.0,                      double.PositiveInfinity,  double.NaN,               double.NaN)]
+        [InlineData( 0.0,                      double.PositiveInfinity,  0.0,                      double.NaN)]
+        [InlineData( 0.0,                      double.PositiveInfinity,  3.1415926535897932,       double.NaN)]
+        [InlineData( 0.0,                      double.PositiveInfinity,  double.PositiveInfinity,  double.NaN)]
+        [InlineData( 5,                        4,                        3,                        23)]
+        [InlineData( 1e308,                    2.0,                     -1e308,                    1e308)]
+        [InlineData( 1e308,                    2.0,                      double.NegativeInfinity,  double.NegativeInfinity)]
+        [InlineData( double.PositiveInfinity,  double.NegativeInfinity,  double.PositiveInfinity,  double.NaN)]
+        [InlineData( double.PositiveInfinity, -0.0,                      double.NegativeInfinity,  double.NaN)]
+        [InlineData( double.PositiveInfinity, -0.0,                     -3.1415926535897932,       double.NaN)]
+        [InlineData( double.PositiveInfinity, -0.0,                     -0.0,                      double.NaN)]
+        [InlineData( double.PositiveInfinity, -0.0,                      double.NaN,               double.NaN)]
+        [InlineData( double.PositiveInfinity, -0.0,                      0.0,                      double.NaN)]
+        [InlineData( double.PositiveInfinity, -0.0,                      3.1415926535897932,       double.NaN)]
+        [InlineData( double.PositiveInfinity, -0.0,                      double.PositiveInfinity,  double.NaN)]
+        [InlineData( double.PositiveInfinity,  0.0,                      double.NegativeInfinity,  double.NaN)]
+        [InlineData( double.PositiveInfinity,  0.0,                     -3.1415926535897932,       double.NaN)]
+        [InlineData( double.PositiveInfinity,  0.0,                     -0.0,                      double.NaN)]
+        [InlineData( double.PositiveInfinity,  0.0,                      double.NaN,               double.NaN)]
+        [InlineData( double.PositiveInfinity,  0.0,                      0.0,                      double.NaN)]
+        [InlineData( double.PositiveInfinity,  0.0,                      3.1415926535897932,       double.NaN)]
+        [InlineData( double.PositiveInfinity,  0.0,                      double.PositiveInfinity,  double.NaN)]
+        [InlineData( double.PositiveInfinity,  double.PositiveInfinity,  double.NegativeInfinity,  double.NaN)]
+        public static void FusedMultiplyAdd(double x, double y, double z, double expectedResult)
+        {
+            AssertEqual(expectedResult, Math.FusedMultiplyAdd(x, y, z), 0.0);
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  unchecked((int)(0x7FFFFFFF)))]
+        [InlineData(-0.0,                      unchecked((int)(0x80000000)))]
+        [InlineData( double.NaN,               unchecked((int)(0x7FFFFFFF)))]
+        [InlineData( 0.0,                      unchecked((int)(0x80000000)))]
+        [InlineData( 0.11331473229676087,     -4)]
+        [InlineData( 0.15195522325791297,     -3)]
+        [InlineData( 0.20269956628651730,     -3)]
+        [InlineData( 0.33662253682241906,     -2)]
+        [InlineData( 0.36787944117144232,     -2)]
+        [InlineData( 0.37521422724648177,     -2)]
+        [InlineData( 0.45742934732229695,     -2)]
+        [InlineData( 0.5,                     -1)]
+        [InlineData( 0.58019181037172444,     -1)]
+        [InlineData( 0.61254732653606592,     -1)]
+        [InlineData( 0.61850313780157598,     -1)]
+        [InlineData( 0.64321824193300488,     -1)]
+        [InlineData( 0.74005557395545179,     -1)]
+        [InlineData( 0.80200887896145195,     -1)]
+        [InlineData( 1,                        0)]
+        [InlineData( 1.2468689889006383,       0)]
+        [InlineData( 1.3512498725672678,       0)]
+        [InlineData( 1.5546822754821001,       0)]
+        [InlineData( 1.6168066722416747,       0)]
+        [InlineData( 1.6325269194381528,       0)]
+        [InlineData( 1.7235679341273495,       0)]
+        [InlineData( 2,                        1)]
+        [InlineData( 2.1861299583286618,       1)]
+        [InlineData( 2.6651441426902252,       1)]
+        [InlineData( 2.7182818284590452,       1)]
+        [InlineData( 2.9706864235520193,       1)]
+        [InlineData( 4.9334096679145963,       2)]
+        [InlineData( 6.5808859910179210,       2)]
+        [InlineData( 8.8249778270762876,       3)]
+        [InlineData( double.PositiveInfinity,  unchecked((int)(0x7FFFFFFF)))]
+        public static void ILogB(double value, int expectedResult)
+        {
+            Assert.Equal(expectedResult, Math.ILogB(value));
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  double.NaN,              0.0)]
+        [InlineData(-0.11331473229676087,      double.NaN,              0.0)]
+        [InlineData(-0.0,                      double.NegativeInfinity, 0.0)]
+        [InlineData( double.NaN,               double.NaN,              0.0)]
+        [InlineData( 0.0,                      double.NegativeInfinity, 0.0)]
+        [InlineData( 0.11331473229676087,     -3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi)
+        [InlineData( 0.15195522325791297,     -2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected: -(e)
+        [InlineData( 0.20269956628651730,     -2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected: -(ln(10))
+        [InlineData( 0.33662253682241906,     -1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi / 2)
+        [InlineData( 0.36787944117144232,     -1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected: -(log2(e))
+        [InlineData( 0.37521422724648177,     -1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected: -(sqrt(2))
+        [InlineData( 0.45742934732229695,     -1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected: -(2 / sqrt(pi))
+        [InlineData( 0.5,                     -1.0,                     CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 0.58019181037172444,     -0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected: -(pi / 4)
+        [InlineData( 0.61254732653606592,     -0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected: -(1 / sqrt(2))
+        [InlineData( 0.61850313780157598,     -0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected: -(ln(2))
+        [InlineData( 0.64321824193300488,     -0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected: -(2 / pi)
+        [InlineData( 0.74005557395545179,     -0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected: -(log10(e))
+        [InlineData( 0.80200887896145195,     -0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected: -(1 / pi)
+        [InlineData( 1,                        0.0,                     0.0)]
+        [InlineData( 1.2468689889006383,       0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected:  (1 / pi)
+        [InlineData( 1.3512498725672678,       0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected:  (log10(e))
+        [InlineData( 1.5546822754821001,       0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected:  (2 / pi)
+        [InlineData( 1.6168066722416747,       0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected:  (ln(2))
+        [InlineData( 1.6325269194381528,       0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected:  (1 / sqrt(2))
+        [InlineData( 1.7235679341273495,       0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected:  (pi / 4)
+        [InlineData( 2,                        1.0,                     CrossPlatformMachineEpsilon * 10)]  //                              value: (e)
+        [InlineData( 2.1861299583286618,       1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected:  (2 / sqrt(pi))
+        [InlineData( 2.6651441426902252,       1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected:  (sqrt(2))
+        [InlineData( 2.7182818284590452,       1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected:  (log2(e))
+        [InlineData( 2.9706864235520193,       1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi / 2)
+        [InlineData( 4.9334096679145963,       2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected:  (ln(10))
+        [InlineData( 6.5808859910179210,       2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected:  (e)
+        [InlineData( 8.8249778270762876,       3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi)
+        [InlineData( double.PositiveInfinity,  double.PositiveInfinity, 0.0)]
+        public static void Log2(double value, double expectedResult, double allowedVariance)
+        {
+            AssertEqual(expectedResult, Math.Log2(value), allowedVariance);
+        }
+
+        [Theory]
+        [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)]
+        [InlineData(double.MinValue, double.MaxValue, double.MaxValue)]
+        [InlineData(double.NaN, double.NaN, double.NaN)]
+        [InlineData(-0.0, 0.0, 0.0)]
+        [InlineData(2.0, -3.0, -3.0)]
+        [InlineData(3.0, -2.0, 3.0)]
+        [InlineData(double.PositiveInfinity, double.NaN, double.NaN)]
+        public static void MaxMagnitude(double x, double y, double expectedResult)
+        {
+            AssertEqual(expectedResult, Math.MaxMagnitude(x, y), 0.0);
+        }
+
+        [Theory]
+        [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)]
+        [InlineData(double.MinValue, double.MaxValue, double.MinValue)]
+        [InlineData(double.NaN, double.NaN, double.NaN)]
+        [InlineData(-0.0, 0.0, -0.0)]
+        [InlineData(2.0, -3.0, 2.0)]
+        [InlineData(3.0, -2.0, -2.0)]
+        [InlineData(double.PositiveInfinity, double.NaN, double.NaN)]
+        public static void MinMagnitude(double x, double y, double expectedResult)
+        {
+            AssertEqual(expectedResult, Math.MinMagnitude(x, y), 0.0);
+        }
+
+        [Theory]
+        [InlineData( double.NegativeInfinity,  unchecked((int)(0x7FFFFFFF)),  double.NegativeInfinity,  0)]
+        [InlineData(-0.11331473229676087,     -3,                            -0.014164341537095108,     CrossPlatformMachineEpsilon / 10)]
+        [InlineData(-0.0,                      unchecked((int)(0x80000000)), -0.0,                      0)]
+        [InlineData( double.NaN,               unchecked((int)(0x7FFFFFFF)),  double.NaN,               0)]
+        [InlineData( 0.0,                      unchecked((int)(0x80000000)),  0,                        0)]
+        [InlineData( 0.11331473229676087,     -4,                             0.0070821707685475542,    CrossPlatformMachineEpsilon / 100)]
+        [InlineData( 0.15195522325791297,     -3,                             0.018994402907239121,     CrossPlatformMachineEpsilon / 10)]
+        [InlineData( 0.20269956628651730,     -3,                             0.025337445785814663,     CrossPlatformMachineEpsilon / 10)]
+        [InlineData( 0.33662253682241906,     -2,                             0.084155634205604762,     CrossPlatformMachineEpsilon / 10)]
+        [InlineData( 0.36787944117144232,     -2,                             0.091969860292860584,     CrossPlatformMachineEpsilon / 10)]
+        [InlineData( 0.37521422724648177,     -2,                             0.093803556811620448,     CrossPlatformMachineEpsilon / 10)]
+        [InlineData( 0.45742934732229695,     -2,                             0.11435733683057424,      CrossPlatformMachineEpsilon)]
+        [InlineData( 0.5,                     -1,                             0.25,                     CrossPlatformMachineEpsilon)]
+        [InlineData( 0.58019181037172444,     -1,                             0.2900959051858622,       CrossPlatformMachineEpsilon)]
+        [InlineData( 0.61254732653606592,     -1,                             0.30627366326803296,      CrossPlatformMachineEpsilon)]
+        [InlineData( 0.61850313780157598,     -1,                             0.30925156890078798,      CrossPlatformMachineEpsilon)]
+        [InlineData( 0.64321824193300488,     -1,                             0.32160912096650246,      CrossPlatformMachineEpsilon)]
+        [InlineData( 0.74005557395545179,     -1,                             0.37002778697772587,      CrossPlatformMachineEpsilon)]
+        [InlineData( 0.80200887896145195,     -1,                             0.40100443948072595,      CrossPlatformMachineEpsilon)]
+        [InlineData( 1,                        0,                             1,                        CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 1.2468689889006383,       0,                             1.2468689889006384,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 1.3512498725672678,       0,                             1.3512498725672677,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 1.5546822754821001,       0,                             1.5546822754821001,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 1.6168066722416747,       0,                             1.6168066722416747,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 1.6325269194381528,       0,                             1.6325269194381529,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 1.7235679341273495,       0,                             1.7235679341273495,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 2,                        1,                             4,                        CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 2.1861299583286618,       1,                             4.3722599166573239,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 2.6651441426902252,       1,                             5.3302882853804503,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 2.7182818284590452,       1,                             5.4365636569180902,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 2.9706864235520193,       1,                             5.9413728471040388,       CrossPlatformMachineEpsilon * 10)]
+        [InlineData( 4.9334096679145963,       2,                             19.733638671658387,       CrossPlatformMachineEpsilon * 100)]
+        [InlineData( 6.5808859910179210,       2,                             26.323543964071686,       CrossPlatformMachineEpsilon * 100)]
+        [InlineData( 8.8249778270762876,       3,                             70.599822616610297,       CrossPlatformMachineEpsilon * 100)]
+        [InlineData( double.PositiveInfinity,  unchecked((int)(0x7FFFFFFF)),  double.PositiveInfinity,  0)]
+        public static void ScaleB(double x, int n, double expectedResult, double allowedVariance)
+        {
+            AssertEqual(expectedResult, Math.ScaleB(x, n), allowedVariance);
+        }
+
+
+        public static IEnumerable<object[]> Round_Digits_TestData
+        {
+            get
+            {
+                yield return new object[] {0, 0, 3, MidpointRounding.ToEven};
+                yield return new object[] {3.42156, 3.422, 3, MidpointRounding.ToEven};
+                yield return new object[] {-3.42156, -3.422, 3, MidpointRounding.ToEven};
+
+                yield return new object[] {0, 0, 3, MidpointRounding.AwayFromZero};
+                yield return new object[] {3.42156, 3.422, 3, MidpointRounding.AwayFromZero};
+                yield return new object[] {-3.42156, -3.422, 3, MidpointRounding.AwayFromZero};
+
+                yield return new object[] {0, 0, 3, MidpointRounding.ToZero};
+                yield return new object[] {3.42156, 3.421, 3, MidpointRounding.ToZero};
+                yield return new object[] {-3.42156, -3.421, 3, MidpointRounding.ToZero};
+
+                yield return new object[] {0, 0, 3, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {3.42156, 3.421, 3, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {-3.42156, -3.422, 3, MidpointRounding.ToNegativeInfinity};
+
+                yield return new object[] {0, 0, 3, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {3.42156, 3.422, 3, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {-3.42156, -3.421, 3, MidpointRounding.ToPositiveInfinity};
+              }
+        }
+
+        [Theory]
+        [InlineData(MidpointRounding.ToEven)]
+        [InlineData(MidpointRounding.AwayFromZero)]
+        [InlineData(MidpointRounding.ToZero)]
+        [InlineData(MidpointRounding.ToNegativeInfinity)]
+        [InlineData(MidpointRounding.ToPositiveInfinity)]
+        public static void Round_Double_Digits(MidpointRounding mode)
+        {
+            Assert.Equal(double.NaN, Math.Round(double.NaN, 3, mode));
+            Assert.Equal(double.PositiveInfinity, Math.Round(double.PositiveInfinity, 3, mode));
+            Assert.Equal(double.NegativeInfinity, Math.Round(double.NegativeInfinity, 3, mode));
+        }
+
+        [Theory]
+        [MemberData(nameof(Round_Digits_TestData))]
+        public static void Round_Double_Digits(double x, double expected, int digits, MidpointRounding mode)
+        {
+            Assert.Equal(expected, Math.Round(x, digits, mode));
+        }
+
+        [Theory]
+        [MemberData(nameof(Round_Digits_TestData))]
+        public static void Round_Decimal_Digits(decimal x, decimal expected, int digits, MidpointRounding mode)
+        {
+            Assert.Equal(expected, Math.Round(x, digits, mode));
+        }
+
+        [Theory]
+        [InlineData(MidpointRounding.ToEven)]
+        [InlineData(MidpointRounding.AwayFromZero)]
+        [InlineData(MidpointRounding.ToZero)]
+        [InlineData(MidpointRounding.ToNegativeInfinity)]
+        [InlineData(MidpointRounding.ToPositiveInfinity)]
+        public static void Round_Decimal_Digits(MidpointRounding mode)
+        {
+            Assert.Equal(decimal.Zero, Math.Round(decimal.Zero, 3, mode));
+        }
+
+        public static IEnumerable<object[]> Round_Modes_TestData
+        {
+            get
+            {
+                yield return new object[] {11, 11, MidpointRounding.ToEven};
+                yield return new object[] {11.4, 11, MidpointRounding.ToEven};
+                yield return new object[] {11.5, 12, MidpointRounding.ToEven};
+                yield return new object[] {11.6, 12, MidpointRounding.ToEven};
+                yield return new object[] {-11, -11, MidpointRounding.ToEven};
+                yield return new object[] {-11.4, -11, MidpointRounding.ToEven};
+                yield return new object[] {-11.5, -12, MidpointRounding.ToEven};
+                yield return new object[] {-11.6, -12, MidpointRounding.ToEven};
+                yield return new object[] {11, 11, MidpointRounding.AwayFromZero};
+                yield return new object[] {11.4, 11, MidpointRounding.AwayFromZero};
+                yield return new object[] {11.5, 12, MidpointRounding.AwayFromZero};
+                yield return new object[] {11.6, 12, MidpointRounding.AwayFromZero};
+                yield return new object[] {-11, -11, MidpointRounding.AwayFromZero};
+                yield return new object[] {-11.4, -11, MidpointRounding.AwayFromZero};
+                yield return new object[] {-11.5, -12, MidpointRounding.AwayFromZero};
+                yield return new object[] {-11.6, -12, MidpointRounding.AwayFromZero};
+                yield return new object[] {11, 11, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {11.4, 12, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {11.5, 12, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {11.6, 12, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {-11, -11, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {-11.4, -11, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {-11.5, -11, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {-11.6, -11, MidpointRounding.ToPositiveInfinity};
+                yield return new object[] {11.0, 11, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {11.4, 11, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {11.5, 11, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {11.6, 11, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {-11.0, -11, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {-11.4, -12, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {-11.5, -12, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {-11.6, -12, MidpointRounding.ToNegativeInfinity};
+                yield return new object[] {11.0, 11, MidpointRounding.ToZero};
+                yield return new object[] {11.4, 11, MidpointRounding.ToZero};
+                yield return new object[] {11.5, 11, MidpointRounding.ToZero};
+                yield return new object[] {11.6, 11, MidpointRounding.ToZero};
+                yield return new object[] {-11.0, -11, MidpointRounding.ToZero};
+                yield return new object[] {-11.4, -11, MidpointRounding.ToZero};
+                yield return new object[] {-11.5, -11, MidpointRounding.ToZero};
+                yield return new object[] {-11.6, -11, MidpointRounding.ToZero};
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(Round_Modes_TestData))]
+        public static void Round_Double_Modes(double x, double expected, MidpointRounding mode)
+        {
+            Assert.Equal(expected, Math.Round(x, 0, mode));
+        }
+
+        [Theory]
+        [MemberData(nameof(Round_Modes_TestData))]
+        public static void Round_Float_Modes(float x, float expected, MidpointRounding mode)
+        {
+            Assert.Equal(expected, MathF.Round(x, 0, mode));
+        }
+
+        [Theory]
+        [MemberData(nameof(Round_Modes_TestData))]
+        public static void Round_Decimal_Modes(decimal x, decimal expected, MidpointRounding mode)
+        {
+            Assert.Equal(expected, Math.Round(x, 0, mode));
+            Assert.Equal(expected, decimal.Round(x, 0, mode));
+        }
     }
 }
@@ -10,7 +10,7 @@ using System.Collections.Generic;
 
 namespace System.Tests
 {
-    public static partial class MathFTests
+    public static class MathFTests
     {
         // binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this
         // is slightly too accurate when writing tests meant to run against libm implementations
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/MathTests.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/MathTests.netcoreapp.cs
deleted file mode 100644 (file)
index b0a08a1..0000000
+++ /dev/null
@@ -1,798 +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;
-
-#pragma warning disable xUnit1025 // reporting duplicate test cases due to not distinguishing 0.0 from -0.0
-
-namespace System.Tests
-{
-    public static partial class MathTests
-    {
-        public static IEnumerable<object[]> Clamp_UnsignedInt_TestData()
-        {
-            yield return new object[] { 1, 1, 3, 1 };
-            yield return new object[] { 2, 1, 3, 2 };
-            yield return new object[] { 3, 1, 3, 3 };
-            yield return new object[] { 1, 1, 1, 1 };
-
-            yield return new object[] { 0, 1, 3, 1 };
-            yield return new object[] { 4, 1, 3, 3 };
-        }
-
-        public static IEnumerable<object[]> Clamp_SignedInt_TestData()
-        {
-            yield return new object[] { -1, -1, 1, -1 };
-            yield return new object[] { 0, -1, 1, 0 };
-            yield return new object[] { 1, -1, 1, 1 };
-            yield return new object[] { 1, -1, 1, 1 };
-
-            yield return new object[] { -2, -1, 1, -1 };
-            yield return new object[] { 2, -1, 1, 1 };
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity, double.NaN,              0.0)]
-        [InlineData(-3.1415926535897932,      double.NaN,              0.0)]                               //                               value: -(pi)
-        [InlineData(-2.7182818284590452,      double.NaN,              0.0)]                               //                               value: -(e)
-        [InlineData(-1.4142135623730950,      double.NaN,              0.0)]                               //                               value: -(sqrt(2))
-        [InlineData(-1.0,                     double.NaN,              0.0)]
-        [InlineData(-0.69314718055994531,     double.NaN,              0.0)]                               //                               value: -(ln(2))
-        [InlineData(-0.43429448190325183,     double.NaN,              0.0)]                               //                               value: -(log10(e))
-        [InlineData(-0.0,                     double.NaN,              0.0)]
-        [InlineData( double.NaN,              double.NaN,              0.0)]
-        [InlineData( 0.0,                     double.NaN,              0.0)]
-        [InlineData( 1.0,                     0.0,                     CrossPlatformMachineEpsilon)]
-        [InlineData( 1.0510897883672876,      0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected:  (1 / pi)
-        [InlineData( 1.0957974645564909,      0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected:  (log10(e))
-        [InlineData( 1.2095794864199787,      0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected:  (2 / pi)
-        [InlineData( 1.25,                    0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected:  (ln(2))
-        [InlineData( 1.2605918365213561,      0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected:  (1 / sqrt(2))
-        [InlineData( 1.3246090892520058,      0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected:  (pi / 4)
-        [InlineData( 1.5430806348152438,      1.0,                     CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 1.7071001431069344,      1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected:  (2 / sqrt(pi))
-        [InlineData( 2.1781835566085709,      1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected:  (sqrt(2))
-        [InlineData( 2.2341880974508023,      1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected:  (log2(e))
-        [InlineData( 2.5091784786580568,      1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi / 2)
-        [InlineData( 5.05,                    2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected:  (ln(10))
-        [InlineData( 7.6101251386622884,      2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected:  (e)
-        [InlineData( 11.591953275521521,      3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi)
-        [InlineData( double.PositiveInfinity, double.PositiveInfinity, 0.0)]
-        public static void Acosh(double value, double expectedResult, double allowedVariance)
-        {
-            AssertEqual(expectedResult, Math.Acosh(value), allowedVariance);
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  double.NegativeInfinity, 0.0)]
-        [InlineData(-11.548739357257748,      -3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi)
-        [InlineData(-7.5441371028169758,      -2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected: -(e)
-        [InlineData(-4.95,                    -2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected: -(ln(10))
-        [InlineData(-2.3012989023072949,      -1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi / 2)
-        [InlineData(-1.9978980091062796,      -1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected: -(log2(e))
-        [InlineData(-1.9350668221743567,      -1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected: -(sqrt(2))
-        [InlineData(-1.3835428792038633,      -1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected: -(2 / sqrt(pi))
-        [InlineData(-1.1752011936438015,      -1,                       CrossPlatformMachineEpsilon * 10)]
-        [InlineData(-0.86867096148600961,     -0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected: -(pi / 4)
-        [InlineData(-0.76752314512611633,     -0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected: -(1 / sqrt(2))
-        [InlineData(-0.75,                    -0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected: -(ln(2))
-        [InlineData(-0.68050167815224332,     -0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected: -(2 / pi)
-        [InlineData(-0.44807597941469025,     -0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected: -(log10(e))
-        [InlineData(-0.32371243907207108,     -0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected: -(1 / pi)
-        [InlineData(-0.0,                     -0.0,                     0.0)]
-        [InlineData( double.NaN,               double.NaN,              0.0)]
-        [InlineData( 0.0,                      0.0,                     0.0)]
-        [InlineData( 0.32371243907207108,      0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected:  (1 / pi)
-        [InlineData( 0.44807597941469025,      0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected:  (log10(e))
-        [InlineData( 0.68050167815224332,      0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected:  (2 / pi)
-        [InlineData( 0.75,                     0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected:  (ln(2))
-        [InlineData( 0.76752314512611633,      0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected:  (1 / sqrt(2))
-        [InlineData( 0.86867096148600961,      0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected:  (pi / 4)
-        [InlineData( 1.1752011936438015,       1.0,                     CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 1.3835428792038633,       1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected:  (2 / sqrt(pi))
-        [InlineData( 1.9350668221743567,       1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected:  (sqrt(2))
-        [InlineData( 1.9978980091062796,       1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected:  (log2(e))
-        [InlineData( 2.3012989023072949,       1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi / 2)
-        [InlineData( 4.95,                     2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected:  (ln(10))
-        [InlineData( 7.5441371028169758,       2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected:  (e)
-        [InlineData( 11.548739357257748,       3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi)
-        [InlineData( double.PositiveInfinity,  double.PositiveInfinity, 0.0)]
-        public static void Asinh(double value, double expectedResult, double allowedVariance)
-        {
-            AssertEqual(expectedResult, Math.Asinh(value), allowedVariance);
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  double.NaN,              0.0)]
-        [InlineData(-3.1415926535897932,       double.NaN,              0.0)]                               //                              value: -(pi)
-        [InlineData(-2.7182818284590452,       double.NaN,              0.0)]                               //                              value: -(e)
-        [InlineData(-1.4142135623730950,       double.NaN,              0.0)]                               //                              value: -(sqrt(2))
-        [InlineData(-1.0,                      double.NegativeInfinity, CrossPlatformMachineEpsilon * 10)]
-        [InlineData(-0.99627207622074994,     -3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi)
-        [InlineData(-0.99132891580059984,     -2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected: -(e)
-        [InlineData(-0.98019801980198020,     -2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected: -(ln(10))
-        [InlineData(-0.91715233566727435,     -1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi / 2)
-        [InlineData(-0.89423894585503855,     -1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected: -(log2(e))
-        [InlineData(-0.88838556158566054,     -1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected: -(sqrt(2))
-        [InlineData(-0.81046380599898809,     -1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected: -(2 / sqrt(pi))
-        [InlineData(-0.76159415595576489,     -1.0,                     CrossPlatformMachineEpsilon * 10)]
-        [InlineData(-0.65579420263267244,     -0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected: -(pi / 4)
-        [InlineData(-0.60885936501391381,     -0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected: -(1 / sqrt(2))
-        [InlineData(-0.6,                     -0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected: -(ln(2))
-        [InlineData(-0.56259360033158334,     -0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected: -(2 / pi)
-        [InlineData(-0.40890401183401433,     -0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected: -(log10(e))
-        [InlineData(-0.30797791269089433,     -0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected: -(1 / pi)
-        [InlineData(-0.0,                     -0.0,                     0.0)]
-        [InlineData( double.NaN,               double.NaN,              0.0)]
-        [InlineData( 0.0,                      0.0,                     0.0)]
-        [InlineData( 0.30797791269089433,      0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected:  (1 / pi)
-        [InlineData( 0.40890401183401433,      0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected:  (log10(e))
-        [InlineData( 0.56259360033158334,      0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected:  (2 / pi)
-        [InlineData( 0.6,                      0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected:  (ln(2))
-        [InlineData( 0.60885936501391381,      0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected:  (1 / sqrt(2))
-        [InlineData( 0.65579420263267244,      0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected:  (pi / 4)
-        [InlineData( 0.76159415595576489,      1.0,                     CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 0.81046380599898809,      1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected:  (2 / sqrt(pi))
-        [InlineData( 0.88838556158566054,      1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected:  (sqrt(2))
-        [InlineData( 0.89423894585503855,      1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected:  (log2(e))
-        [InlineData( 0.91715233566727435,      1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi / 2)
-        [InlineData( 0.98019801980198020,      2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected:  (ln(10))
-        [InlineData( 0.99132891580059984,      2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected:  (e)
-        [InlineData( 0.99627207622074994,      3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi)
-        [InlineData( 1.0,                      double.PositiveInfinity, 0.0)]
-        [InlineData( 1.4142135623730950,       double.NaN,              0.0)]                               //                              value:  (sqrt(2))
-        [InlineData( 2.7182818284590452,       double.NaN,              0.0)]                               //                              value:  (e)
-        [InlineData( 3.1415926535897932,       double.NaN,              0.0)]                               //                              value:  (pi)
-        [InlineData( double.PositiveInfinity,  double.NaN,              0.0)]
-        public static void Atanh(double value, double expectedResult, double allowedVariance)
-        {
-            AssertEqual(expectedResult, Math.Atanh(value), allowedVariance);
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  double.NegativeInfinity)]
-        [InlineData(-3.1415926535897932,      -3.1415926535897936)]     // value: -(pi)
-        [InlineData(-2.7182818284590452,      -2.7182818284590455)]     // value: -(e)
-        [InlineData(-2.3025850929940457,      -2.3025850929940463)]     // value: -(ln(10))
-        [InlineData(-1.5707963267948966,      -1.5707963267948968)]     // value: -(pi / 2)
-        [InlineData(-1.4426950408889634,      -1.4426950408889636)]     // value: -(log2(e))
-        [InlineData(-1.4142135623730950,      -1.4142135623730951)]     // value: -(sqrt(2))
-        [InlineData(-1.1283791670955126,      -1.1283791670955128)]     // value: -(2 / sqrt(pi))
-        [InlineData(-1.0,                     -1.0000000000000002)]
-        [InlineData(-0.78539816339744831,     -0.78539816339744839)]    // value: -(pi / 4)
-        [InlineData(-0.70710678118654752,     -0.70710678118654768)]    // value: -(1 / sqrt(2))
-        [InlineData(-0.69314718055994531,     -0.69314718055994540)]    // value: -(ln(2))
-        [InlineData(-0.63661977236758134,     -0.63661977236758149)]    // value: -(2 / pi)
-        [InlineData(-0.43429448190325183,     -0.43429448190325187)]    // value: -(log10(e))
-        [InlineData(-0.31830988618379067,     -0.31830988618379075)]    // value: -(1 / pi)
-        [InlineData(-0.0,                     -double.Epsilon)]
-        [InlineData( double.NaN,               double.NaN)]
-        [InlineData( 0.0,                     -double.Epsilon)]
-        [InlineData( 0.31830988618379067,      0.31830988618379064)]    // value:  (1 / pi)
-        [InlineData( 0.43429448190325183,      0.43429448190325176)]    // value:  (log10(e))
-        [InlineData( 0.63661977236758134,      0.63661977236758127)]    // value:  (2 / pi)
-        [InlineData( 0.69314718055994531,      0.69314718055994518)]    // value:  (ln(2))
-        [InlineData( 0.70710678118654752,      0.70710678118654746)]    // value:  (1 / sqrt(2))
-        [InlineData( 0.78539816339744831,      0.78539816339744817)]    // value:  (pi / 4)
-        [InlineData( 1.0,                      0.99999999999999989)]
-        [InlineData( 1.1283791670955126,       1.1283791670955123)]     // value:  (2 / sqrt(pi))
-        [InlineData( 1.4142135623730950,       1.4142135623730947)]     // value:  (sqrt(2))
-        [InlineData( 1.4426950408889634,       1.4426950408889632)]     // value:  (log2(e))
-        [InlineData( 1.5707963267948966,       1.5707963267948963)]     // value:  (pi / 2)
-        [InlineData( 2.3025850929940457,       2.3025850929940455)]     // value:  (ln(10))
-        [InlineData( 2.7182818284590452,       2.7182818284590446)]     // value:  (e)
-        [InlineData( 3.1415926535897932,       3.1415926535897927)]     // value:  (pi)
-        [InlineData( double.PositiveInfinity,  double.MaxValue)]
-        public static void BitDecrement(double value, double expectedResult)
-        {
-            AssertEqual(expectedResult, Math.BitDecrement(value), 0.0);
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  double.MinValue)]
-        [InlineData(-3.1415926535897932,      -3.1415926535897927)]     // value: -(pi)
-        [InlineData(-2.7182818284590452,      -2.7182818284590446)]     // value: -(e)
-        [InlineData(-2.3025850929940457,      -2.3025850929940455)]     // value: -(ln(10))
-        [InlineData(-1.5707963267948966,      -1.5707963267948963)]     // value: -(pi / 2)
-        [InlineData(-1.4426950408889634,      -1.4426950408889632)]     // value: -(log2(e))
-        [InlineData(-1.4142135623730950,      -1.4142135623730947)]     // value: -(sqrt(2))
-        [InlineData(-1.1283791670955126,      -1.1283791670955123)]     // value: -(2 / sqrt(pi))
-        [InlineData(-1.0,                     -0.99999999999999989)]
-        [InlineData(-0.78539816339744831,     -0.78539816339744817)]    // value: -(pi / 4)
-        [InlineData(-0.70710678118654752,     -0.70710678118654746)]    // value: -(1 / sqrt(2))
-        [InlineData(-0.69314718055994531,     -0.69314718055994518)]    // value: -(ln(2))
-        [InlineData(-0.63661977236758134,     -0.63661977236758127)]    // value: -(2 / pi)
-        [InlineData(-0.43429448190325183,     -0.43429448190325176)]    // value: -(log10(e))
-        [InlineData(-0.31830988618379067,     -0.31830988618379064)]    // value: -(1 / pi)
-        [InlineData(-0.0,                      double.Epsilon)]
-        [InlineData( double.NaN,               double.NaN)]
-        [InlineData( 0.0,                      double.Epsilon)]
-        [InlineData( 0.31830988618379067,      0.31830988618379075)]    // value:  (1 / pi)
-        [InlineData( 0.43429448190325183,      0.43429448190325187)]    // value:  (log10(e))
-        [InlineData( 0.63661977236758134,      0.63661977236758149)]    // value:  (2 / pi)
-        [InlineData( 0.69314718055994531,      0.69314718055994540)]    // value:  (ln(2))
-        [InlineData( 0.70710678118654752,      0.70710678118654768)]    // value:  (1 / sqrt(2))
-        [InlineData( 0.78539816339744831,      0.78539816339744839)]    // value:  (pi / 4)
-        [InlineData( 1.0,                      1.0000000000000002 )]
-        [InlineData( 1.1283791670955126,       1.1283791670955128 )]     // value:  (2 / sqrt(pi))
-        [InlineData( 1.4142135623730950,       1.4142135623730951 )]     // value:  (sqrt(2))
-        [InlineData( 1.4426950408889634,       1.4426950408889636 )]     // value:  (log2(e))
-        [InlineData( 1.5707963267948966,       1.5707963267948968 )]     // value:  (pi / 2)
-        [InlineData( 2.3025850929940457,       2.3025850929940463 )]     // value:  (ln(10))
-        [InlineData( 2.7182818284590452,       2.7182818284590455 )]     // value:  (e)
-        [InlineData( 3.1415926535897932,       3.1415926535897936 )]     // value:  (pi)
-        [InlineData( double.PositiveInfinity,  double.PositiveInfinity)]
-        public static void BitIncrement(double value, double expectedResult)
-        {
-            AssertEqual(expectedResult, Math.BitIncrement(value), 0.0);
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  double.NegativeInfinity, 0.0)]
-        [InlineData(-3.1415926535897932,      -1.4645918875615233,      CrossPlatformMachineEpsilon * 10)]   // value: -(pi)
-        [InlineData(-2.7182818284590452,      -1.3956124250860895,      CrossPlatformMachineEpsilon * 10)]   // value: -(e)
-        [InlineData(-2.3025850929940457,      -1.3205004784536852,      CrossPlatformMachineEpsilon * 10)]   // value: -(ln(10))
-        [InlineData(-1.5707963267948966,      -1.1624473515096265,      CrossPlatformMachineEpsilon * 10)]   // value: -(pi / 2)
-        [InlineData(-1.4426950408889634,      -1.1299472763373901,      CrossPlatformMachineEpsilon * 10)]   // value: -(log2(e))
-        [InlineData(-1.4142135623730950,      -1.1224620483093730,      CrossPlatformMachineEpsilon * 10)]   // value: -(sqrt(2))
-        [InlineData(-1.1283791670955126,      -1.0410821966965807,      CrossPlatformMachineEpsilon * 10)]   // value: -(2 / sqrt(pi))
-        [InlineData(-1.0,                     -1.0,                     CrossPlatformMachineEpsilon * 10)]
-        [InlineData(-0.78539816339744831,     -0.92263507432201421,     CrossPlatformMachineEpsilon)]        // value: -(pi / 4)
-        [InlineData(-0.70710678118654752,     -0.89089871814033930,     CrossPlatformMachineEpsilon)]        // value: -(1 / sqrt(2))
-        [InlineData(-0.69314718055994531,     -0.88499704450051772,     CrossPlatformMachineEpsilon)]        // value: -(ln(2))
-        [InlineData(-0.63661977236758134,     -0.86025401382809963,     CrossPlatformMachineEpsilon)]        // value: -(2 / pi)
-        [InlineData(-0.43429448190325183,     -0.75728863133090766,     CrossPlatformMachineEpsilon)]        // value: -(log10(e))
-        [InlineData(-0.31830988618379067,     -0.68278406325529568,     CrossPlatformMachineEpsilon)]        // value: -(1 / pi)
-        [InlineData(-0.0,                     -0.0,                     0.0)]
-        [InlineData( double.NaN,               double.NaN,              0.0)]
-        [InlineData( 0.0,                      0.0,                     0.0)]
-        [InlineData( 0.31830988618379067,      0.68278406325529568,     CrossPlatformMachineEpsilon)]        // value:  (1 / pi)
-        [InlineData( 0.43429448190325183,      0.75728863133090766,     CrossPlatformMachineEpsilon)]        // value:  (log10(e))
-        [InlineData( 0.63661977236758134,      0.86025401382809963,     CrossPlatformMachineEpsilon)]        // value:  (2 / pi)
-        [InlineData( 0.69314718055994531,      0.88499704450051772,     CrossPlatformMachineEpsilon)]        // value:  (ln(2))
-        [InlineData( 0.70710678118654752,      0.89089871814033930,     CrossPlatformMachineEpsilon)]        // value:  (1 / sqrt(2))
-        [InlineData( 0.78539816339744831,      0.92263507432201421,     CrossPlatformMachineEpsilon)]        // value:  (pi / 4)
-        [InlineData( 1.0,                      1.0,                     CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 1.1283791670955126,       1.0410821966965807,      CrossPlatformMachineEpsilon * 10)]   // value:  (2 / sqrt(pi))
-        [InlineData( 1.4142135623730950,       1.1224620483093730,      CrossPlatformMachineEpsilon * 10)]   // value:  (sqrt(2))
-        [InlineData( 1.4426950408889634,       1.1299472763373901,      CrossPlatformMachineEpsilon * 10)]   // value:  (log2(e))
-        [InlineData( 1.5707963267948966,       1.1624473515096265,      CrossPlatformMachineEpsilon * 10)]   // value:  (pi / 2)
-        [InlineData( 2.3025850929940457,       1.3205004784536852,      CrossPlatformMachineEpsilon * 10)]   // value:  (ln(10))
-        [InlineData( 2.7182818284590452,       1.3956124250860895,      CrossPlatformMachineEpsilon * 10)]   // value:  (e)
-        [InlineData( 3.1415926535897932,       1.4645918875615233,      CrossPlatformMachineEpsilon * 10)]   // value:  (pi)
-        [InlineData( double.PositiveInfinity,  double.PositiveInfinity, 0.0)]
-        public static void Cbrt(double value, double expectedResult, double allowedVariance)
-        {
-            AssertEqual(expectedResult, Math.Cbrt(value), allowedVariance);
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_SignedInt_TestData))]
-        public static void Clamp_SByte(sbyte value, sbyte min, sbyte max, sbyte expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_UnsignedInt_TestData))]
-        public static void Clamp_Byte(byte value, byte min, byte max, byte expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_SignedInt_TestData))]
-        public static void Clamp_Short(short value, short min, short max, short expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_UnsignedInt_TestData))]
-        public static void Clamp_UShort(ushort value, ushort min, ushort max, ushort expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_SignedInt_TestData))]
-        public static void Clamp_Int(int value, int min, int max, int expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_UnsignedInt_TestData))]
-        public static void Clamp_UInt(uint value, uint min, uint max, uint expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_SignedInt_TestData))]
-        public static void Clamp_Long(long value, long min, long max, long expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_UnsignedInt_TestData))]
-        public static void Clamp_ULong(ulong value, ulong min, ulong max, ulong expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_SignedInt_TestData))]
-        [InlineData(double.NegativeInfinity, double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)]
-        [InlineData(1, double.NegativeInfinity, double.PositiveInfinity, 1)]
-        [InlineData(double.PositiveInfinity, double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)]
-        [InlineData(1, double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity)]
-        [InlineData(1, double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity)]
-        [InlineData(double.NaN, double.NaN, double.NaN, double.NaN)]
-        [InlineData(double.NaN, double.NaN, 1, double.NaN)]
-        [InlineData(double.NaN, 1, double.NaN, double.NaN)]
-        [InlineData(double.NaN, 1, 1, double.NaN)]
-        [InlineData(1, double.NaN, double.NaN, 1)]
-        [InlineData(1, double.NaN, 1, 1)]
-        [InlineData(1, 1, double.NaN, 1)]
-        public static void Clamp_Double(double value, double min, double max, double expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_SignedInt_TestData))]
-        [InlineData(float.NegativeInfinity, float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)]
-        [InlineData(1, float.NegativeInfinity, float.PositiveInfinity, 1)]
-        [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)]
-        [InlineData(1, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity)]
-        [InlineData(1, float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity)]
-        [InlineData(float.NaN, float.NaN, float.NaN, float.NaN)]
-        [InlineData(float.NaN, float.NaN, 1, float.NaN)]
-        [InlineData(float.NaN, 1, float.NaN, float.NaN)]
-        [InlineData(float.NaN, 1, 1, float.NaN)]
-        [InlineData(1, float.NaN, float.NaN, 1)]
-        [InlineData(1, float.NaN, 1, 1)]
-        [InlineData(1, 1, float.NaN, 1)]
-        public static void Clamp_Float(float value, float min, float max, float expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Theory]
-        [MemberData(nameof(Clamp_SignedInt_TestData))]
-        public static void Clamp_Decimal(decimal value, decimal min, decimal max, decimal expected)
-        {
-            Assert.Equal(expected, Math.Clamp(value, min, max));
-        }
-
-        [Fact]
-        public static void Clamp_MinGreaterThanMax_ThrowsArgumentException()
-        {
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((sbyte)1, (sbyte)2, (sbyte)1));
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((byte)1, (byte)2, (byte)1));
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((short)1, (short)2, (short)1));
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((ushort)1, (ushort)2, (ushort)1));
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((int)1, (int)2, (int)1));
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((uint)1, (uint)2, (uint)1));
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((long)1, (long)2, (long)1));
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((ulong)1, (ulong)2, (ulong)1));
-
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((float)1, (float)2, (float)1));
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((double)1, (double)2, (double)1));
-            AssertExtensions.Throws<ArgumentException>(null, () => Math.Clamp((decimal)1, (decimal)2, (decimal)1));
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  double.NegativeInfinity,  double.NegativeInfinity)]
-        [InlineData( double.NegativeInfinity, -3.1415926535897932,       double.NegativeInfinity)]
-        [InlineData( double.NegativeInfinity, -0.0,                      double.NegativeInfinity)]
-        [InlineData( double.NegativeInfinity,  double.NaN,               double.NegativeInfinity)]
-        [InlineData( double.NegativeInfinity,  0.0,                      double.PositiveInfinity)]
-        [InlineData( double.NegativeInfinity,  3.1415926535897932,       double.PositiveInfinity)]
-        [InlineData( double.NegativeInfinity,  double.PositiveInfinity,  double.PositiveInfinity)]
-        [InlineData(-3.1415926535897932,       double.NegativeInfinity, -3.1415926535897932)]
-        [InlineData(-3.1415926535897932,      -3.1415926535897932,      -3.1415926535897932)]
-        [InlineData(-3.1415926535897932,      -0.0,                     -3.1415926535897932)]
-        [InlineData(-3.1415926535897932,       double.NaN,              -3.1415926535897932)]
-        [InlineData(-3.1415926535897932,       0.0,                      3.1415926535897932)]
-        [InlineData(-3.1415926535897932,       3.1415926535897932,       3.1415926535897932)]
-        [InlineData(-3.1415926535897932,       double.PositiveInfinity,  3.1415926535897932)]
-        [InlineData(-0.0,                      double.NegativeInfinity, -0.0)]
-        [InlineData(-0.0,                     -3.1415926535897932,      -0.0)]
-        [InlineData(-0.0,                     -0.0,                     -0.0)]
-        [InlineData(-0.0,                      double.NaN,              -0.0)]
-        [InlineData(-0.0,                      0.0,                      0.0)]
-        [InlineData(-0.0,                      3.1415926535897932,       0.0)]
-        [InlineData(-0.0,                      double.PositiveInfinity,  0.0)]
-        [InlineData( double.NaN,               double.NegativeInfinity,  double.NaN)]
-        [InlineData( double.NaN,              -3.1415926535897932,       double.NaN)]
-        [InlineData( double.NaN,              -0.0,                      double.NaN)]
-        [InlineData( double.NaN,               double.NaN,               double.NaN)]
-        [InlineData( double.NaN,               0.0,                      double.NaN)]
-        [InlineData( double.NaN,               3.1415926535897932,       double.NaN)]
-        [InlineData( double.NaN,               double.PositiveInfinity,  double.NaN)]
-        [InlineData( 0.0,                      double.NegativeInfinity, -0.0)]
-        [InlineData( 0.0,                     -3.1415926535897932,      -0.0)]
-        [InlineData( 0.0,                     -0.0,                     -0.0)]
-        [InlineData( 0.0,                      double.NaN,              -0.0)]
-        [InlineData( 0.0,                      0.0,                      0.0)]
-        [InlineData( 0.0,                      3.1415926535897932,       0.0)]
-        [InlineData( 0.0,                      double.PositiveInfinity,  0.0)]
-        [InlineData( 3.1415926535897932,       double.NegativeInfinity, -3.1415926535897932)]
-        [InlineData( 3.1415926535897932,      -3.1415926535897932,      -3.1415926535897932)]
-        [InlineData( 3.1415926535897932,      -0.0,                     -3.1415926535897932)]
-        [InlineData( 3.1415926535897932,       double.NaN,              -3.1415926535897932)]
-        [InlineData( 3.1415926535897932,       0.0,                      3.1415926535897932)]
-        [InlineData( 3.1415926535897932,       3.1415926535897932,       3.1415926535897932)]
-        [InlineData( 3.1415926535897932,       double.PositiveInfinity,  3.1415926535897932)]
-        [InlineData( double.PositiveInfinity,  double.NegativeInfinity,  double.NegativeInfinity)]
-        [InlineData( double.PositiveInfinity, -3.1415926535897932,       double.NegativeInfinity)]
-        [InlineData( double.PositiveInfinity, -0.0,                      double.NegativeInfinity)]
-        [InlineData( double.PositiveInfinity,  double.NaN,               double.NegativeInfinity)]
-        [InlineData( double.PositiveInfinity,  0.0,                      double.PositiveInfinity)]
-        [InlineData( double.PositiveInfinity,  3.1415926535897932,       double.PositiveInfinity)]
-        [InlineData( double.PositiveInfinity,  double.PositiveInfinity,  double.PositiveInfinity)]
-        public static void CopySign(double x, double y, double expectedResult)
-        {
-            AssertEqual(expectedResult, Math.CopySign(x, y), 0.0);
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  double.NegativeInfinity,  double.NegativeInfinity,  double.NaN)]
-        [InlineData( double.NegativeInfinity, -0.0,                      double.NegativeInfinity,  double.NaN)]
-        [InlineData( double.NegativeInfinity, -0.0,                     -3.1415926535897932,       double.NaN)]
-        [InlineData( double.NegativeInfinity, -0.0,                     -0.0,                      double.NaN)]
-        [InlineData( double.NegativeInfinity, -0.0,                      double.NaN,               double.NaN)]
-        [InlineData( double.NegativeInfinity, -0.0,                      0.0,                      double.NaN)]
-        [InlineData( double.NegativeInfinity, -0.0,                      3.1415926535897932,       double.NaN)]
-        [InlineData( double.NegativeInfinity, -0.0,                      double.PositiveInfinity,  double.NaN)]
-        [InlineData( double.NegativeInfinity,  0.0,                      double.NegativeInfinity,  double.NaN)]
-        [InlineData( double.NegativeInfinity,  0.0,                     -3.1415926535897932,       double.NaN)]
-        [InlineData( double.NegativeInfinity,  0.0,                     -0.0,                      double.NaN)]
-        [InlineData( double.NegativeInfinity,  0.0,                      double.NaN,               double.NaN)]
-        [InlineData( double.NegativeInfinity,  0.0,                      0.0,                      double.NaN)]
-        [InlineData( double.NegativeInfinity,  0.0,                      3.1415926535897932,       double.NaN)]
-        [InlineData( double.NegativeInfinity,  0.0,                      double.PositiveInfinity,  double.NaN)]
-        [InlineData( double.NegativeInfinity,  double.PositiveInfinity,  double.PositiveInfinity,  double.NaN)]
-        [InlineData(-1e308,                    2.0,                      1e308,                   -1e308)]
-        [InlineData(-1e308,                    2.0,                      double.PositiveInfinity,  double.PositiveInfinity)]
-        [InlineData(-5,                        4,                       -3,                       -23)]
-        [InlineData(-0.0,                      double.NegativeInfinity,  double.NegativeInfinity,  double.NaN)]
-        [InlineData(-0.0,                      double.NegativeInfinity, -3.1415926535897932,       double.NaN)]
-        [InlineData(-0.0,                      double.NegativeInfinity, -0.0,                      double.NaN)]
-        [InlineData(-0.0,                      double.NegativeInfinity,  double.NaN,               double.NaN)]
-        [InlineData(-0.0,                      double.NegativeInfinity,  0.0,                      double.NaN)]
-        [InlineData(-0.0,                      double.NegativeInfinity,  3.1415926535897932,       double.NaN)]
-        [InlineData(-0.0,                      double.NegativeInfinity,  double.PositiveInfinity,  double.NaN)]
-        [InlineData(-0.0,                      double.PositiveInfinity,  double.NegativeInfinity,  double.NaN)]
-        [InlineData(-0.0,                      double.PositiveInfinity, -3.1415926535897932,       double.NaN)]
-        [InlineData(-0.0,                      double.PositiveInfinity, -0.0,                      double.NaN)]
-        [InlineData(-0.0,                      double.PositiveInfinity,  double.NaN,               double.NaN)]
-        [InlineData(-0.0,                      double.PositiveInfinity,  0.0,                      double.NaN)]
-        [InlineData(-0.0,                      double.PositiveInfinity,  3.1415926535897932,       double.NaN)]
-        [InlineData(-0.0,                      double.PositiveInfinity,  double.PositiveInfinity,  double.NaN)]
-        [InlineData( 0.0,                      double.NegativeInfinity,  double.NegativeInfinity,  double.NaN)]
-        [InlineData( 0.0,                      double.NegativeInfinity, -3.1415926535897932,       double.NaN)]
-        [InlineData( 0.0,                      double.NegativeInfinity, -0.0,                      double.NaN)]
-        [InlineData( 0.0,                      double.NegativeInfinity,  double.NaN,               double.NaN)]
-        [InlineData( 0.0,                      double.NegativeInfinity,  0.0,                      double.NaN)]
-        [InlineData( 0.0,                      double.NegativeInfinity,  3.1415926535897932,       double.NaN)]
-        [InlineData( 0.0,                      double.NegativeInfinity,  double.PositiveInfinity,  double.NaN)]
-        [InlineData( 0.0,                      double.PositiveInfinity,  double.NegativeInfinity,  double.NaN)]
-        [InlineData( 0.0,                      double.PositiveInfinity, -3.1415926535897932,       double.NaN)]
-        [InlineData( 0.0,                      double.PositiveInfinity, -0.0,                      double.NaN)]
-        [InlineData( 0.0,                      double.PositiveInfinity,  double.NaN,               double.NaN)]
-        [InlineData( 0.0,                      double.PositiveInfinity,  0.0,                      double.NaN)]
-        [InlineData( 0.0,                      double.PositiveInfinity,  3.1415926535897932,       double.NaN)]
-        [InlineData( 0.0,                      double.PositiveInfinity,  double.PositiveInfinity,  double.NaN)]
-        [InlineData( 5,                        4,                        3,                        23)]
-        [InlineData( 1e308,                    2.0,                     -1e308,                    1e308)]
-        [InlineData( 1e308,                    2.0,                      double.NegativeInfinity,  double.NegativeInfinity)]
-        [InlineData( double.PositiveInfinity,  double.NegativeInfinity,  double.PositiveInfinity,  double.NaN)]
-        [InlineData( double.PositiveInfinity, -0.0,                      double.NegativeInfinity,  double.NaN)]
-        [InlineData( double.PositiveInfinity, -0.0,                     -3.1415926535897932,       double.NaN)]
-        [InlineData( double.PositiveInfinity, -0.0,                     -0.0,                      double.NaN)]
-        [InlineData( double.PositiveInfinity, -0.0,                      double.NaN,               double.NaN)]
-        [InlineData( double.PositiveInfinity, -0.0,                      0.0,                      double.NaN)]
-        [InlineData( double.PositiveInfinity, -0.0,                      3.1415926535897932,       double.NaN)]
-        [InlineData( double.PositiveInfinity, -0.0,                      double.PositiveInfinity,  double.NaN)]
-        [InlineData( double.PositiveInfinity,  0.0,                      double.NegativeInfinity,  double.NaN)]
-        [InlineData( double.PositiveInfinity,  0.0,                     -3.1415926535897932,       double.NaN)]
-        [InlineData( double.PositiveInfinity,  0.0,                     -0.0,                      double.NaN)]
-        [InlineData( double.PositiveInfinity,  0.0,                      double.NaN,               double.NaN)]
-        [InlineData( double.PositiveInfinity,  0.0,                      0.0,                      double.NaN)]
-        [InlineData( double.PositiveInfinity,  0.0,                      3.1415926535897932,       double.NaN)]
-        [InlineData( double.PositiveInfinity,  0.0,                      double.PositiveInfinity,  double.NaN)]
-        [InlineData( double.PositiveInfinity,  double.PositiveInfinity,  double.NegativeInfinity,  double.NaN)]
-        public static void FusedMultiplyAdd(double x, double y, double z, double expectedResult)
-        {
-            AssertEqual(expectedResult, Math.FusedMultiplyAdd(x, y, z), 0.0);
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  unchecked((int)(0x7FFFFFFF)))]
-        [InlineData(-0.0,                      unchecked((int)(0x80000000)))]
-        [InlineData( double.NaN,               unchecked((int)(0x7FFFFFFF)))]
-        [InlineData( 0.0,                      unchecked((int)(0x80000000)))]
-        [InlineData( 0.11331473229676087,     -4)]
-        [InlineData( 0.15195522325791297,     -3)]
-        [InlineData( 0.20269956628651730,     -3)]
-        [InlineData( 0.33662253682241906,     -2)]
-        [InlineData( 0.36787944117144232,     -2)]
-        [InlineData( 0.37521422724648177,     -2)]
-        [InlineData( 0.45742934732229695,     -2)]
-        [InlineData( 0.5,                     -1)]
-        [InlineData( 0.58019181037172444,     -1)]
-        [InlineData( 0.61254732653606592,     -1)]
-        [InlineData( 0.61850313780157598,     -1)]
-        [InlineData( 0.64321824193300488,     -1)]
-        [InlineData( 0.74005557395545179,     -1)]
-        [InlineData( 0.80200887896145195,     -1)]
-        [InlineData( 1,                        0)]
-        [InlineData( 1.2468689889006383,       0)]
-        [InlineData( 1.3512498725672678,       0)]
-        [InlineData( 1.5546822754821001,       0)]
-        [InlineData( 1.6168066722416747,       0)]
-        [InlineData( 1.6325269194381528,       0)]
-        [InlineData( 1.7235679341273495,       0)]
-        [InlineData( 2,                        1)]
-        [InlineData( 2.1861299583286618,       1)]
-        [InlineData( 2.6651441426902252,       1)]
-        [InlineData( 2.7182818284590452,       1)]
-        [InlineData( 2.9706864235520193,       1)]
-        [InlineData( 4.9334096679145963,       2)]
-        [InlineData( 6.5808859910179210,       2)]
-        [InlineData( 8.8249778270762876,       3)]
-        [InlineData( double.PositiveInfinity,  unchecked((int)(0x7FFFFFFF)))]
-        public static void ILogB(double value, int expectedResult)
-        {
-            Assert.Equal(expectedResult, Math.ILogB(value));
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  double.NaN,              0.0)]
-        [InlineData(-0.11331473229676087,      double.NaN,              0.0)]
-        [InlineData(-0.0,                      double.NegativeInfinity, 0.0)]
-        [InlineData( double.NaN,               double.NaN,              0.0)]
-        [InlineData( 0.0,                      double.NegativeInfinity, 0.0)]
-        [InlineData( 0.11331473229676087,     -3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi)
-        [InlineData( 0.15195522325791297,     -2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected: -(e)
-        [InlineData( 0.20269956628651730,     -2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected: -(ln(10))
-        [InlineData( 0.33662253682241906,     -1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected: -(pi / 2)
-        [InlineData( 0.36787944117144232,     -1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected: -(log2(e))
-        [InlineData( 0.37521422724648177,     -1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected: -(sqrt(2))
-        [InlineData( 0.45742934732229695,     -1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected: -(2 / sqrt(pi))
-        [InlineData( 0.5,                     -1.0,                     CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 0.58019181037172444,     -0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected: -(pi / 4)
-        [InlineData( 0.61254732653606592,     -0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected: -(1 / sqrt(2))
-        [InlineData( 0.61850313780157598,     -0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected: -(ln(2))
-        [InlineData( 0.64321824193300488,     -0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected: -(2 / pi)
-        [InlineData( 0.74005557395545179,     -0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected: -(log10(e))
-        [InlineData( 0.80200887896145195,     -0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected: -(1 / pi)
-        [InlineData( 1,                        0.0,                     0.0)]
-        [InlineData( 1.2468689889006383,       0.31830988618379067,     CrossPlatformMachineEpsilon)]       // expected:  (1 / pi)
-        [InlineData( 1.3512498725672678,       0.43429448190325183,     CrossPlatformMachineEpsilon)]       // expected:  (log10(e))
-        [InlineData( 1.5546822754821001,       0.63661977236758134,     CrossPlatformMachineEpsilon)]       // expected:  (2 / pi)
-        [InlineData( 1.6168066722416747,       0.69314718055994531,     CrossPlatformMachineEpsilon)]       // expected:  (ln(2))
-        [InlineData( 1.6325269194381528,       0.70710678118654752,     CrossPlatformMachineEpsilon)]       // expected:  (1 / sqrt(2))
-        [InlineData( 1.7235679341273495,       0.78539816339744831,     CrossPlatformMachineEpsilon)]       // expected:  (pi / 4)
-        [InlineData( 2,                        1.0,                     CrossPlatformMachineEpsilon * 10)]  //                              value: (e)
-        [InlineData( 2.1861299583286618,       1.1283791670955126,      CrossPlatformMachineEpsilon * 10)]  // expected:  (2 / sqrt(pi))
-        [InlineData( 2.6651441426902252,       1.4142135623730950,      CrossPlatformMachineEpsilon * 10)]  // expected:  (sqrt(2))
-        [InlineData( 2.7182818284590452,       1.4426950408889634,      CrossPlatformMachineEpsilon * 10)]  // expected:  (log2(e))
-        [InlineData( 2.9706864235520193,       1.5707963267948966,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi / 2)
-        [InlineData( 4.9334096679145963,       2.3025850929940457,      CrossPlatformMachineEpsilon * 10)]  // expected:  (ln(10))
-        [InlineData( 6.5808859910179210,       2.7182818284590452,      CrossPlatformMachineEpsilon * 10)]  // expected:  (e)
-        [InlineData( 8.8249778270762876,       3.1415926535897932,      CrossPlatformMachineEpsilon * 10)]  // expected:  (pi)
-        [InlineData( double.PositiveInfinity,  double.PositiveInfinity, 0.0)]
-        public static void Log2(double value, double expectedResult, double allowedVariance)
-        {
-            AssertEqual(expectedResult, Math.Log2(value), allowedVariance);
-        }
-
-        [Theory]
-        [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.PositiveInfinity)]
-        [InlineData(double.MinValue, double.MaxValue, double.MaxValue)]
-        [InlineData(double.NaN, double.NaN, double.NaN)]
-        [InlineData(-0.0, 0.0, 0.0)]
-        [InlineData(2.0, -3.0, -3.0)]
-        [InlineData(3.0, -2.0, 3.0)]
-        [InlineData(double.PositiveInfinity, double.NaN, double.NaN)]
-        public static void MaxMagnitude(double x, double y, double expectedResult)
-        {
-            AssertEqual(expectedResult, Math.MaxMagnitude(x, y), 0.0);
-        }
-
-        [Theory]
-        [InlineData(double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)]
-        [InlineData(double.MinValue, double.MaxValue, double.MinValue)]
-        [InlineData(double.NaN, double.NaN, double.NaN)]
-        [InlineData(-0.0, 0.0, -0.0)]
-        [InlineData(2.0, -3.0, 2.0)]
-        [InlineData(3.0, -2.0, -2.0)]
-        [InlineData(double.PositiveInfinity, double.NaN, double.NaN)]
-        public static void MinMagnitude(double x, double y, double expectedResult)
-        {
-            AssertEqual(expectedResult, Math.MinMagnitude(x, y), 0.0);
-        }
-
-        [Theory]
-        [InlineData( double.NegativeInfinity,  unchecked((int)(0x7FFFFFFF)),  double.NegativeInfinity,  0)]
-        [InlineData(-0.11331473229676087,     -3,                            -0.014164341537095108,     CrossPlatformMachineEpsilon / 10)]
-        [InlineData(-0.0,                      unchecked((int)(0x80000000)), -0.0,                      0)]
-        [InlineData( double.NaN,               unchecked((int)(0x7FFFFFFF)),  double.NaN,               0)]
-        [InlineData( 0.0,                      unchecked((int)(0x80000000)),  0,                        0)]
-        [InlineData( 0.11331473229676087,     -4,                             0.0070821707685475542,    CrossPlatformMachineEpsilon / 100)]
-        [InlineData( 0.15195522325791297,     -3,                             0.018994402907239121,     CrossPlatformMachineEpsilon / 10)]
-        [InlineData( 0.20269956628651730,     -3,                             0.025337445785814663,     CrossPlatformMachineEpsilon / 10)]
-        [InlineData( 0.33662253682241906,     -2,                             0.084155634205604762,     CrossPlatformMachineEpsilon / 10)]
-        [InlineData( 0.36787944117144232,     -2,                             0.091969860292860584,     CrossPlatformMachineEpsilon / 10)]
-        [InlineData( 0.37521422724648177,     -2,                             0.093803556811620448,     CrossPlatformMachineEpsilon / 10)]
-        [InlineData( 0.45742934732229695,     -2,                             0.11435733683057424,      CrossPlatformMachineEpsilon)]
-        [InlineData( 0.5,                     -1,                             0.25,                     CrossPlatformMachineEpsilon)]
-        [InlineData( 0.58019181037172444,     -1,                             0.2900959051858622,       CrossPlatformMachineEpsilon)]
-        [InlineData( 0.61254732653606592,     -1,                             0.30627366326803296,      CrossPlatformMachineEpsilon)]
-        [InlineData( 0.61850313780157598,     -1,                             0.30925156890078798,      CrossPlatformMachineEpsilon)]
-        [InlineData( 0.64321824193300488,     -1,                             0.32160912096650246,      CrossPlatformMachineEpsilon)]
-        [InlineData( 0.74005557395545179,     -1,                             0.37002778697772587,      CrossPlatformMachineEpsilon)]
-        [InlineData( 0.80200887896145195,     -1,                             0.40100443948072595,      CrossPlatformMachineEpsilon)]
-        [InlineData( 1,                        0,                             1,                        CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 1.2468689889006383,       0,                             1.2468689889006384,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 1.3512498725672678,       0,                             1.3512498725672677,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 1.5546822754821001,       0,                             1.5546822754821001,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 1.6168066722416747,       0,                             1.6168066722416747,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 1.6325269194381528,       0,                             1.6325269194381529,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 1.7235679341273495,       0,                             1.7235679341273495,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 2,                        1,                             4,                        CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 2.1861299583286618,       1,                             4.3722599166573239,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 2.6651441426902252,       1,                             5.3302882853804503,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 2.7182818284590452,       1,                             5.4365636569180902,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 2.9706864235520193,       1,                             5.9413728471040388,       CrossPlatformMachineEpsilon * 10)]
-        [InlineData( 4.9334096679145963,       2,                             19.733638671658387,       CrossPlatformMachineEpsilon * 100)]
-        [InlineData( 6.5808859910179210,       2,                             26.323543964071686,       CrossPlatformMachineEpsilon * 100)]
-        [InlineData( 8.8249778270762876,       3,                             70.599822616610297,       CrossPlatformMachineEpsilon * 100)]
-        [InlineData( double.PositiveInfinity,  unchecked((int)(0x7FFFFFFF)),  double.PositiveInfinity,  0)]
-        public static void ScaleB(double x, int n, double expectedResult, double allowedVariance)
-        {
-            AssertEqual(expectedResult, Math.ScaleB(x, n), allowedVariance);
-        }
-
-
-        public static IEnumerable<object[]> Round_Digits_TestData
-        {
-            get
-            {
-                yield return new object[] {0, 0, 3, MidpointRounding.ToEven};
-                yield return new object[] {3.42156, 3.422, 3, MidpointRounding.ToEven};
-                yield return new object[] {-3.42156, -3.422, 3, MidpointRounding.ToEven};
-
-                yield return new object[] {0, 0, 3, MidpointRounding.AwayFromZero};
-                yield return new object[] {3.42156, 3.422, 3, MidpointRounding.AwayFromZero};
-                yield return new object[] {-3.42156, -3.422, 3, MidpointRounding.AwayFromZero};
-
-                yield return new object[] {0, 0, 3, MidpointRounding.ToZero};
-                yield return new object[] {3.42156, 3.421, 3, MidpointRounding.ToZero};
-                yield return new object[] {-3.42156, -3.421, 3, MidpointRounding.ToZero};
-
-                yield return new object[] {0, 0, 3, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {3.42156, 3.421, 3, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {-3.42156, -3.422, 3, MidpointRounding.ToNegativeInfinity};
-
-                yield return new object[] {0, 0, 3, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {3.42156, 3.422, 3, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {-3.42156, -3.421, 3, MidpointRounding.ToPositiveInfinity};
-              }
-        }
-
-        [Theory]
-        [InlineData(MidpointRounding.ToEven)]
-        [InlineData(MidpointRounding.AwayFromZero)]
-        [InlineData(MidpointRounding.ToZero)]
-        [InlineData(MidpointRounding.ToNegativeInfinity)]
-        [InlineData(MidpointRounding.ToPositiveInfinity)]
-        public static void Round_Double_Digits(MidpointRounding mode)
-        {
-            Assert.Equal(double.NaN, Math.Round(double.NaN, 3, mode));
-            Assert.Equal(double.PositiveInfinity, Math.Round(double.PositiveInfinity, 3, mode));
-            Assert.Equal(double.NegativeInfinity, Math.Round(double.NegativeInfinity, 3, mode));
-        }
-
-        [Theory]
-        [MemberData(nameof(Round_Digits_TestData))]
-        public static void Round_Double_Digits(double x, double expected, int digits, MidpointRounding mode)
-        {
-            Assert.Equal(expected, Math.Round(x, digits, mode));
-        }
-
-        [Theory]
-        [MemberData(nameof(Round_Digits_TestData))]
-        public static void Round_Decimal_Digits(decimal x, decimal expected, int digits, MidpointRounding mode)
-        {
-            Assert.Equal(expected, Math.Round(x, digits, mode));
-        }
-
-        [Theory]
-        [InlineData(MidpointRounding.ToEven)]
-        [InlineData(MidpointRounding.AwayFromZero)]
-        [InlineData(MidpointRounding.ToZero)]
-        [InlineData(MidpointRounding.ToNegativeInfinity)]
-        [InlineData(MidpointRounding.ToPositiveInfinity)]
-        public static void Round_Decimal_Digits(MidpointRounding mode)
-        {
-            Assert.Equal(decimal.Zero, Math.Round(decimal.Zero, 3, mode));
-        }
-
-        public static IEnumerable<object[]> Round_Modes_TestData
-        {
-            get
-            {
-                yield return new object[] {11, 11, MidpointRounding.ToEven};
-                yield return new object[] {11.4, 11, MidpointRounding.ToEven};
-                yield return new object[] {11.5, 12, MidpointRounding.ToEven};
-                yield return new object[] {11.6, 12, MidpointRounding.ToEven};
-                yield return new object[] {-11, -11, MidpointRounding.ToEven};
-                yield return new object[] {-11.4, -11, MidpointRounding.ToEven};
-                yield return new object[] {-11.5, -12, MidpointRounding.ToEven};
-                yield return new object[] {-11.6, -12, MidpointRounding.ToEven};
-                yield return new object[] {11, 11, MidpointRounding.AwayFromZero};
-                yield return new object[] {11.4, 11, MidpointRounding.AwayFromZero};
-                yield return new object[] {11.5, 12, MidpointRounding.AwayFromZero};
-                yield return new object[] {11.6, 12, MidpointRounding.AwayFromZero};
-                yield return new object[] {-11, -11, MidpointRounding.AwayFromZero};
-                yield return new object[] {-11.4, -11, MidpointRounding.AwayFromZero};
-                yield return new object[] {-11.5, -12, MidpointRounding.AwayFromZero};
-                yield return new object[] {-11.6, -12, MidpointRounding.AwayFromZero};
-                yield return new object[] {11, 11, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {11.4, 12, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {11.5, 12, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {11.6, 12, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {-11, -11, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {-11.4, -11, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {-11.5, -11, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {-11.6, -11, MidpointRounding.ToPositiveInfinity};
-                yield return new object[] {11.0, 11, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {11.4, 11, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {11.5, 11, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {11.6, 11, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {-11.0, -11, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {-11.4, -12, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {-11.5, -12, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {-11.6, -12, MidpointRounding.ToNegativeInfinity};
-                yield return new object[] {11.0, 11, MidpointRounding.ToZero};
-                yield return new object[] {11.4, 11, MidpointRounding.ToZero};
-                yield return new object[] {11.5, 11, MidpointRounding.ToZero};
-                yield return new object[] {11.6, 11, MidpointRounding.ToZero};
-                yield return new object[] {-11.0, -11, MidpointRounding.ToZero};
-                yield return new object[] {-11.4, -11, MidpointRounding.ToZero};
-                yield return new object[] {-11.5, -11, MidpointRounding.ToZero};
-                yield return new object[] {-11.6, -11, MidpointRounding.ToZero};
-            }
-        }
-
-        [Theory]
-        [MemberData(nameof(Round_Modes_TestData))]
-        public static void Round_Double_Modes(double x, double expected, MidpointRounding mode)
-        {
-            Assert.Equal(expected, Math.Round(x, 0, mode));
-        }
-
-        [Theory]
-        [MemberData(nameof(Round_Modes_TestData))]
-        public static void Round_Float_Modes(float x, float expected, MidpointRounding mode)
-        {
-            Assert.Equal(expected, MathF.Round(x, 0, mode));
-        }
-
-        [Theory]
-        [MemberData(nameof(Round_Modes_TestData))]
-        public static void Round_Decimal_Modes(decimal x, decimal expected, MidpointRounding mode)
-        {
-            Assert.Equal(expected, Math.Round(x, 0, mode));
-            Assert.Equal(expected, decimal.Round(x, 0, mode));
-        }
-    }
-}
index 9c15c6b..6c150a0 100644 (file)
@@ -6,7 +6,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public static partial class RandomTests
+    public static class RandomTests
     {
         [Fact]
         public static void Unseeded()
@@ -158,5 +158,50 @@ namespace System.Tests
                 return Sample();
             }
         }
+
+        [Fact]
+        public static void Empty_Span()
+        {
+            int seed = Environment.TickCount;
+            Random r = new Random(seed);
+            r.NextBytes(Span<byte>.Empty);
+        }
+
+        [Fact]
+        public static void Seeded_Span()
+        {
+            int seed = Environment.TickCount;
+
+            Random r1 = new Random(seed);
+            Random r2 = new Random(seed);
+
+            Span<byte> s1 = new Span<byte>(new byte[1000]);
+            r1.NextBytes(s1);
+            Span<byte> s2 = new Span<byte>(new byte[1000]);
+            r2.NextBytes(s2);
+            for (int i = 0; i < s1.Length; i++)
+            {
+                Assert.Equal(s1[i], s2[i]);
+            }
+            for (int i = 0; i < s1.Length; i++)
+            {
+                int x1 = r1.Next();
+                int x2 = r2.Next();
+                Assert.Equal(x1, x2);
+            }
+        }
+
+        [Fact]
+        public static void ExpectedValues_NextBytesSpan()
+        {
+            byte[][] expectedValues = ByteValues();
+            for (int seed = 0; seed < expectedValues.Length; seed++)
+            {
+                byte[] actualValues = new byte[expectedValues[seed].Length];
+                var r = new Random(seed);
+                r.NextBytes(new Span<byte>(actualValues));
+                Assert.Equal(expectedValues[seed], actualValues);
+            }
+        }
     }
 }
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Random.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/Random.netcoreapp.cs
deleted file mode 100644 (file)
index 5d00083..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 Xunit;
-
-namespace System.Tests
-{
-    public static partial class RandomTests
-    {
-        [Fact]
-        public static void Empty_Span()
-        {
-            int seed = Environment.TickCount;
-            Random r = new Random(seed);
-            r.NextBytes(Span<byte>.Empty);
-        }
-
-        [Fact]
-        public static void Seeded_Span()
-        {
-            int seed = Environment.TickCount;
-
-            Random r1 = new Random(seed);
-            Random r2 = new Random(seed);
-
-            Span<byte> s1 = new Span<byte>(new byte[1000]);
-            r1.NextBytes(s1);
-            Span<byte> s2 = new Span<byte>(new byte[1000]);
-            r2.NextBytes(s2);
-            for (int i = 0; i < s1.Length; i++)
-            {
-                Assert.Equal(s1[i], s2[i]);
-            }
-            for (int i = 0; i < s1.Length; i++)
-            {
-                int x1 = r1.Next();
-                int x2 = r2.Next();
-                Assert.Equal(x1, x2);
-            }
-        }
-
-        [Fact]
-        public static void ExpectedValues_NextBytesSpan()
-        {
-            byte[][] expectedValues = ByteValues();
-            for (int seed = 0; seed < expectedValues.Length; seed++)
-            {
-                byte[] actualValues = new byte[expectedValues[seed].Length];
-                var r = new Random(seed);
-                r.NextBytes(new Span<byte>(actualValues));
-                Assert.Equal(expectedValues[seed], actualValues);
-            }
-        }
-    }
-}
@@ -2,12 +2,10 @@
 // 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.IO;
 using System.Threading;
 using Microsoft.DotNet.RemoteExecutor;
 using Xunit;
-using Xunit.Abstractions;
 
 namespace System.Runtime.Tests
 {
index 8a6dce8..6083a72 100644 (file)
@@ -10,7 +10,7 @@ using Xunit;
 
 namespace System.Tests
 {
-    public static partial class StringComparerTests
+    public static class StringComparerTests
     {
         [Fact]
         public static void TestCurrent()
@@ -131,5 +131,100 @@ namespace System.Tests
             Assert.Equal(StringComparer.InvariantCultureIgnoreCase.GetHashCode("test"), StringComparer.InvariantCultureIgnoreCase.GetHashCode("TEST"));
             Assert.Equal(0, StringComparer.InvariantCultureIgnoreCase.Compare("test", "TEST"));
         }
+
+        public static readonly object[][] FromComparison_TestData =
+        {
+            //             StringComparison                 StringComparer
+            new object[] { StringComparison.CurrentCulture, StringComparer.CurrentCulture },
+            new object[] { StringComparison.CurrentCultureIgnoreCase, StringComparer.CurrentCultureIgnoreCase },
+            new object[] { StringComparison.InvariantCulture, StringComparer.InvariantCulture },
+            new object[] { StringComparison.InvariantCultureIgnoreCase, StringComparer.InvariantCultureIgnoreCase },
+            new object[] { StringComparison.Ordinal, StringComparer.Ordinal },
+            new object[] { StringComparison.OrdinalIgnoreCase, StringComparer.OrdinalIgnoreCase },
+        };
+
+        [Theory]
+        [MemberData(nameof(FromComparison_TestData))]
+        public static void FromComparisonTest(StringComparison comparison, StringComparer comparer)
+        {
+            Assert.Equal(comparer, StringComparer.FromComparison(comparison));
+        }
+
+        [Fact]
+        public static void FromComparisonInvalidTest()
+        {
+            StringComparison minInvalid = Enum.GetValues(typeof(StringComparison)).Cast<StringComparison>().Min() - 1;
+            StringComparison maxInvalid = Enum.GetValues(typeof(StringComparison)).Cast<StringComparison>().Max() + 1;
+
+            AssertExtensions.Throws<ArgumentException>("comparisonType", () => StringComparer.FromComparison(minInvalid));
+            AssertExtensions.Throws<ArgumentException>("comparisonType", () => StringComparer.FromComparison(maxInvalid));
+        }
+
+        public static TheoryData<string, string, string, CompareOptions, bool> CreateFromCultureAndOptionsData => new TheoryData<string, string, string, CompareOptions, bool>
+        {
+            { "abcd", "ABCD", "en-US", CompareOptions.None, false},
+            { "latin i", "LATIN I", "en-US", CompareOptions.None, false},
+            { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.None, false},
+            { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.None, false},
+            { "abcd", "ABCD", "en-US", CompareOptions.IgnoreCase, true},
+            { "latin i", "LATIN I", "en-US", CompareOptions.IgnoreCase, true},
+            { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.IgnoreCase, true},
+            { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.IgnoreCase, true},
+            { "abcd", "ab cd", "en-US", CompareOptions.IgnoreSymbols, true },
+            { "abcd", "ab+cd", "en-US", CompareOptions.IgnoreSymbols, true },
+            { "abcd", "ab%cd", "en-US", CompareOptions.IgnoreSymbols, true },
+            { "abcd", "ab&cd", "en-US", CompareOptions.IgnoreSymbols, true },
+            { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
+            { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
+            { "a-bcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
+            { "abcd*", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
+            { "ab$dd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, false },
+            { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
+        };
+
+        public static TheoryData<string, string, string, CompareOptions, bool> CreateFromCultureAndOptionsStringSortData => new TheoryData<string, string, string, CompareOptions, bool>
+        {
+            { "abcd", "abcd", "en-US", CompareOptions.StringSort, true },
+            { "abcd", "ABcd", "en-US", CompareOptions.StringSort, false },
+        };
+
+        [Theory]
+        [MemberData(nameof(CreateFromCultureAndOptionsData))]
+        [MemberData(nameof(CreateFromCultureAndOptionsStringSortData))]
+        public static void CreateFromCultureAndOptions(string actualString, string expectedString, string cultureName, CompareOptions options, bool result)
+        {
+            CultureInfo ci = CultureInfo.GetCultureInfo(cultureName);
+            StringComparer sc = StringComparer.Create(ci, options);
+
+            Assert.Equal(result, sc.Equals(actualString, expectedString));
+            Assert.Equal(result, sc.Equals((object)actualString, (object)expectedString));
+        }
+
+        [Theory]
+        [MemberData(nameof(CreateFromCultureAndOptionsData))]
+        public static void CreateFromCultureAndOptionsStringSort(string actualString, string expectedString, string cultureName, CompareOptions options, bool result)
+        {
+            CultureInfo ci = CultureInfo.GetCultureInfo(cultureName);
+            StringComparer sc = StringComparer.Create(ci, options);
+
+            if (result)
+            {
+                Assert.Equal(sc.GetHashCode(actualString), sc.GetHashCode(expectedString));
+                Assert.Equal(sc.GetHashCode((object)actualString), sc.GetHashCode((object)actualString));
+            }
+            else
+            {
+                Assert.NotEqual(sc.GetHashCode(actualString), sc.GetHashCode(expectedString));
+                Assert.NotEqual(sc.GetHashCode((object)actualString), sc.GetHashCode((object)expectedString));
+            }
+        }
+
+        [Fact]
+        public static void CreateFromCultureAndOptionsOrdinal()
+        {
+            CultureInfo ci = CultureInfo.GetCultureInfo("en-US");
+            Assert.Throws<ArgumentException>(() => StringComparer.Create(ci, CompareOptions.Ordinal));
+            Assert.Throws<ArgumentException>(() => StringComparer.Create(ci, CompareOptions.OrdinalIgnoreCase));
+        }
     }
 }
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.netcoreapp.cs b/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.netcoreapp.cs
deleted file mode 100644 (file)
index 698b38f..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.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using Xunit;
-
-namespace System.Tests
-{
-    public static partial class StringComparerTests
-    {
-        public static readonly object[][] FromComparison_TestData =
-        {
-            //             StringComparison                 StringComparer
-            new object[] { StringComparison.CurrentCulture, StringComparer.CurrentCulture },
-            new object[] { StringComparison.CurrentCultureIgnoreCase, StringComparer.CurrentCultureIgnoreCase },
-            new object[] { StringComparison.InvariantCulture, StringComparer.InvariantCulture },
-            new object[] { StringComparison.InvariantCultureIgnoreCase, StringComparer.InvariantCultureIgnoreCase },
-            new object[] { StringComparison.Ordinal, StringComparer.Ordinal },
-            new object[] { StringComparison.OrdinalIgnoreCase, StringComparer.OrdinalIgnoreCase },
-        };
-
-        [Theory]
-        [MemberData(nameof(FromComparison_TestData))]
-        public static void FromComparisonTest(StringComparison comparison, StringComparer comparer)
-        {
-            Assert.Equal(comparer, StringComparer.FromComparison(comparison));
-        }
-
-        [Fact]
-        public static void FromComparisonInvalidTest()
-        {
-            StringComparison minInvalid = Enum.GetValues(typeof(StringComparison)).Cast<StringComparison>().Min() - 1;
-            StringComparison maxInvalid = Enum.GetValues(typeof(StringComparison)).Cast<StringComparison>().Max() + 1;
-
-            AssertExtensions.Throws<ArgumentException>("comparisonType", () => StringComparer.FromComparison(minInvalid));
-            AssertExtensions.Throws<ArgumentException>("comparisonType", () => StringComparer.FromComparison(maxInvalid));
-        }
-
-        public static TheoryData<string, string, string, CompareOptions, bool> CreateFromCultureAndOptionsData => new TheoryData<string, string, string, CompareOptions, bool>
-        {
-            { "abcd", "ABCD", "en-US", CompareOptions.None, false},
-            { "latin i", "LATIN I", "en-US", CompareOptions.None, false},
-            { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.None, false},
-            { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.None, false},
-            { "abcd", "ABCD", "en-US", CompareOptions.IgnoreCase, true},
-            { "latin i", "LATIN I", "en-US", CompareOptions.IgnoreCase, true},
-            { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.IgnoreCase, true},
-            { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.IgnoreCase, true},
-            { "abcd", "ab cd", "en-US", CompareOptions.IgnoreSymbols, true },
-            { "abcd", "ab+cd", "en-US", CompareOptions.IgnoreSymbols, true },
-            { "abcd", "ab%cd", "en-US", CompareOptions.IgnoreSymbols, true },
-            { "abcd", "ab&cd", "en-US", CompareOptions.IgnoreSymbols, true },
-            { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
-            { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
-            { "a-bcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
-            { "abcd*", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
-            { "ab$dd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, false },
-            { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true },
-        };
-
-        public static TheoryData<string, string, string, CompareOptions, bool> CreateFromCultureAndOptionsStringSortData => new TheoryData<string, string, string, CompareOptions, bool>
-        {
-            { "abcd", "abcd", "en-US", CompareOptions.StringSort, true },
-            { "abcd", "ABcd", "en-US", CompareOptions.StringSort, false },
-        };
-
-        [Theory]
-        [MemberData(nameof(CreateFromCultureAndOptionsData))]
-        [MemberData(nameof(CreateFromCultureAndOptionsStringSortData))]
-        public static void CreateFromCultureAndOptions(string actualString, string expectedString, string cultureName, CompareOptions options, bool result)
-        {
-            CultureInfo ci = CultureInfo.GetCultureInfo(cultureName);
-            StringComparer sc = StringComparer.Create(ci, options);
-
-            Assert.Equal(result, sc.Equals(actualString, expectedString));
-            Assert.Equal(result, sc.Equals((object)actualString, (object)expectedString));
-        }
-
-        [Theory]
-        [MemberData(nameof(CreateFromCultureAndOptionsData))]
-        public static void CreateFromCultureAndOptionsStringSort(string actualString, string expectedString, string cultureName, CompareOptions options, bool result)
-        {
-            CultureInfo ci = CultureInfo.GetCultureInfo(cultureName);
-            StringComparer sc = StringComparer.Create(ci, options);
-
-            if (result)
-            {
-                Assert.Equal(sc.GetHashCode(actualString), sc.GetHashCode(expectedString));
-                Assert.Equal(sc.GetHashCode((object)actualString), sc.GetHashCode((object)actualString));
-            }
-            else
-            {
-                Assert.NotEqual(sc.GetHashCode(actualString), sc.GetHashCode(expectedString));
-                Assert.NotEqual(sc.GetHashCode((object)actualString), sc.GetHashCode((object)expectedString));
-            }
-        }
-
-        [Fact]
-        public static void CreateFromCultureAndOptionsOrdinal()
-        {
-            CultureInfo ci = CultureInfo.GetCultureInfo("en-US");
-            Assert.Throws<ArgumentException>(() => StringComparer.Create(ci, CompareOptions.Ordinal));
-            Assert.Throws<ArgumentException>(() => StringComparer.Create(ci, CompareOptions.OrdinalIgnoreCase));
-        }
-    }
-}