Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make paths case-sensitive on Unix #418

Merged
merged 21 commits into from
Dec 7, 2018
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0edd921
Added StringComparer to MockFileSystem, used in Mock* classes
rkoeninger Dec 4, 2018
502ec17
Merge branch 'master' of https://github.com/System-IO-Abstractions/Sy…
rkoeninger Dec 4, 2018
2c95458
Removed drive letter ToUpper in MockDriveInfo
rkoeninger Dec 4, 2018
be0439c
Labelled tests as being Windows/Unix specific based on case sensitivity
rkoeninger Dec 4, 2018
0cd82fe
Corrected UnixOnly test to check for null
rkoeninger Dec 4, 2018
c892fb1
Adjusted *Specifics wording
rkoeninger Dec 4, 2018
f29f438
Merge branch 'master' into unix-case-insensitive
rkoeninger Dec 4, 2018
533bc8a
Fixed MockDirectory.GetParent to correctly identify and return '/' root
rkoeninger Dec 4, 2018
9d93690
Merge branch 'unix-case-insensitive' of https://github.com/rkoeninger…
rkoeninger Dec 4, 2018
49eb635
Merge branch 'master' into unix-case-insensitive
rkoeninger Dec 4, 2018
642faf9
Fixed MockDirectory.GetFiles to handle un-normalized slashes
rkoeninger Dec 5, 2018
38e7e60
Made NormalizeSlashes handle UNC paths
rkoeninger Dec 5, 2018
d3ee172
Moved Exists check in MockDirectory.GetFiles into GetFilesInternal af…
rkoeninger Dec 5, 2018
be2c3a6
Made MockDirectory.GetLogicalDrives return drive letters in upper cas…
rkoeninger Dec 6, 2018
8a46f81
Fixed GetLogicalDrives test
rkoeninger Dec 6, 2018
bcc061c
De-triplicated check for Directory.Exists(DirName(FullPath(p)))
rkoeninger Dec 6, 2018
2053fd6
Added StringOperations, used throughout Mock* classes
rkoeninger Dec 6, 2018
93d322a
Removed WindowsSpecifics.EmptyInvalidPathChars
rkoeninger Dec 6, 2018
b4d5905
Made MockDirectory_GetParent_ShouldThr... WindowsOnly again
rkoeninger Dec 6, 2018
46ae1c2
Combined private CheckDirectoryExists and VerifyDir... in MockFile
rkoeninger Dec 6, 2018
057a4e8
Cleanup, review change, in MockFileExistsTests
rkoeninger Dec 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 58 additions & 13 deletions System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -547,10 +547,10 @@ public void MockDirectory_CreateDirectory_ShouldWorkWithUNCPath()
var fileSystem = new MockFileSystem();

// Act
fileSystem.Directory.CreateDirectory(XFS.Path(@"\\server\share\path\to\create", () => false));
fileSystem.Directory.CreateDirectory(@"\\server\share\path\to\create");

// Assert
Assert.IsTrue(fileSystem.Directory.Exists(XFS.Path(@"\\server\share\path\to\create\", () => false)));
Assert.IsTrue(fileSystem.Directory.Exists(@"\\server\share\path\to\create\"));
}

[Test]
Expand All @@ -561,7 +561,7 @@ public void MockDirectory_CreateDirectory_ShouldFailIfTryingToCreateUNCPathOnlyS
var fileSystem = new MockFileSystem();

// Act
var ex = Assert.Throws<ArgumentException>(() => fileSystem.Directory.CreateDirectory(XFS.Path(@"\\server", () => false)));
var ex = Assert.Throws<ArgumentException>(() => fileSystem.Directory.CreateDirectory(@"\\server"));

// Assert
StringAssert.StartsWith("The UNC path should be of the form \\\\server\\share.", ex.Message);
Expand All @@ -576,10 +576,10 @@ public void MockDirectory_CreateDirectory_ShouldSucceedIfTryingToCreateUNCPathSh
var fileSystem = new MockFileSystem();

// Act
fileSystem.Directory.CreateDirectory(XFS.Path(@"\\server\share", () => false));
fileSystem.Directory.CreateDirectory(@"\\server\share");

// Assert
Assert.IsTrue(fileSystem.Directory.Exists(XFS.Path(@"\\server\share\", () => false)));
Assert.IsTrue(fileSystem.Directory.Exists(@"\\server\share\"));
}

[Test]
Expand All @@ -599,6 +599,7 @@ public void MockDirectory_Delete_ShouldDeleteDirectory()
}

[Test]
[WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockDirectory_Delete_ShouldDeleteDirectoryCaseInsensitively()
{
// Arrange
Expand All @@ -614,6 +615,40 @@ public void MockDirectory_Delete_ShouldDeleteDirectoryCaseInsensitively()
Assert.IsFalse(fileSystem.Directory.Exists(XFS.Path(@"c:\bar")));
}

[Test]
[UnixOnly(UnixSpecifics.CaseSensitivity)]
public void MockDirectory_Delete_ShouldThrowDirectoryNotFoundException_WhenSpecifiedWithInDifferentCase()
{
// Arrange
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ "/bar/foo.txt", new MockFileData("Demo text content") }
});

// Act
TestDelegate action = () => fileSystem.Directory.Delete("/BAR", true);

// Assert
Assert.Throws<DirectoryNotFoundException>(action);
}

[Test]
[UnixOnly(UnixSpecifics.CaseSensitivity)]
public void MockDirectory_Delete_ShouldDeleteDirectoryCaseSensitively()
{
// Arrange
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ "/bar/foo.txt", new MockFileData("Demo text content") }
});

// Act
fileSystem.Directory.Delete("/bar", true);

// Assert
Assert.IsFalse(fileSystem.Directory.Exists("/bar"));
}

[Test]
public void MockDirectory_Delete_ShouldThrowDirectoryNotFoundException()
{
Expand Down Expand Up @@ -849,8 +884,8 @@ public void MockDirectory_GetLogicalDrives_Returns_LogicalDrives()
else
{
Assert.AreEqual(2, drives.Length);
Assert.IsTrue(drives.Contains("c:\\"));
Assert.IsTrue(drives.Contains("d:\\"));
Assert.IsTrue(drives.Contains(@"C:\"));
Assert.IsTrue(drives.Contains(@"D:\"));
}
}
#endif
Expand Down Expand Up @@ -1250,14 +1285,9 @@ public void MockDirectory_GetParent_ShouldReturnADirectoryInfoIfPathDoesNotExist
}

[Test]
[WindowsOnly(WindowsSpecifics.EmptyInvalidPathChars)]
public void MockDirectory_GetParent_ShouldThrowArgumentExceptionIfPathHasIllegalCharacters()
{
if (XFS.IsUnixPlatform())
{
Assert.Pass("Path.GetInvalidChars() does not return anything on Mono");
return;
}

// Arrange
var fileSystem = new MockFileSystem();

Expand All @@ -1282,6 +1312,21 @@ public void MockDirectory_GetParent_ShouldReturnNullIfPathIsRoot()
Assert.IsNull(actualResult);
}

[Test]
[UnixOnly(UnixSpecifics.SlashRoot)]
public void MockDirectory_GetParent_ShouldReturnRootIfDirectoryIsInRoot()
{
// Arrange
var fileSystem = new MockFileSystem();
fileSystem.AddDirectory("/bar");

// Act
var parent = fileSystem.Directory.GetParent("/bar");

// Assert
Assert.AreEqual("/", parent.FullName);
}

public static IEnumerable<string[]> MockDirectory_GetParent_Cases
{
get
Expand Down
21 changes: 21 additions & 0 deletions System.IO.Abstractions.TestingHelpers.Tests/MockFileExistsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public void MockFile_Exists_ShouldReturnTrueForSamePath()
}

[Test]
[WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockFile_Exists_ShouldReturnTrueForPathVaryingByCase()
{
// Arrange
Expand All @@ -45,6 +46,26 @@ public void MockFile_Exists_ShouldReturnTrueForPathVaryingByCase()
Assert.IsTrue(result);
}

[Test]
[UnixOnly(UnixSpecifics.CaseSensitivity)]
public void MockFile_Exists_ShouldReturnFalseForPathVaryingByCase()
{
// Arrange
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ XFS.Path(@"c:\something\demo.txt"), new MockFileData("Demo text content") },
rkoeninger marked this conversation as resolved.
Show resolved Hide resolved
{ XFS.Path(@"c:\something\other.gif"), new MockFileData(new byte[] { 0x21, 0x58, 0x3f, 0xa9 }) }
rkoeninger marked this conversation as resolved.
Show resolved Hide resolved
});

var file = new MockFile(fileSystem);

// Act
var result = file.Exists(XFS.Path(@"c:\SomeThing\Other.gif"));

// Assert
Assert.IsFalse(result);
}

[Test]
public void MockFile_Exists_ShouldReturnFalseForEntirelyDifferentPath()
{
Expand Down
42 changes: 39 additions & 3 deletions System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public void MockFileSystem_GetFile_ShouldReturnFileRegisteredInConstructor()
}

[Test]
[WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockFileSystem_GetFile_ShouldReturnFileRegisteredInConstructorWhenPathsDifferByCase()
{
var file1 = new MockFileData("Demo\r\ntext\ncontent\rvalue");
Expand All @@ -55,23 +56,56 @@ public void MockFileSystem_GetFile_ShouldReturnFileRegisteredInConstructorWhenPa
Assert.AreEqual(file1, result);
}

[Test]
[UnixOnly(UnixSpecifics.CaseSensitivity)]
public void MockFileSystem_GetFile_ShouldNotReturnFileRegisteredInConstructorWhenPathsDifferByCase()
{
var file1 = new MockFileData("Demo\r\ntext\ncontent\rvalue");
rkoeninger marked this conversation as resolved.
Show resolved Hide resolved
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ "/something/demo.txt", file1 },
{ "/something/other.gif", new MockFileData(new byte[] { 0x21, 0x58, 0x3f, 0xa9 }) }
rkoeninger marked this conversation as resolved.
Show resolved Hide resolved
});

var result = fileSystem.GetFile("/SomeThing/DEMO.txt");

Assert.IsNull(result);
}

[Test]
public void MockFileSystem_AddFile_ShouldHandleUnnormalizedSlashes()
{
var path = XFS.Path(@"c:\d1\d2\file.txt");
var altPath = XFS.Path("c:/d1/d2/file.txt");
rkoeninger marked this conversation as resolved.
Show resolved Hide resolved
var altParentPath = XFS.Path("c://d1//d2/");
var fs = new MockFileSystem();
fs.AddFile(path, new MockFileData("Hello"));

var fileCount = fs.Directory.GetFiles(altParentPath).Length;
var fileExists = fs.File.Exists(altPath);

Assert.AreEqual(1, fileCount);
Assert.IsTrue(fileExists);
}

[Test]
public void MockFileSystem_AddFile_ShouldHandleNullFileDataAsEmpty()
{
var path = XFS.Path(@"c:\something\nullish.txt");
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ @"c:\something\nullish.txt", null }
{ path, null }
});

