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 all 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.StrictPathRules)]
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
60 changes: 37 additions & 23 deletions System.IO.Abstractions.TestingHelpers.Tests/MockFileExistsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,70 @@ namespace System.IO.Abstractions.TestingHelpers.Tests

using XFS = MockUnixSupport;

public class MockFileExistsTests {
public class MockFileExistsTests
{
[Test]
public void MockFile_Exists_ShouldReturnTrueForSamePath()
{
// Arrange
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ XFS.Path(@"c:\something\demo.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\something\other.gif"), new MockFileData(new byte[] { 0x21, 0x58, 0x3f, 0xa9 }) }
{ XFS.Path(@"C:\something\other.gif"), new MockFileData("gif content") }
});

var file = new MockFile(fileSystem);

// Act
var result = file.Exists(XFS.Path(@"c:\something\other.gif"));
var result = fileSystem.File.Exists(XFS.Path(@"C:\something\other.gif"));

// Assert
Assert.IsTrue(result);
}

[Test]
[WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockFile_Exists_ShouldReturnTrueForPathVaryingByCase()
{
// Arrange
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ XFS.Path(@"c:\something\demo.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\something\other.gif"), new MockFileData(new byte[] { 0x21, 0x58, 0x3f, 0xa9 }) }
{ @"C:\something\demo.txt", new MockFileData("Demo text content") }
});

var file = new MockFile(fileSystem);

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

// Assert
Assert.IsTrue(result);
}

[Test]
public void MockFile_Exists_ShouldReturnFalseForEntirelyDifferentPath()
[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") },
{ XFS.Path(@"c:\something\other.gif"), new MockFileData(new byte[] { 0x21, 0x58, 0x3f, 0xa9 }) }
{ "/something/demo.txt", new MockFileData("Demo text content") }
});

var file = new MockFile(fileSystem);
// Act
var result = fileSystem.File.Exists("/SomeThing/DEMO.txt");

// Assert
Assert.IsFalse(result);
}

[Test]
public void MockFile_Exists_ShouldReturnFalseForEntirelyDifferentPath()
{
// Arrange
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ XFS.Path(@"C:\something\demo.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"C:\something\other.gif"), new MockFileData("gif content") }
});

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

// Assert
Assert.IsFalse(result);
Expand All @@ -67,9 +78,14 @@ public void MockFile_Exists_ShouldReturnFalseForEntirelyDifferentPath()
[Test]
public void MockFile_Exists_ShouldReturnFalseForNullPath()
{
var file = new MockFile(new MockFileSystem());
// Arrange
var fileSystem = new MockFileSystem();

Assert.That(file.Exists(null), Is.False);
// Act
var result = fileSystem.File.Exists(null);

// Assert
Assert.IsFalse(result);
}

[Test]
Expand All @@ -78,14 +94,12 @@ public void MockFile_Exists_ShouldReturnFalseForDirectories()
// Arrange
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ XFS.Path(@"c:\something\demo.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"c:\something\other.gif"), new MockFileData(new byte[] { 0x21, 0x58, 0x3f, 0xa9 }) }
{ XFS.Path(@"C:\something\demo.txt"), new MockFileData("Demo text content") },
{ XFS.Path(@"C:\something\other.gif"), new MockFileData("gif content") }
});

var file = new MockFile(fileSystem);

// Act
var result = file.Exists(XFS.Path(@"c:\SomeThing\"));
var result = fileSystem.File.Exists(XFS.Path(@"C:\something\"));

// Assert
Assert.IsFalse(result);
Expand Down
47 changes: 41 additions & 6 deletions System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void MockFileSystem_GetFile_ShouldReturnNullWhenFileIsNotRegistered()
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ @"c:\something\demo.txt", new MockFileData("Demo\r\ntext\ncontent\rvalue") },
{ @"c:\something\other.gif", new MockFileData(new byte[] { 0x21, 0x58, 0x3f, 0xa9 }) }
{ @"c:\something\other.gif", new MockFileData("gif content") }
});

var result = fileSystem.GetFile(@"c:\something\else.txt");
Expand All @@ -32,7 +32,7 @@ public void MockFileSystem_GetFile_ShouldReturnFileRegisteredInConstructor()
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ @"c:\something\demo.txt", file1 },
{ @"c:\something\other.gif", new MockFileData(new byte[] { 0x21, 0x58, 0x3f, 0xa9 }) }
{ @"c:\something\other.gif", new MockFileData("gif content") }
});

var result = fileSystem.GetFile(@"c:\something\demo.txt");
Expand All @@ -41,37 +41,70 @@ public void MockFileSystem_GetFile_ShouldReturnFileRegisteredInConstructor()
}

[Test]
[WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockFileSystem_GetFile_ShouldReturnFileRegisteredInConstructorWhenPathsDifferByCase()
{
var file1 = new MockFileData("Demo\r\ntext\ncontent\rvalue");
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ @"c:\something\demo.txt", file1 },
{ @"c:\something\other.gif", new MockFileData(new byte[] { 0x21, 0x58, 0x3f, 0xa9 }) }
{ @"c:\something\other.gif", new MockFileData("gif content") }
});

var result = fileSystem.GetFile(@"c:\SomeThing\DEMO.txt");

Assert.AreEqual(file1, result);
}

[Test]
[UnixOnly(UnixSpecifics.CaseSensitivity)]
public void MockFileSystem_GetFile_ShouldNotReturnFileRegisteredInConstructorWhenPathsDifferByCase()
{
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ "/something/demo.txt", new MockFileData("Demo\r\ntext\ncontent\rvalue") },
{ "/something/other.gif", new MockFileData("gif content") }
});

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 alternatePath = XFS.Path("c:/d1/d2/file.txt");
var alternateParentPath = XFS.Path("c://d1//d2/");
var fs = new MockFileSystem();
fs.AddFile(path, new MockFileData("Hello"));

var fileCount = fs.Directory.GetFiles(alternateParentPath).Length;
var fileExists = fs.File.Exists(alternatePath);

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 +190,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 +209,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";
}
}
Loading