Skip to content

Commit

Permalink
fix(439): Pattern "*." returns only files with no extension (#516)
Browse files Browse the repository at this point in the history
* fix(439): Add special case to Directory.GetFilesInternal to return only files without extensions when search pattern is "*."

* Added files with no extension to the existing tests in MockDirectoryTests.

* fix(439): Pattern *. works as System.Directory.

* Fix for case sensitive paths.
  • Loading branch information
KaliVi authored and fgreinacher committed Oct 11, 2019
1 parent 00e7431 commit c317a93
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 7 deletions.
157 changes: 153 additions & 4 deletions System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ public void MockDirectory_GetFiles_ShouldReturnAllFilesBelowPathWhenPatternIsWil
XFS.Path(@"c:\a\a.txt"),
XFS.Path(@"c:\a\b.gif"),
XFS.Path(@"c:\a\c.txt"),
XFS.Path(@"c:\a\d"),
XFS.Path(@"c:\a\a\a.txt"),
XFS.Path(@"c:\a\a\b.txt"),
XFS.Path(@"c:\a\a\c.gif")
XFS.Path(@"c:\a\a\c.gif"),
XFS.Path(@"c:\a\a\d")
};

// Act
Expand All @@ -39,12 +41,15 @@ private MockFileSystem SetupFileSystem()
{ XFS.Path(@"c:\a.gif"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\b.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\c.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\d"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\a\a.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\a\b.gif"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\a\c.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\a\d"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\a\a\a.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\a\a\b.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\a\a\c.gif"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\a\a\d"), new MockFileData("Demo text content") }
});

}
Expand All @@ -58,7 +63,8 @@ public void MockDirectory_GetFiles_ShouldReturnFilesDirectlyBelowPathWhenPattern
{
XFS.Path(@"c:\a\a.txt"),
XFS.Path(@"c:\a\b.gif"),
XFS.Path(@"c:\a\c.txt")
XFS.Path(@"c:\a\c.txt"),
XFS.Path(@"c:\a\d")
};

// Act
Expand Down Expand Up @@ -221,6 +227,145 @@ public void MockDirectory_GetFiles_ShouldFilterByExtensionBasedSearchPatternAndS
Assert.That(result, Is.EquivalentTo(expected));
}

[Test]
public void MockDirectory_GetFiles_ShouldFilterForAllFilesWithNoExtensionsAndSearchOptionTopDirectoryOnly()
{
// Arrange
var fileSystem = SetupFileSystem();
fileSystem.AddFile(XFS.Path(@"C:\mytestfilename"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfilename."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name.again"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name.again."), new MockFileData("some content"));

var expected = new[]
{
XFS.Path(@"c:\d"),
XFS.Path(@"C:\mytestfilename"),
XFS.Path(@"C:\mytestfilename."),
XFS.Path(@"C:\mytestfile.name."),
XFS.Path(@"C:\mytestfile.name.again.")
};

// Act
var result = fileSystem.Directory.GetFiles(XFS.Path(@"C:\"), "*.", SearchOption.TopDirectoryOnly);

// Assert
Assert.That(result, Is.EquivalentTo(expected));
}

[Test]
public void MockDirectory_GetFiles_ShouldFilterForAllFilesWithNoExtensionsAndSearchOptionAllDirectories()
{
// Arrange
var fileSystem = SetupFileSystem();
fileSystem.AddFile(XFS.Path(@"C:\specialNameFormats\mytestfilename"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\specialNameFormats\mytestfilename."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\specialNameFormats\mytestfile.name"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\specialNameFormats\mytestfile.name."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\specialNameFormats\mytestfile.name.again"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\specialNameFormats\mytestfile.name.again."), new MockFileData("some content"));

var expected = new[]
{
XFS.Path(@"c:\d"),
XFS.Path(@"c:\a\d"),
XFS.Path(@"c:\a\a\d"),
XFS.Path(@"C:\specialNameFormats\mytestfilename"),
XFS.Path(@"C:\specialNameFormats\mytestfilename."),
XFS.Path(@"C:\specialNameFormats\mytestfile.name."),
XFS.Path(@"C:\specialNameFormats\mytestfile.name.again.")
};

// Act
var result = fileSystem.Directory.GetFiles(XFS.Path(@"c:\"), "*.", SearchOption.AllDirectories);

// Assert
Assert.That(result, Is.EquivalentTo(expected));
}

[Test]
public void MockDirectory_GetFiles_ShouldFilterForFilesWithNoExtensionsAndNonTrivialFilterAndSearchOptionTopDirectoryOnly()
{
// Arrange
var fileSystem = SetupFileSystem();
fileSystem.AddFile(XFS.Path(@"C:\mytestfilename"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfilename."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name.again"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name.again."), new MockFileData("some content"));

var expected = new[]
{
XFS.Path(@"C:\mytestfilename"),
XFS.Path(@"C:\mytestfilename."),
XFS.Path(@"C:\mytestfile.name."),
XFS.Path(@"C:\mytestfile.name.again.")

};

// Act
var result = fileSystem.Directory.GetFiles(XFS.Path(@"C:\"), "my??s*.", SearchOption.TopDirectoryOnly);

// Assert
Assert.That(result, Is.EquivalentTo(expected));
}

[Test]
public void MockDirectory_GetFiles_ShouldFilterForFilesWithNoExtensionsAndNonTrivialFilter2AndSearchOptionTopDirectoryOnly()
{
// Arrange
var fileSystem = SetupFileSystem();
fileSystem.AddFile(XFS.Path(@"C:\mytestfilename"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfilename."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name.again"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name.again."), new MockFileData("some content"));

var expected = new[]
{
XFS.Path(@"C:\mytestfile.name"),
XFS.Path(@"C:\mytestfile.name."),
XFS.Path(@"C:\mytestfile.name.again.")

};

// Act
var result = fileSystem.Directory.GetFiles(XFS.Path(@"C:\"), "my*.n*.", SearchOption.TopDirectoryOnly);

// Assert
Assert.That(result, Is.EquivalentTo(expected));
}

[Test]
public void MockDirectory_GetFiles_ShouldFilterForFilesWithNoExtensionsAndFilterThatIncludesDotAndSearchOptionTopDirectoryOnly()
{
// Arrange
var fileSystem = SetupFileSystem();
fileSystem.AddFile(XFS.Path(@"C:\mytestfilename"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfilename."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name."), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name.again"), new MockFileData("some content"));
fileSystem.AddFile(XFS.Path(@"C:\mytestfile.name.again."), new MockFileData("some content"));

var expected = new[]
{
XFS.Path(@"C:\mytestfile.name"),
XFS.Path(@"C:\mytestfile.name."),
XFS.Path(@"C:\mytestfile.name.again.")
};

// Act
var result = fileSystem.Directory.GetFiles(XFS.Path(@"C:\"), "my*.n*.", SearchOption.TopDirectoryOnly);

// Assert
Assert.That(result, Is.EquivalentTo(expected));
}

private void ExecuteTimeAttributeTest(Action<IFileSystem, string, DateTime> setter, Func<IFileSystem, string, DateTime> getter)
{
string path = XFS.Path(@"c:\something\demo.txt");
Expand Down Expand Up @@ -1215,7 +1360,7 @@ public void MockDirectory_Move_ShouldMoveFiles()
{
string sourceFilePath = XFS.Path(@"c:\demo.txt");
string sourceFileContent = "this is some content";

var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ sourceFilePath, new MockFileData(sourceFileContent) }
Expand Down Expand Up @@ -1497,9 +1642,11 @@ public void MockDirectory_EnumerateFiles_ShouldReturnAllFilesBelowPathWhenPatter
XFS.Path(@"c:\a\a.txt"),
XFS.Path(@"c:\a\b.gif"),
XFS.Path(@"c:\a\c.txt"),
XFS.Path(@"c:\a\d"),
XFS.Path(@"c:\a\a\a.txt"),
XFS.Path(@"c:\a\a\b.txt"),
XFS.Path(@"c:\a\a\c.gif")
XFS.Path(@"c:\a\a\c.gif"),
XFS.Path(@"c:\a\a\d")
};

// Act
Expand Down Expand Up @@ -1589,9 +1736,11 @@ public void MockDirectory_EnumerateFileSystemEntries_ShouldReturnAllFilesBelowPa
XFS.Path(@"c:\a\a.txt"),
XFS.Path(@"c:\a\b.gif"),
XFS.Path(@"c:\a\c.txt"),
XFS.Path(@"c:\a\d"),
XFS.Path(@"c:\a\a\a.txt"),
XFS.Path(@"c:\a\a\b.txt"),
XFS.Path(@"c:\a\a\c.gif"),
XFS.Path(@"c:\a\a\d"),
XFS.Path(@"c:\a\a")
};

Expand Down
36 changes: 33 additions & 3 deletions System.IO.Abstractions.TestingHelpers/MockDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,11 @@ private string[] GetFilesInternal(
? @"([^<>:""/|?*]*/)*"
: @"([^<>:""/\\|?*]*\\)*";

var searchEndInStarDot = searchPattern.EndsWith(@"*.");

string fileNamePattern;
string pathPatternNoExtension = string.Empty;
string pathPatternEndsInDot = string.Empty;
string pathPatternSpecial = null;

if (searchPattern == "*")
Expand Down Expand Up @@ -264,9 +268,17 @@ private string[] GetFilesInternal(
searchOption == SearchOption.AllDirectories ? allDirectoriesPattern : string.Empty,
fileNamePattern);

return files
.Where(p => Regex.IsMatch(p, pathPattern)
|| (pathPatternSpecial != null && Regex.IsMatch(p, pathPatternSpecial)))
if (searchEndInStarDot)
{
pathPatternNoExtension = ReplaceLastOccurrence(pathPattern, @"]*?\.", @"\.]*?[.]*");
pathPatternEndsInDot = ReplaceLastOccurrence(pathPattern, @"]*?\.", @"]*?[.]{1,}");
}

return files.Where(p =>
!searchEndInStarDot ?
(Regex.IsMatch(p, pathPattern) || (pathPatternSpecial != null && Regex.IsMatch(p, pathPatternSpecial)))
: (Regex.IsMatch(p, pathPatternNoExtension) || Regex.IsMatch(p, pathPatternEndsInDot))
)
.ToArray();
}

Expand Down Expand Up @@ -558,5 +570,23 @@ private void CheckSearchPattern(string searchPattern)
throw CommonExceptions.IllegalCharactersInPath(nameof(searchPattern));
}
}

private string ReplaceLastOccurrence(string source, string find, string replace)
{
if (source == null)
{
return source;
}

var place = source.LastIndexOf(find);

if (place == -1)
{
return source;
}

var result = source.Remove(place, find.Length).Insert(place, replace);
return result;
}
}
}

0 comments on commit c317a93

Please sign in to comment.