<commit_before>// 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 Xunit;

namespace System.IO.Tests
{
    public class Directory_CreateDirectory : FileSystemTest
    {
        #region Utilities

        public virtual DirectoryInfo Create(string path)
        {
            return Directory.CreateDirectory(path);
        }

        #endregion

        #region UniversalTests

        [Fact]
        public void NullAsPath_ThrowsArgumentNullException()
        {
            Assert.Throws<ArgumentNullException>(() => Create(null));
        }

        [Fact]
        public void EmptyAsPath_ThrowsArgumentException()
        {
            Assert.Throws<ArgumentException>(() => Create(string.Empty));
        }

        [Theory, MemberData(nameof(PathsWithInvalidCharacters))]
        public void PathWithInvalidCharactersAsPath_ThrowsArgumentException(string invalidPath)
        {
            if (invalidPath.Equals(@"\\?\") && !PathFeatures.IsUsingLegacyPathNormalization())
                Assert.Throws<IOException>(() => Create(invalidPath));
            else if (invalidPath.Contains(@"\\?\") && !PathFeatures.IsUsingLegacyPathNormalization())
                Assert.Throws<DirectoryNotFoundException>(() => Create(invalidPath));
            else
                Assert.Throws<ArgumentException>(() => Create(invalidPath));
        }

        [Fact]
        public void PathAlreadyExistsAsFile()
        {
            string path = GetTestFilePath();
            File.Create(path).Dispose();

            Assert.Throws<IOException>(() => Create(path));
            Assert.Throws<IOException>(() => Create(IOServices.AddTrailingSlashIfNeeded(path)));
            Assert.Throws<IOException>(() => Create(IOServices.RemoveTrailingSlash(path)));
        }

        [Theory]
        [InlineData(FileAttributes.Hidden)]
        [InlineData(FileAttributes.ReadOnly)]
        [InlineData(FileAttributes.Normal)]
        public void PathAlreadyExistsAsDirectory(FileAttributes attributes)
        {
            DirectoryInfo testDir = Create(GetTestFilePath());
            FileAttributes original = testDir.Attributes;

            try
            {
                testDir.Attributes = attributes;
                Assert.Equal(testDir.FullName, Create(testDir.FullName).FullName);
            }
            finally
            {
                testDir.Attributes = original;
            }
        }

        [Fact]
        public void RootPath()
        {
            string dirName = Path.GetPathRoot(Directory.GetCurrentDirectory());
            DirectoryInfo dir = Create(dirName);
            Assert.Equal(dir.FullName, dirName);
        }

        [Fact]
        public void DotIsCurrentDirectory()
        {
            string path = GetTestFilePath();
            DirectoryInfo result = Create(Path.Combine(path, "."));
            Assert.Equal(IOServices.RemoveTrailingSlash(path), result.FullName);

            result = Create(Path.Combine(path, ".") + Path.DirectorySeparatorChar);
            Assert.Equal(IOServices.AddTrailingSlashIfNeeded(path), result.FullName);
        }

        [Fact]
        public void CreateCurrentDirectory()
        {
            DirectoryInfo result = Create(Directory.GetCurrentDirectory());
            Assert.Equal(Directory.GetCurrentDirectory(), result.FullName);
        }

        [Fact]
        public void DotDotIsParentDirectory()
        {
            DirectoryInfo result = Create(Path.Combine(GetTestFilePath(), ".."));
            Assert.Equal(IOServices.RemoveTrailingSlash(TestDirectory), result.FullName);

            result = Create(Path.Combine(GetTestFilePath(), "..") + Path.DirectorySeparatorChar);
            Assert.Equal(IOServices.AddTrailingSlashIfNeeded(TestDirectory), result.FullName);
        }

        [Fact]
        public void ValidPathWithTrailingSlash()
        {
            DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());

            var components = IOInputs.GetValidPathComponentNames();
            Assert.All(components, (component) =>
            {
                string path = IOServices.AddTrailingSlashIfNeeded(Path.Combine(testDir.FullName, component));
                DirectoryInfo result = Create(path);

                Assert.Equal(path, result.FullName);
                Assert.True(result.Exists);
            });
        }

        [ConditionalFact(nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // trailing slash
        public void ValidExtendedPathWithTrailingSlash()
        {
            DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());

            var components = IOInputs.GetValidPathComponentNames();
            Assert.All(components, (component) =>
            {
                string path = IOInputs.ExtendedPrefix + IOServices.AddTrailingSlashIfNeeded(Path.Combine(testDir.FullName, component));
                DirectoryInfo result = Create(path);

                Assert.Equal(path, result.FullName);
                Assert.True(result.Exists);
            });
        }

        [Fact]
        public void ValidPathWithoutTrailingSlash()
        {
            DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());

            var components = IOInputs.GetValidPathComponentNames();
            Assert.All(components, (component) =>
            {
                string path = testDir.FullName + Path.DirectorySeparatorChar + component;
                DirectoryInfo result = Create(path);

                Assert.Equal(path, result.FullName);
                Assert.True(Directory.Exists(result.FullName));
            });
        }

        [Fact]
        public void ValidPathWithMultipleSubdirectories()
        {
            string dirName = Path.Combine(GetTestFilePath(), "Test", "Test", "Test");
            DirectoryInfo dir = Create(dirName);

            Assert.Equal(dir.FullName, dirName);
        }

        [Fact]
        public void AllowedSymbols()
        {
            string dirName = Path.Combine(TestDirectory, Path.GetRandomFileName() + "!@#$%^&");
            DirectoryInfo dir = Create(dirName);

            Assert.Equal(dir.FullName, dirName);
        }

        [Fact]
        public void DirectoryEqualToMaxDirectory_CanBeCreated()
        {
            DirectoryInfo testDir = Create(GetTestFilePath());
            PathInfo path = IOServices.GetPath(testDir.FullName, IOInputs.MaxDirectory, IOInputs.MaxComponent);
            Assert.All(path.SubPaths, (subpath) =>
            {
                DirectoryInfo result = Create(subpath);

                Assert.Equal(subpath, result.FullName);
                Assert.True(Directory.Exists(result.FullName));
            });
        }

        [Fact]
        public void DirectoryEqualToMaxDirectory_CanBeCreatedAllAtOnce()
        {
            DirectoryInfo testDir = Create(GetTestFilePath());
            PathInfo path = IOServices.GetPath(testDir.FullName, IOInputs.MaxDirectory, maxComponent: 10);
            DirectoryInfo result = Create(path.FullPath);

            Assert.Equal(path.FullPath, result.FullName);
            Assert.True(Directory.Exists(result.FullName));
        }

        [Fact]
        public void DirectoryWithComponentLongerThanMaxComponentAsPath_ThrowsPathTooLongException()
        {
            // While paths themselves can be up to 260 characters including trailing null, file systems
            // limit each components of the path to a total of 255 characters.
            var paths = IOInputs.GetPathsWithComponentLongerThanMaxComponent();

            Assert.All(paths, (path) =>
            {
                Assert.Throws<PathTooLongException>(() => Create(path));
            });
        }

        #endregion

        #region PlatformSpecific

        [Theory, MemberData(nameof(PathsWithInvalidColons))]
        [PlatformSpecific(TestPlatforms.Windows)]  // invalid colons throws ArgumentException
        [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Versions of netfx older than 4.6.2 throw an ArgumentException instead of NotSupportedException. Until all of our machines run netfx against the actual latest version, these will fail.")]
        public void PathWithInvalidColons_ThrowsNotSupportedException(string invalidPath)
        {
            Assert.Throws<NotSupportedException>(() => Create(invalidPath));
        }

        [ConditionalFact(nameof(AreAllLongPathsAvailable))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path succeeds
        public void DirectoryLongerThanMaxPath_Succeeds()
        {
            var paths = IOInputs.GetPathsLongerThanMaxPath(GetTestFilePath());
            Assert.All(paths, (path) =>
            {
                DirectoryInfo result = Create(path);
                Assert.True(Directory.Exists(result.FullName));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path throws PathTooLongException
        public void DirectoryLongerThanMaxLongPath_ThrowsPathTooLongException()
        {
            var paths = IOInputs.GetPathsLongerThanMaxLongPath(GetTestFilePath());
            Assert.All(paths, (path) =>
            {
                Assert.Throws<PathTooLongException>(() => Create(path));
            });
        }

        [ConditionalFact(nameof(LongPathsAreNotBlocked), nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path with extended syntax throws PathTooLongException
        public void DirectoryLongerThanMaxLongPathWithExtendedSyntax_ThrowsPathTooLongException()
        {
            var paths = IOInputs.GetPathsLongerThanMaxLongPath(GetTestFilePath(), useExtendedSyntax: true);
            Assert.All(paths, (path) =>
            {
                Assert.Throws<PathTooLongException>(() => Create(path));
            });
        }

        [ConditionalFact(nameof(LongPathsAreNotBlocked), nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path with extended syntax succeeds
        public void ExtendedDirectoryLongerThanLegacyMaxPath_Succeeds()
        {
            var paths = IOInputs.GetPathsLongerThanMaxPath(GetTestFilePath(), useExtendedSyntax: true);
            Assert.All(paths, (path) =>
            {
                Assert.True(Create(path).Exists);
            });
        }

        [ConditionalFact(nameof(AreAllLongPathsAvailable))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path succeeds
        public void DirectoryLongerThanMaxDirectoryAsPath_Succeeds()
        {
            var paths = IOInputs.GetPathsLongerThanMaxDirectory(GetTestFilePath());
            Assert.All(paths, (path) =>
            {
                var result = Create(path);
                Assert.True(Directory.Exists(result.FullName));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)] // long directory path allowed
        public void UnixPathLongerThan256_Allowed()
        {
            DirectoryInfo testDir = Create(GetTestFilePath());
            PathInfo path = IOServices.GetPath(testDir.FullName, 257, IOInputs.MaxComponent);
            DirectoryInfo result = Create(path.FullPath);
            Assert.Equal(path.FullPath, result.FullName);
            Assert.True(Directory.Exists(result.FullName));
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)]  // deeply nested directories allowed
        public void UnixPathWithDeeplyNestedDirectories()
        {
            DirectoryInfo parent = Create(GetTestFilePath());
            for (int i = 1; i <= 100; i++) // 100 == arbitrarily large number of directories
            {
                parent = Create(Path.Combine(parent.FullName, "dir" + i));
                Assert.True(Directory.Exists(parent.FullName));
            }
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)]  // whitespace as path throws ArgumentException on Windows
        public void WindowsWhiteSpaceAsPath_ThrowsArgumentException()
        {
            var paths = IOInputs.GetWhiteSpace();
            Assert.All(paths, (path) =>
            {
                Assert.Throws<ArgumentException>(() => Create(path));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)]  // whitespace as path allowed
        public void UnixWhiteSpaceAsPath_Allowed()
        {
            var paths = IOInputs.GetWhiteSpace();
            Assert.All(paths, (path) =>
            {
                Create(Path.Combine(TestDirectory, path));
                Assert.True(Directory.Exists(Path.Combine(TestDirectory, path)));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)]  // trailing whitespace in path is removed on Windows
        public void WindowsTrailingWhiteSpace()
        {
            // Windows will remove all non-significant whitespace in a path
            DirectoryInfo testDir = Create(GetTestFilePath());
            var components = IOInputs.GetWhiteSpace();

            Assert.All(components, (component) =>
            {
                string path = IOServices.RemoveTrailingSlash(testDir.FullName) + component;
                DirectoryInfo result = Create(path);

                Assert.True(Directory.Exists(result.FullName));
                Assert.Equal(testDir.FullName, IOServices.RemoveTrailingSlash(result.FullName));
            });
        }

        [ConditionalFact(nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // extended syntax with whitespace
        public void WindowsExtendedSyntaxWhiteSpace()
        {
            var paths = IOInputs.GetSimpleWhiteSpace();
            using (TemporaryDirectory directory = new TemporaryDirectory())
            {
                foreach (var path in paths)
                {
                    string extendedPath = Path.Combine(IOInputs.ExtendedPrefix + directory.Path, path);
                    Directory.CreateDirectory(extendedPath);
                    Assert.True(Directory.Exists(extendedPath), extendedPath);
                }
            }
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)]  // trailing whitespace in path treated as significant on Unix
        public void UnixNonSignificantTrailingWhiteSpace()
        {
            // Unix treats trailing/prename whitespace as significant and a part of the name.
            DirectoryInfo testDir = Create(GetTestFilePath());
            var components = IOInputs.GetWhiteSpace();

            Assert.All(components, (component) =>
            {
                string path = IOServices.RemoveTrailingSlash(testDir.FullName) + component;
                DirectoryInfo result = Create(path);

                Assert.True(Directory.Exists(result.FullName));
                Assert.NotEqual(testDir.FullName, IOServices.RemoveTrailingSlash(result.FullName));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // alternate data streams
        public void PathWithAlternateDataStreams_ThrowsNotSupportedException()
        {
            var paths = IOInputs.GetPathsWithAlternativeDataStreams();
            Assert.All(paths, (path) =>
            {
                Assert.Throws<NotSupportedException>(() => Create(path));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // device name prefixes
        public void PathWithReservedDeviceNameAsPath_ThrowsDirectoryNotFoundException()
        {   // Throws DirectoryNotFoundException, when the behavior really should be an invalid path
            var paths = IOInputs.GetPathsWithReservedDeviceNames();
            Assert.All(paths, (path) =>
            {
                Assert.Throws<DirectoryNotFoundException>(() => Create(path));
            });
        }

        [ConditionalFact(nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)] // device name prefixes
        public void PathWithReservedDeviceNameAsExtendedPath()
        {
            var paths = IOInputs.GetReservedDeviceNames();
            using (TemporaryDirectory directory = new TemporaryDirectory())
            {
                Assert.All(paths, (path) =>
                {
                    Assert.True(Create(IOInputs.ExtendedPrefix + Path.Combine(directory.Path, path)).Exists, path);
                });
            }
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // UNC shares
        public void UncPathWithoutShareNameAsPath_ThrowsArgumentException()
        {
            var paths = IOInputs.GetUncPathsWithoutShareName();
            foreach (var path in paths)
            {
                Assert.Throws<ArgumentException>(() => Create(path));
            }
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // UNC shares
        public void UNCPathWithOnlySlashes()
        {
            Assert.Throws<ArgumentException>(() => Create("//"));
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // drive labels
        public void CDriveCase()
        {
            DirectoryInfo dir = Create("c:\\");
            DirectoryInfo dir2 = Create("C:\\");
            Assert.NotEqual(dir.FullName, dir2.FullName);
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)]  // drive letters
        public void DriveLetter_Windows()
        {
            // On Windows, DirectoryInfo will replace "<DriveLetter>:" with "."
            var driveLetter = Create(Directory.GetCurrentDirectory()[0] + ":");
            var current = Create(".");
            Assert.Equal(current.Name, driveLetter.Name);
            Assert.Equal(current.FullName, driveLetter.FullName);
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)]  // drive letters casing<commit_msg>Disable CDriveCase on uap (#19068)<commit_after>// 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 Xunit;

namespace System.IO.Tests
{
    public class Directory_CreateDirectory : FileSystemTest
    {
        #region Utilities

        public virtual DirectoryInfo Create(string path)
        {
            return Directory.CreateDirectory(path);
        }

        #endregion

        #region UniversalTests

        [Fact]
        public void NullAsPath_ThrowsArgumentNullException()
        {
            Assert.Throws<ArgumentNullException>(() => Create(null));
        }

        [Fact]
        public void EmptyAsPath_ThrowsArgumentException()
        {
            Assert.Throws<ArgumentException>(() => Create(string.Empty));
        }

        [Theory, MemberData(nameof(PathsWithInvalidCharacters))]
        public void PathWithInvalidCharactersAsPath_ThrowsArgumentException(string invalidPath)
        {
            if (invalidPath.Equals(@"\\?\") && !PathFeatures.IsUsingLegacyPathNormalization())
                Assert.Throws<IOException>(() => Create(invalidPath));
            else if (invalidPath.Contains(@"\\?\") && !PathFeatures.IsUsingLegacyPathNormalization())
                Assert.Throws<DirectoryNotFoundException>(() => Create(invalidPath));
            else
                Assert.Throws<ArgumentException>(() => Create(invalidPath));
        }

        [Fact]
        public void PathAlreadyExistsAsFile()
        {
            string path = GetTestFilePath();
            File.Create(path).Dispose();

            Assert.Throws<IOException>(() => Create(path));
            Assert.Throws<IOException>(() => Create(IOServices.AddTrailingSlashIfNeeded(path)));
            Assert.Throws<IOException>(() => Create(IOServices.RemoveTrailingSlash(path)));
        }

        [Theory]
        [InlineData(FileAttributes.Hidden)]
        [InlineData(FileAttributes.ReadOnly)]
        [InlineData(FileAttributes.Normal)]
        public void PathAlreadyExistsAsDirectory(FileAttributes attributes)
        {
            DirectoryInfo testDir = Create(GetTestFilePath());
            FileAttributes original = testDir.Attributes;

            try
            {
                testDir.Attributes = attributes;
                Assert.Equal(testDir.FullName, Create(testDir.FullName).FullName);
            }
            finally
            {
                testDir.Attributes = original;
            }
        }

        [Fact]
        public void RootPath()
        {
            string dirName = Path.GetPathRoot(Directory.GetCurrentDirectory());
            DirectoryInfo dir = Create(dirName);
            Assert.Equal(dir.FullName, dirName);
        }

        [Fact]
        public void DotIsCurrentDirectory()
        {
            string path = GetTestFilePath();
            DirectoryInfo result = Create(Path.Combine(path, "."));
            Assert.Equal(IOServices.RemoveTrailingSlash(path), result.FullName);

            result = Create(Path.Combine(path, ".") + Path.DirectorySeparatorChar);
            Assert.Equal(IOServices.AddTrailingSlashIfNeeded(path), result.FullName);
        }

        [Fact]
        public void CreateCurrentDirectory()
        {
            DirectoryInfo result = Create(Directory.GetCurrentDirectory());
            Assert.Equal(Directory.GetCurrentDirectory(), result.FullName);
        }

        [Fact]
        public void DotDotIsParentDirectory()
        {
            DirectoryInfo result = Create(Path.Combine(GetTestFilePath(), ".."));
            Assert.Equal(IOServices.RemoveTrailingSlash(TestDirectory), result.FullName);

            result = Create(Path.Combine(GetTestFilePath(), "..") + Path.DirectorySeparatorChar);
            Assert.Equal(IOServices.AddTrailingSlashIfNeeded(TestDirectory), result.FullName);
        }

        [Fact]
        public void ValidPathWithTrailingSlash()
        {
            DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());

            var components = IOInputs.GetValidPathComponentNames();
            Assert.All(components, (component) =>
            {
                string path = IOServices.AddTrailingSlashIfNeeded(Path.Combine(testDir.FullName, component));
                DirectoryInfo result = Create(path);

                Assert.Equal(path, result.FullName);
                Assert.True(result.Exists);
            });
        }

        [ConditionalFact(nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // trailing slash
        public void ValidExtendedPathWithTrailingSlash()
        {
            DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());

            var components = IOInputs.GetValidPathComponentNames();
            Assert.All(components, (component) =>
            {
                string path = IOInputs.ExtendedPrefix + IOServices.AddTrailingSlashIfNeeded(Path.Combine(testDir.FullName, component));
                DirectoryInfo result = Create(path);

                Assert.Equal(path, result.FullName);
                Assert.True(result.Exists);
            });
        }

        [Fact]
        public void ValidPathWithoutTrailingSlash()
        {
            DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());

            var components = IOInputs.GetValidPathComponentNames();
            Assert.All(components, (component) =>
            {
                string path = testDir.FullName + Path.DirectorySeparatorChar + component;
                DirectoryInfo result = Create(path);

                Assert.Equal(path, result.FullName);
                Assert.True(Directory.Exists(result.FullName));
            });
        }

        [Fact]
        public void ValidPathWithMultipleSubdirectories()
        {
            string dirName = Path.Combine(GetTestFilePath(), "Test", "Test", "Test");
            DirectoryInfo dir = Create(dirName);

            Assert.Equal(dir.FullName, dirName);
        }

        [Fact]
        public void AllowedSymbols()
        {
            string dirName = Path.Combine(TestDirectory, Path.GetRandomFileName() + "!@#$%^&");
            DirectoryInfo dir = Create(dirName);

            Assert.Equal(dir.FullName, dirName);
        }

        [Fact]
        public void DirectoryEqualToMaxDirectory_CanBeCreated()
        {
            DirectoryInfo testDir = Create(GetTestFilePath());
            PathInfo path = IOServices.GetPath(testDir.FullName, IOInputs.MaxDirectory, IOInputs.MaxComponent);
            Assert.All(path.SubPaths, (subpath) =>
            {
                DirectoryInfo result = Create(subpath);

                Assert.Equal(subpath, result.FullName);
                Assert.True(Directory.Exists(result.FullName));
            });
        }

        [Fact]
        public void DirectoryEqualToMaxDirectory_CanBeCreatedAllAtOnce()
        {
            DirectoryInfo testDir = Create(GetTestFilePath());
            PathInfo path = IOServices.GetPath(testDir.FullName, IOInputs.MaxDirectory, maxComponent: 10);
            DirectoryInfo result = Create(path.FullPath);

            Assert.Equal(path.FullPath, result.FullName);
            Assert.True(Directory.Exists(result.FullName));
        }

        [Fact]
        public void DirectoryWithComponentLongerThanMaxComponentAsPath_ThrowsPathTooLongException()
        {
            // While paths themselves can be up to 260 characters including trailing null, file systems
            // limit each components of the path to a total of 255 characters.
            var paths = IOInputs.GetPathsWithComponentLongerThanMaxComponent();

            Assert.All(paths, (path) =>
            {
                Assert.Throws<PathTooLongException>(() => Create(path));
            });
        }

        #endregion

        #region PlatformSpecific

        [Theory, MemberData(nameof(PathsWithInvalidColons))]
        [PlatformSpecific(TestPlatforms.Windows)]  // invalid colons throws ArgumentException
        [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Versions of netfx older than 4.6.2 throw an ArgumentException instead of NotSupportedException. Until all of our machines run netfx against the actual latest version, these will fail.")]
        public void PathWithInvalidColons_ThrowsNotSupportedException(string invalidPath)
        {
            Assert.Throws<NotSupportedException>(() => Create(invalidPath));
        }

        [ConditionalFact(nameof(AreAllLongPathsAvailable))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path succeeds
        public void DirectoryLongerThanMaxPath_Succeeds()
        {
            var paths = IOInputs.GetPathsLongerThanMaxPath(GetTestFilePath());
            Assert.All(paths, (path) =>
            {
                DirectoryInfo result = Create(path);
                Assert.True(Directory.Exists(result.FullName));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path throws PathTooLongException
        public void DirectoryLongerThanMaxLongPath_ThrowsPathTooLongException()
        {
            var paths = IOInputs.GetPathsLongerThanMaxLongPath(GetTestFilePath());
            Assert.All(paths, (path) =>
            {
                Assert.Throws<PathTooLongException>(() => Create(path));
            });
        }

        [ConditionalFact(nameof(LongPathsAreNotBlocked), nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path with extended syntax throws PathTooLongException
        public void DirectoryLongerThanMaxLongPathWithExtendedSyntax_ThrowsPathTooLongException()
        {
            var paths = IOInputs.GetPathsLongerThanMaxLongPath(GetTestFilePath(), useExtendedSyntax: true);
            Assert.All(paths, (path) =>
            {
                Assert.Throws<PathTooLongException>(() => Create(path));
            });
        }

        [ConditionalFact(nameof(LongPathsAreNotBlocked), nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path with extended syntax succeeds
        public void ExtendedDirectoryLongerThanLegacyMaxPath_Succeeds()
        {
            var paths = IOInputs.GetPathsLongerThanMaxPath(GetTestFilePath(), useExtendedSyntax: true);
            Assert.All(paths, (path) =>
            {
                Assert.True(Create(path).Exists);
            });
        }

        [ConditionalFact(nameof(AreAllLongPathsAvailable))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // long directory path succeeds
        public void DirectoryLongerThanMaxDirectoryAsPath_Succeeds()
        {
            var paths = IOInputs.GetPathsLongerThanMaxDirectory(GetTestFilePath());
            Assert.All(paths, (path) =>
            {
                var result = Create(path);
                Assert.True(Directory.Exists(result.FullName));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)] // long directory path allowed
        public void UnixPathLongerThan256_Allowed()
        {
            DirectoryInfo testDir = Create(GetTestFilePath());
            PathInfo path = IOServices.GetPath(testDir.FullName, 257, IOInputs.MaxComponent);
            DirectoryInfo result = Create(path.FullPath);
            Assert.Equal(path.FullPath, result.FullName);
            Assert.True(Directory.Exists(result.FullName));
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)]  // deeply nested directories allowed
        public void UnixPathWithDeeplyNestedDirectories()
        {
            DirectoryInfo parent = Create(GetTestFilePath());
            for (int i = 1; i <= 100; i++) // 100 == arbitrarily large number of directories
            {
                parent = Create(Path.Combine(parent.FullName, "dir" + i));
                Assert.True(Directory.Exists(parent.FullName));
            }
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)]  // whitespace as path throws ArgumentException on Windows
        public void WindowsWhiteSpaceAsPath_ThrowsArgumentException()
        {
            var paths = IOInputs.GetWhiteSpace();
            Assert.All(paths, (path) =>
            {
                Assert.Throws<ArgumentException>(() => Create(path));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)]  // whitespace as path allowed
        public void UnixWhiteSpaceAsPath_Allowed()
        {
            var paths = IOInputs.GetWhiteSpace();
            Assert.All(paths, (path) =>
            {
                Create(Path.Combine(TestDirectory, path));
                Assert.True(Directory.Exists(Path.Combine(TestDirectory, path)));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)]  // trailing whitespace in path is removed on Windows
        public void WindowsTrailingWhiteSpace()
        {
            // Windows will remove all non-significant whitespace in a path
            DirectoryInfo testDir = Create(GetTestFilePath());
            var components = IOInputs.GetWhiteSpace();

            Assert.All(components, (component) =>
            {
                string path = IOServices.RemoveTrailingSlash(testDir.FullName) + component;
                DirectoryInfo result = Create(path);

                Assert.True(Directory.Exists(result.FullName));
                Assert.Equal(testDir.FullName, IOServices.RemoveTrailingSlash(result.FullName));
            });
        }

        [ConditionalFact(nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)]  // extended syntax with whitespace
        public void WindowsExtendedSyntaxWhiteSpace()
        {
            var paths = IOInputs.GetSimpleWhiteSpace();
            using (TemporaryDirectory directory = new TemporaryDirectory())
            {
                foreach (var path in paths)
                {
                    string extendedPath = Path.Combine(IOInputs.ExtendedPrefix + directory.Path, path);
                    Directory.CreateDirectory(extendedPath);
                    Assert.True(Directory.Exists(extendedPath), extendedPath);
                }
            }
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)]  // trailing whitespace in path treated as significant on Unix
        public void UnixNonSignificantTrailingWhiteSpace()
        {
            // Unix treats trailing/prename whitespace as significant and a part of the name.
            DirectoryInfo testDir = Create(GetTestFilePath());
            var components = IOInputs.GetWhiteSpace();

            Assert.All(components, (component) =>
            {
                string path = IOServices.RemoveTrailingSlash(testDir.FullName) + component;
                DirectoryInfo result = Create(path);

                Assert.True(Directory.Exists(result.FullName));
                Assert.NotEqual(testDir.FullName, IOServices.RemoveTrailingSlash(result.FullName));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // alternate data streams
        public void PathWithAlternateDataStreams_ThrowsNotSupportedException()
        {
            var paths = IOInputs.GetPathsWithAlternativeDataStreams();
            Assert.All(paths, (path) =>
            {
                Assert.Throws<NotSupportedException>(() => Create(path));
            });
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // device name prefixes
        public void PathWithReservedDeviceNameAsPath_ThrowsDirectoryNotFoundException()
        {   // Throws DirectoryNotFoundException, when the behavior really should be an invalid path
            var paths = IOInputs.GetPathsWithReservedDeviceNames();
            Assert.All(paths, (path) =>
            {
                Assert.Throws<DirectoryNotFoundException>(() => Create(path));
            });
        }

        [ConditionalFact(nameof(UsingNewNormalization))]
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        [PlatformSpecific(TestPlatforms.Windows)] // device name prefixes
        public void PathWithReservedDeviceNameAsExtendedPath()
        {
            var paths = IOInputs.GetReservedDeviceNames();
            using (TemporaryDirectory directory = new TemporaryDirectory())
            {
                Assert.All(paths, (path) =>
                {
                    Assert.True(Create(IOInputs.ExtendedPrefix + Path.Combine(directory.Path, path)).Exists, path);
                });
            }
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // UNC shares
        public void UncPathWithoutShareNameAsPath_ThrowsArgumentException()
        {
            var paths = IOInputs.GetUncPathsWithoutShareName();
            foreach (var path in paths)
            {
                Assert.Throws<ArgumentException>(() => Create(path));
            }
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // UNC shares
        public void UNCPathWithOnlySlashes()
        {
            Assert.Throws<ArgumentException>(() => Create("//"));
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)] // drive labels
        [SkipOnTargetFramework(TargetFrameworkMonikers.Uap | TargetFrameworkMonikers.UapAot)]
        public void CDriveCase()
        {
            DirectoryInfo dir = Create("c:\\");
            DirectoryInfo dir2 = Create("C:\\");
            Assert.NotEqual(dir.FullName, dir2.FullName);
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.Windows)]  // drive letters
        public void DriveLetter_Windows()
        {
            // On Windows, DirectoryInfo will replace "<DriveLetter>:" with "."
            var driveLetter = Create(Directory.GetCurrentDirectory()[0] + ":");
            var current = Create(".");
            Assert.Equal(current.Name, driveLetter.Name);
            Assert.Equal(current.FullName, driveLetter.FullName);
        }

        [Fact]
        [PlatformSpecific(TestPlatforms.AnyUnix)]  // drive letters casing
{'fraction_non_alphanumeric': 0.09604624645328949, 'fraction_numerical': 0.0015645302431651243, 'mean_word_length': 2.2566493955094993, 'pattern_counts': {'":': 2, '<': 41, '<?xml version=': 0, '>': 107, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5934221', 'n_tokens_mistral': 9645, 'n_tokens_neox': 9201, 'n_words': 1691}