From 48e424365ffbc11e698e8cb2c234f6b6f31fff32 Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sun, 22 Sep 2024 19:48:28 +0200 Subject: [PATCH] update deps and add Path.HasTrailingDirectorySeparator --- Directory.Build.props | 2 +- ...ommonUtilities.DownloadManager.Test.csproj | 8 +-- .../src/Extensions/PathExtensions.cs | 49 ++++++++++--- .../CommonUtilities.FileSystem.Test.csproj | 6 +- ...hExtensionsTest.HasLeadingPathSeparator.cs | 67 +++++++++++++++++ ...ExtensionsTest.HasTrailingPathSeparator.cs | 72 +++++++++++-------- .../test/CommonUtilities.Registry.Test.csproj | 2 +- ...CommonUtilities.SimplePipeline.Test.csproj | 4 +- .../CommonUtilities.TestingUtilities.csproj | 2 +- .../test/CommonUtilities.Test.csproj | 8 +-- 10 files changed, 165 insertions(+), 55 deletions(-) create mode 100644 src/CommonUtilities.FileSystem/test/PathExtensionsTest.HasLeadingPathSeparator.cs diff --git a/Directory.Build.props b/Directory.Build.props index 2087a1c..0104357 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -25,7 +25,7 @@ all - 3.6.141 + 3.6.143 diff --git a/src/CommonUtilities.DownloadManager/test/CommonUtilities.DownloadManager.Test.csproj b/src/CommonUtilities.DownloadManager/test/CommonUtilities.DownloadManager.Test.csproj index e34447d..f275082 100644 --- a/src/CommonUtilities.DownloadManager/test/CommonUtilities.DownloadManager.Test.csproj +++ b/src/CommonUtilities.DownloadManager/test/CommonUtilities.DownloadManager.Test.csproj @@ -19,10 +19,10 @@ - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/CommonUtilities.FileSystem/src/Extensions/PathExtensions.cs b/src/CommonUtilities.FileSystem/src/Extensions/PathExtensions.cs index e9e4cb1..ed2fa95 100644 --- a/src/CommonUtilities.FileSystem/src/Extensions/PathExtensions.cs +++ b/src/CommonUtilities.FileSystem/src/Extensions/PathExtensions.cs @@ -36,25 +36,22 @@ public static partial class PathExtensions internal static readonly Lazy IsFileSystemCaseInsensitive = new(CheckIfFileSystemIsCaseInsensitive); /// - /// Determines whether the specified path ends with a directory path separator + /// Returns a value that indicates whether the path ends in a directory separator. /// /// - /// The path to check. - /// if ends with a directory path separator; otherwise, . - /// is . - public static bool HasTrailingDirectorySeparator(this IPath _, string path) + /// The path to analyze. + /// if the path ends in a directory separator; otherwise, . + public static bool HasTrailingDirectorySeparator(this IPath _, [NotNullWhen(true)] string? path) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - return HasTrailingDirectorySeparator(path.AsSpan()); + return path is not null && HasTrailingDirectorySeparator(path.AsSpan()); } /// - /// Determines whether the specified path ends with a directory path separator. + /// Returns a value that indicates whether the path, specified as a read-only span, ends in a directory separator. /// /// - /// The path to check. - /// if ends with a directory path separator; otherwise, . + /// The path to analyze. + /// if the path ends in a directory separator; otherwise, . public static bool HasTrailingDirectorySeparator(this IPath _, ReadOnlySpan path) { return HasTrailingDirectorySeparator(path); @@ -68,6 +65,36 @@ private static bool HasTrailingDirectorySeparator(ReadOnlySpan value) return IsAnyDirectorySeparator(last); } + /// + /// Returns a value that indicates whether the path starts with a directory separator. + /// + /// + /// The path to analyze. + /// if the path starts with a directory separator; otherwise, . + public static bool HasLeadingDirectorySeparator(this IPath _, [NotNullWhen(true)] string? path) + { + return path is not null && HasLeadingDirectorySeparator(path.AsSpan()); + } + + /// + /// Returns a value that indicates whether the path, specified as a read-only span, starts with a directory separator. + /// + /// + /// The path to analyze. + /// if the path starts with a directory separator; otherwise, . + public static bool HasLeadingDirectorySeparator(this IPath _, ReadOnlySpan path) + { + return HasLeadingDirectorySeparator(path); + } + + private static bool HasLeadingDirectorySeparator(ReadOnlySpan value) + { + if (value.Length == 0) + return false; + var first = value[0]; + return IsAnyDirectorySeparator(first); + } + private static bool IsAnyDirectorySeparator(char c) { return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar; diff --git a/src/CommonUtilities.FileSystem/test/CommonUtilities.FileSystem.Test.csproj b/src/CommonUtilities.FileSystem/test/CommonUtilities.FileSystem.Test.csproj index c66e8e8..dcf6e70 100644 --- a/src/CommonUtilities.FileSystem/test/CommonUtilities.FileSystem.Test.csproj +++ b/src/CommonUtilities.FileSystem/test/CommonUtilities.FileSystem.Test.csproj @@ -23,13 +23,13 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/CommonUtilities.FileSystem/test/PathExtensionsTest.HasLeadingPathSeparator.cs b/src/CommonUtilities.FileSystem/test/PathExtensionsTest.HasLeadingPathSeparator.cs new file mode 100644 index 0000000..de2a83e --- /dev/null +++ b/src/CommonUtilities.FileSystem/test/PathExtensionsTest.HasLeadingPathSeparator.cs @@ -0,0 +1,67 @@ +using System; +using System.IO.Abstractions; +using AnakinRaW.CommonUtilities.Testing; +using Xunit; + +namespace AnakinRaW.CommonUtilities.FileSystem.Test; + +public class HasLeadingPathSeparatorTest +{ + // Using the actual file system here since we are not modifying it. + // Also, we want to assure that everything works on the real system, + // not that an arbitrary test implementation works. + private readonly IFileSystem _fileSystem = new System.IO.Abstractions.FileSystem(); + + [Theory] + [InlineData("")] + [InlineData(null)] + public void Test_HasLeadingPathSeparator(string? input) + { + Assert.False(_fileSystem.Path.HasLeadingDirectorySeparator(input)); + Assert.False(_fileSystem.Path.HasLeadingDirectorySeparator(input.AsSpan())); + } + + public static TheoryData TestData_StartsWithDirectorySeparator_Windows => new() + { + { @"\", true }, + { @"/", true }, + { @"C:\folder\", false }, + { @"C:/folder/", false }, + { @"C:\", false }, + { @"C:/", false }, + { @"\\", true }, + { @"//", true }, + { @"\\server\share\", true }, + { @"\\?\UNC\a\", true }, + { @"\\?\C:\", true }, + { @"\\?\UNC\", true }, + { @"\folder", true }, + { @"folder", false }, + }; + + [PlatformSpecificTheory(TestPlatformIdentifier.Windows)] + [MemberData(nameof(TestData_StartsWithDirectorySeparator_Windows))] + public void Test_HasLeadingPathSeparator_Windows(string input, bool expected) + { + Assert.Equal(expected, _fileSystem.Path.HasLeadingDirectorySeparator(input)); + Assert.Equal(expected, _fileSystem.Path.HasLeadingDirectorySeparator(input.AsSpan())); + } + + + public static TheoryData TestData_StartsWithDirectorySeparator_Linux => new() + { + { @"/", true }, + { @"/folder/", true }, + { @"//", true }, + { @"folder", false }, + { @"/folder", true } + }; + + [PlatformSpecificTheory(TestPlatformIdentifier.Linux)] + [MemberData(nameof(TestData_StartsWithDirectorySeparator_Linux))] + public void Test_HasLeadingPathSeparator_Linux(string input, bool expected) + { + Assert.Equal(expected, _fileSystem.Path.HasLeadingDirectorySeparator(input)); + Assert.Equal(expected, _fileSystem.Path.HasLeadingDirectorySeparator(input.AsSpan())); + } +} \ No newline at end of file diff --git a/src/CommonUtilities.FileSystem/test/PathExtensionsTest.HasTrailingPathSeparator.cs b/src/CommonUtilities.FileSystem/test/PathExtensionsTest.HasTrailingPathSeparator.cs index 00acdae..83632d8 100644 --- a/src/CommonUtilities.FileSystem/test/PathExtensionsTest.HasTrailingPathSeparator.cs +++ b/src/CommonUtilities.FileSystem/test/PathExtensionsTest.HasTrailingPathSeparator.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.IO.Abstractions; using AnakinRaW.CommonUtilities.Testing; using Xunit; @@ -13,48 +14,63 @@ public class HasTrailingPathSeparatorTest private readonly IFileSystem _fileSystem = new System.IO.Abstractions.FileSystem(); [Theory] - [InlineData("", false)] - [InlineData(null, false)] - public void Test_HasTrailingPathSeparator(string? input, bool expected) + [InlineData("")] + [InlineData(null)] + public void Test_HasTrailingPathSeparator(string? input) { - if (input is null) - Assert.Throws(() => _fileSystem.Path.HasTrailingDirectorySeparator(input)); - else - Assert.Equal(expected, _fileSystem.Path.HasTrailingDirectorySeparator(input)); - Assert.Equal(expected, _fileSystem.Path.HasTrailingDirectorySeparator(input.AsSpan())); + Assert.False(_fileSystem.Path.HasTrailingDirectorySeparator(input)); + Assert.False(_fileSystem.Path.HasTrailingDirectorySeparator(input.AsSpan())); +#if NET + Assert.False(Path.EndsInDirectorySeparator(input)); +#endif } + public static TheoryData TestData_EndsInDirectorySeparator_Windows => new() + { + { @"\", 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 }, + }; + [PlatformSpecificTheory(TestPlatformIdentifier.Windows)] - [InlineData("/", true)] - [InlineData("\\", true)] - [InlineData("a", false)] - [InlineData("a/", true)] - [InlineData("a\\", true)] - [InlineData("a\\b", false)] - [InlineData("a/b", false)] - [InlineData("a/b\\", true)] - [InlineData("a\\b/", true)] + [MemberData(nameof(TestData_EndsInDirectorySeparator_Windows))] public void Test_HasTrailingPathSeparator_Windows(string input, bool expected) { Assert.Equal(expected, _fileSystem.Path.HasTrailingDirectorySeparator(input)); Assert.Equal(expected, _fileSystem.Path.HasTrailingDirectorySeparator(input.AsSpan())); +#if NET + Assert.Equal(Path.EndsInDirectorySeparator(input), expected); +#endif } + public static TheoryData TestData_EndsInDirectorySeparator_Linux => new() + { + { @"/", true }, + { @"/folder/", true }, + { @"//", true }, + { @"folder", false }, + { @"folder/", true } + }; + [PlatformSpecificTheory(TestPlatformIdentifier.Linux)] - [InlineData("/", true)] - [InlineData("\\", false)] - [InlineData("a", false)] - [InlineData("a/", true)] - [InlineData("a\\", false)] - [InlineData("a\\b", false)] - [InlineData("a/b", false)] - [InlineData("a/b\\", false)] - [InlineData("a\\b/", true)] - [InlineData("a\\b\\/", true)] - [InlineData("a\\b/\\", false)] + [MemberData(nameof(TestData_EndsInDirectorySeparator_Linux))] public void Test_HasTrailingPathSeparator_Linux(string input, bool expected) { Assert.Equal(expected, _fileSystem.Path.HasTrailingDirectorySeparator(input)); Assert.Equal(expected, _fileSystem.Path.HasTrailingDirectorySeparator(input.AsSpan())); +#if NET + Assert.Equal(Path.EndsInDirectorySeparator(input), expected); +#endif } } \ No newline at end of file diff --git a/src/CommonUtilities.Registry/test/CommonUtilities.Registry.Test.csproj b/src/CommonUtilities.Registry/test/CommonUtilities.Registry.Test.csproj index d6a6df4..a559dfb 100644 --- a/src/CommonUtilities.Registry/test/CommonUtilities.Registry.Test.csproj +++ b/src/CommonUtilities.Registry/test/CommonUtilities.Registry.Test.csproj @@ -17,7 +17,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/CommonUtilities.SimplePipeline/test/CommonUtilities.SimplePipeline.Test.csproj b/src/CommonUtilities.SimplePipeline/test/CommonUtilities.SimplePipeline.Test.csproj index e5b2da1..3d2a557 100644 --- a/src/CommonUtilities.SimplePipeline/test/CommonUtilities.SimplePipeline.Test.csproj +++ b/src/CommonUtilities.SimplePipeline/test/CommonUtilities.SimplePipeline.Test.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/src/CommonUtilities.TestingUtilities/CommonUtilities.TestingUtilities.csproj b/src/CommonUtilities.TestingUtilities/CommonUtilities.TestingUtilities.csproj index cfc3e8f..5b18018 100644 --- a/src/CommonUtilities.TestingUtilities/CommonUtilities.TestingUtilities.csproj +++ b/src/CommonUtilities.TestingUtilities/CommonUtilities.TestingUtilities.csproj @@ -21,7 +21,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all diff --git a/src/CommonUtilities/test/CommonUtilities.Test.csproj b/src/CommonUtilities/test/CommonUtilities.Test.csproj index 9c610c4..82a71f2 100644 --- a/src/CommonUtilities/test/CommonUtilities.Test.csproj +++ b/src/CommonUtilities/test/CommonUtilities.Test.csproj @@ -20,10 +20,10 @@ - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive