diff options
author | Jeremy Kuhne <jeremy.kuhne@microsoft.com> | 2018-02-28 21:11:41 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-28 21:11:41 +0300 |
commit | d2a2221640d86036e0d5e6cf51f6d3a8258e6baa (patch) | |
tree | 11be98e46e6e4fab319b9efd5aac63b23638902b /src | |
parent | 7924c62db8400ec14e03089c43e35e561176684d (diff) |
Fix a bug in TranslateWin32Expression (#27539)
Add test coverage.
Diffstat (limited to 'src')
4 files changed, 119 insertions, 9 deletions
diff --git a/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemName.cs b/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemName.cs index 2de8d2a4ad..b41a69b458 100644 --- a/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemName.cs +++ b/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemName.cs @@ -44,7 +44,7 @@ namespace System.IO.Enumeration { case '.': modified = true; - if (i > 1 && i == length - 1 && expression[i - 1] == '*') + if (i >= 1 && i == length - 1 && expression[i - 1] == '*') { sb[sb.Length - 1] = '<'; // DOS_STAR (ends in *.) } diff --git a/src/System.IO.FileSystem/tests/Enumeration/MatchTypesTests.netcoreapp.cs b/src/System.IO.FileSystem/tests/Enumeration/MatchTypesTests.netcoreapp.cs new file mode 100644 index 0000000000..49b8e1b9e0 --- /dev/null +++ b/src/System.IO.FileSystem/tests/Enumeration/MatchTypesTests.netcoreapp.cs @@ -0,0 +1,80 @@ +// 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.Enumeration +{ + public abstract class MatchTypesTests : FileSystemTest + { + protected abstract string[] GetPaths(string directory, string pattern, EnumerationOptions options); + + [Fact] + public void QuestionMarkBehavior() + { + DirectoryInfo testDirectory = Directory.CreateDirectory(GetTestFilePath()); + FileInfo fileOne = new FileInfo(Path.Combine(testDirectory.FullName, "a.one")); + FileInfo fileTwo = new FileInfo(Path.Combine(testDirectory.FullName, "ab.two")); + FileInfo fileThree = new FileInfo(Path.Combine(testDirectory.FullName, "abc.three")); + + fileOne.Create().Dispose(); + fileTwo.Create().Dispose(); + fileThree.Create().Dispose(); + + // Question marks collapse to periods in Win32 + string[] paths = GetPaths(testDirectory.FullName, "a??.*", new EnumerationOptions { MatchType = MatchType.Win32 }); + FSAssert.EqualWhenOrdered(new string[] { fileOne.FullName, fileTwo.FullName, fileThree.FullName }, paths); + + paths = GetPaths(testDirectory.FullName, "*.?????", new EnumerationOptions { MatchType = MatchType.Win32 }); + FSAssert.EqualWhenOrdered(new string[] { fileOne.FullName, fileTwo.FullName, fileThree.FullName }, paths); + + // Simple, one question mark is one character + paths = GetPaths(testDirectory.FullName, "a??.*", new EnumerationOptions { MatchType = MatchType.Simple }); + FSAssert.EqualWhenOrdered(new string[] { fileThree.FullName }, paths); + + paths = GetPaths(testDirectory.FullName, "*.?????", new EnumerationOptions { MatchType = MatchType.Simple }); + FSAssert.EqualWhenOrdered(new string[] { fileThree.FullName }, paths); + } + + [Fact] + public void StarDotBehavior() + { + DirectoryInfo testDirectory = Directory.CreateDirectory(GetTestFilePath()); + FileInfo fileOne = new FileInfo(Path.Combine(testDirectory.FullName, "one")); + FileInfo fileTwo = new FileInfo(Path.Combine(testDirectory.FullName, "one.two")); + string fileThree = Path.Combine(testDirectory.FullName, "three."); + + fileOne.Create().Dispose(); + fileTwo.Create().Dispose(); + + // Need extended device syntax to create a name with a trailing dot. + File.Create(PlatformDetection.IsWindows ? @"\\?\" + fileThree : fileThree).Dispose(); + + // *. means any file without an extension + string[] paths = GetPaths(testDirectory.FullName, "*.", new EnumerationOptions { MatchType = MatchType.Win32 }); + FSAssert.EqualWhenOrdered(new string[] { fileOne.FullName, fileThree }, paths); + + // Simple, anything with a trailing period + paths = GetPaths(testDirectory.FullName, "*.", new EnumerationOptions { MatchType = MatchType.Simple }); + FSAssert.EqualWhenOrdered(new string[] { fileThree }, paths); + } + } + + public class MatchTypesTests_Directory_GetFiles : MatchTypesTests + { + protected override string[] GetPaths(string directory, string pattern, EnumerationOptions options) + { + return Directory.GetFiles(directory, pattern, options); + } + } + + public class MatchTypesTests_DirectoryInfo_GetFiles : MatchTypesTests + { + protected override string[] GetPaths(string directory, string pattern, EnumerationOptions options) + { + return new DirectoryInfo(directory).GetFiles(pattern, options).Select(i => i.FullName).ToArray(); + } + } +} diff --git a/src/System.IO.FileSystem/tests/Enumeration/Win32MatcherTests.netcoreapp.cs b/src/System.IO.FileSystem/tests/Enumeration/Win32MatcherTests.netcoreapp.cs index bc1d529969..d7c764ac15 100644 --- a/src/System.IO.FileSystem/tests/Enumeration/Win32MatcherTests.netcoreapp.cs +++ b/src/System.IO.FileSystem/tests/Enumeration/Win32MatcherTests.netcoreapp.cs @@ -9,13 +9,25 @@ namespace System.IO.Tests { public class Win32MatcherTests { - [Theory, MemberData(nameof(Win32MatchData)), MemberData(nameof(EscapedWin32MatchData))] + [Theory, + MemberData(nameof(SimpleMatchData)), + MemberData(nameof(EscapedSimpleMatchData)), + MemberData(nameof(Win32MatchData)), + MemberData(nameof(EscapedWin32MatchData))] public static void Win32Match(string expression, string name, bool ignoreCase, bool expected) { Assert.Equal(expected, FileSystemName.MatchesWin32Expression(expression, name.AsSpan(), ignoreCase)); } - public static TheoryData<string, string, bool, bool> EscapedWin32MatchData => new TheoryData<string, string, bool, bool> + [Theory, + MemberData(nameof(SimpleMatchData)), + MemberData(nameof(EscapedSimpleMatchData))] + public static void SimpleMatch(string expression, string name, bool ignoreCase, bool expected) + { + Assert.Equal(expected, FileSystemName.MatchesSimpleExpression(expression, name.AsSpan(), ignoreCase)); + } + + public static TheoryData<string, string, bool, bool> EscapedSimpleMatchData => new TheoryData<string, string, bool, bool> { // Trailing escape matches as it is considered "invisible" { "\\", "\\", false, true }, @@ -23,7 +35,6 @@ namespace System.IO.Tests { "\\\\", "\\", false, true }, { "\\\\", "\\", true, true }, - { "\\*", "a", false, false }, { "\\*", "a", true, false }, { "\\*", "*", false, true }, @@ -36,14 +47,17 @@ namespace System.IO.Tests { "*\\*", "***A", true, false }, { "*\\*", "ABC*A", false, false }, { "*\\*", "ABC*A", true, false }, + }; + public static TheoryData<string, string, bool, bool> EscapedWin32MatchData => new TheoryData<string, string, bool, bool> + { { "\\\"", "a", false, false }, { "\\\"", "a", true, false }, { "\\\"", "\"", false, true }, { "\\\"", "\"", true, true }, }; - public static TheoryData<string, string, bool, bool> Win32MatchData => new TheoryData<string, string, bool, bool> + public static TheoryData<string, string, bool, bool> SimpleMatchData => new TheoryData<string, string, bool, bool> { { null, "", false, false }, { null, "", true, false }, @@ -58,7 +72,6 @@ namespace System.IO.Tests { "*foo", "nofoo", true, true }, { "*foo", "NoFOO", true, true }, { "*foo", "noFOO", false, false }, - { @"*", @"foo.txt", true, true }, { @".", @"foo.txt", true, false }, { @".", @"footxt", true, false }, @@ -66,6 +79,10 @@ namespace System.IO.Tests { @"*.*", @"foo.", true, true }, { @"*.*", @".foo", true, true }, { @"*.*", @"footxt", true, false }, + }; + + public static TheoryData<string, string, bool, bool> Win32MatchData => new TheoryData<string, string, bool, bool> + { { "<\"*", @"footxt", true, true }, // DOS equivalent of *.* { "<\"*", @"foo.txt", true, true }, // DOS equivalent of *.* { "<\"*", @".foo", true, true }, // DOS equivalent of *.* @@ -112,5 +129,19 @@ namespace System.IO.Tests { @"<.", @"a.", true, true }, { @"<.", @"a.b", true, false }, }; + + [Theory, + InlineData("", "*"), + InlineData("*.*", "*"), + InlineData("*", "*"), + InlineData(".", "."), + InlineData("?", ">"), + InlineData("*.", "<"), + InlineData("?.?", ">\">"), + InlineData("foo*.", "foo<")] + public void TranslateExpression(string expression, string expected) + { + Assert.Equal(expected, FileSystemName.TranslateWin32Expression(expression)); + } } } diff --git a/src/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj index 5ff308577c..ef777424cb 100644 --- a/src/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj +++ b/src/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj @@ -64,6 +64,7 @@ <Compile Include="Enumeration\PatternTransformTests.netcoreapp.cs" /> <Compile Include="Enumeration\RootTests.netcoreapp.cs" /> <Compile Include="Enumeration\AttributeTests.netcoreapp.cs" /> + <Compile Include="Enumeration\MatchTypesTests.netcoreapp.cs" /> </ItemGroup> <ItemGroup> <!-- Rewritten --> @@ -195,8 +196,6 @@ <ItemGroup> <EmbeddedResource Include="Resources\$(AssemblyName).rd.xml" /> </ItemGroup> - <ItemGroup> - <Folder Include="Matchers\" /> - </ItemGroup> + <ItemGroup /> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> </Project>
\ No newline at end of file |