var result = fileSystem.File.ReadAllText(@"c:\SomeThing\nullish.txt");
var result = fileSystem.File.ReadAllText(path);

Assert.IsEmpty(result, "Null MockFileData should be allowed for and result in an empty file.");
}

[Test]
public void MockFileSystem_AddFile_ShouldRepaceExistingFile()
{
const string path = @"c:\some\file.txt";
var path = XFS.Path(@"c:\some\file.txt");
const string existingContent = "Existing content";
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
Expand Down Expand Up @@ -157,6 +191,7 @@ public void MockFileSystem_AddFile_ShouldMatchCapitalization_PerfectMatch()
}

[Test]
[WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockFileSystem_AddFile_ShouldMatchCapitalization_PartialMatch()
{
var fileSystem = new MockFileSystem();
Expand All @@ -175,6 +210,7 @@ public void MockFileSystem_AddFile_ShouldMatchCapitalization_PartialMatch()
}

[Test]
[WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockFileSystem_AddFile_ShouldMatchCapitalization_PartialMatch_FurtherLeft()
{
var fileSystem = new MockFileSystem();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@

namespace System.IO.Abstractions.TestingHelpers.Tests
{
using XFS = MockUnixSupport;

[TestFixture]
public class MockUnixSupportTests
{
[Test]
[UnixOnly(UnixSpecifics.SlashRoot)]
public void Should_Convert_Backslashes_To_Slashes_On_Unix()
{
Assert.AreEqual("/test/", MockUnixSupport.Path(@"\test\", () => true));
Assert.AreEqual("/test/", XFS.Path(@"\test\"));
}

[Test]
[UnixOnly(UnixSpecifics.SlashRoot)]
public void Should_Remove_Drive_Letter_On_Unix()
{
Assert.AreEqual("/test/", MockUnixSupport.Path(@"c:\test\", () => true));
Assert.AreEqual("/test/", XFS.Path(@"c:\test\"));
}
}
}
4 changes: 3 additions & 1 deletion System.IO.Abstractions.TestingHelpers.Tests/UnixSpecifics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
{
internal static class UnixSpecifics
{
public const string SlashRoot = "Filesystem root is just '/' in Unix";
public const string SlashRoot = "Filesystem root is just '/' on Unix";

public const string CaseSensitivity = "Paths are case-sensitive on Unix";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public WindowsOnlyAttribute(string reason)

public void BeforeTest(ITest test)
{
if (MockUnixSupport.IsUnixPlatform())
if (!MockUnixSupport.IsWindowsPlatform())
rkoeninger marked this conversation as resolved.
Show resolved Hide resolved
{
Assert.Inconclusive(reason);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ internal static class WindowsSpecifics
public const string UNCPaths = "UNC paths are a Windows-only concept";

public const string StrictPathRules = "Windows has stricter path rules than other platforms";

public const string EmptyInvalidPathChars = "Path.GetInvalidPathChars() doesn't return anything on Mono";
rkoeninger marked this conversation as resolved.
Show resolved Hide resolved

public const string CaseInsensitivity = "Paths are case-insensitive on Windows";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public interface IMockFileDataAccessor
/// </summary>
IEnumerable<string> AllDirectories { get; }

bool CaseSensitive { get; }
StringComparer Comparer { get; }
StringComparison Comparison { get; }
rkoeninger marked this conversation as resolved.
Show resolved Hide resolved

FileBase File { get; }
DirectoryBase Directory { get; }
IFileInfoFactory FileInfo {get; }
Expand Down
Loading