diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index c49eb8654..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-language: csharp
-mono: none
-dotnet: 2.1.4
-script:
- - dotnet build System.IO.Abstractions --framework netstandard1.4
- - dotnet build System.IO.Abstractions.TestingHelpers --framework netstandard1.4
- - dotnet test System.IO.Abstractions.TestingHelpers.Tests --framework netcoreapp2.0
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 000000000..2f1977e33
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,28 @@
+{
+ // Use IntelliSense to find out which attributes exist for C# debugging
+ // Use hover for the description of the existing attributes
+ // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": ".NET Core Launch (console)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ // If you have changed target frameworks, make sure to update the program path.
+ "program": "${workspaceFolder}/System.IO.Abstractions.TestingHelpers.Tests/bin/Debug/netcoreapp2.0/System.IO.Abstractions.TestingHelpers.Tests.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}/System.IO.Abstractions.TestingHelpers.Tests",
+ // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
+ "console": "internalConsole",
+ "stopAtEntry": false,
+ "internalConsoleOptions": "openOnSessionStart"
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach",
+ "processId": "${command:pickProcess}"
+ }
+ ,]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 000000000..a4c910c67
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,15 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/System.IO.Abstractions.TestingHelpers.Tests/System.IO.Abstractions.TestingHelpers.Tests.csproj"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..220091947
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,22 @@
+# Contributor guide
+
+## Versioning
+
+This library uses [Nerdbank.GitVersioning](https://github.com/AArnott/Nerdbank.GitVersioning) for generating stable and reproducible version numbers.
+
+The base version is manually maintained in [the version config](version.json). Every build calculates its final version number based on the base version and the number of changes that occured since the last change to the version config.
+
+The base version represents the MAJOR and MINOR parts of [SemVer](https://semver.org). If a PR contains breaking changes or new features the base version has to be changed accordingly. If a PR solely contains minor changes (bug fixes, code improvements) nothing needs to be done as the PATCH number will automatically increment with each commit.
+
+## Branches / tags
+
+* `master` contains the latest sources - this is where we develop.
+* `release` contains the sources for the latest version on `nuget.org` - this is where we deploy from.
+* All versions on `nuget.org` have a matching GitHub release/tag
+
+### Release workflow
+
+1. Create a [PR from `master` to `release`](https://github.com/System-IO-Abstractions/System.IO.Abstractions/compare/release...master?expand=1) and wait for CI to finish.
+1. Inspect CI run (test results, version number)
+1. Merge PR and wait for deployment
+1. Inspect newly created package versions on NuGet.org and newly created GitHub release
diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 000000000..a4b4cac9e
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 64a1e40e2..4aa074087 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,5 @@
[](https://www.nuget.org/packages/System.IO.Abstractions)
-
-[](https://ci.appveyor.com/project/tathamoddie/system-io-abstractions/branch/master) on Windows
-
-[](https://travis-ci.org/System-IO-Abstractions/System.IO.Abstractions) on Linux
+[](https://ci.appveyor.com/project/tathamoddie/system-io-abstractions/branch/master) [](https://dependabot.com)
---
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs
index 194dde31b..a850a157d 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs
@@ -36,8 +36,8 @@ public static IEnumerable MockDirectoryInfo_Exists_Cases
{
get
{
- yield return new object[]{ XFS.Path(@"c:\temp\folder"), true };
- yield return new object[]{ XFS.Path(@"c:\temp\folder\notExistant"), false };
+ yield return new object[] { XFS.Path(@"c:\temp\folder"), true };
+ yield return new object[] { XFS.Path(@"c:\temp\folder\notExistant"), false };
}
}
@@ -152,8 +152,8 @@ public void MockDirectoryInfo_GetParent_ShouldReturnDirectoriesAndNamesWithSearc
[Test]
public void MockDirectoryInfo_EnumerateFiles_ShouldReturnAllFiles()
{
- // Arrange
- var fileSystem = new MockFileSystem(new Dictionary
+ // Arrange
+ var fileSystem = new MockFileSystem(new Dictionary
{
//Files "above" in folder we're querying
{ XFS.Path(@"c:\temp\a.txt"), "" },
@@ -166,11 +166,11 @@ public void MockDirectoryInfo_EnumerateFiles_ShouldReturnAllFiles()
{ XFS.Path(@"c:\temp\folder\deeper\d.txt"), "" }
});
- // Act
- var directoryInfo = new MockDirectoryInfo(fileSystem, XFS.Path(@"c:\temp\folder"));
+ // Act
+ var directoryInfo = new MockDirectoryInfo(fileSystem, XFS.Path(@"c:\temp\folder"));
- // Assert
- Assert.AreEqual(new[]{"b.txt", "c.txt"}, directoryInfo.EnumerateFiles().ToList().Select(x => x.Name).ToArray());
+ // Assert
+ Assert.AreEqual(new[] { "b.txt", "c.txt" }, directoryInfo.EnumerateFiles().ToList().Select(x => x.Name).ToArray());
}
[Test]
@@ -238,7 +238,7 @@ public void MockDirectoryInfo_Constructor_ShouldThrowArgumentNullException_IfArg
var fileSystem = new MockFileSystem();
// Act
- TestDelegate action = () => new MockDirectoryInfo(fileSystem, null);
+ TestDelegate action = () => new MockDirectoryInfo(fileSystem, null);
// Assert
var exception = Assert.Throws(action);
@@ -272,20 +272,18 @@ public void MockDirectoryInfo_Constructor_ShouldThrowArgumentException_IfArgumen
Assert.That(exception.Message, Does.StartWith("The path is not of a legal form."));
}
- [Test]
- public void MockDirectoryInfo_ToString_ShouldReturnDirectoryName()
+ [TestCase(@"c:\temp\folder\folder")]
+ [TestCase(@"..\..\..\Desktop")]
+ public void MockDirectoryInfo_ToString_ShouldReturnDirectoryName(string directoryName)
{
- var directoryPath = XFS.Path(@"c:\temp\folder\folder");
-
// Arrange
- var fileSystem = new MockFileSystem();
- var directoryInfo = new MockDirectoryInfo(fileSystem, directoryPath);
+ var directoryPath = XFS.Path(directoryName);
// Act
- var str = directoryInfo.ToString();
+ var mockDirectoryInfo = new MockDirectoryInfo(new MockFileSystem(), directoryPath);
// Assert
- Assert.AreEqual(directoryPath, str);
+ Assert.AreEqual(directoryPath, mockDirectoryInfo.ToString());
}
}
}
\ No newline at end of file
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs
index 9cd17fa75..250241dd2 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs
@@ -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]
@@ -561,7 +561,7 @@ public void MockDirectory_CreateDirectory_ShouldFailIfTryingToCreateUNCPathOnlyS
var fileSystem = new MockFileSystem();
// Act
- var ex = Assert.Throws(() => fileSystem.Directory.CreateDirectory(XFS.Path(@"\\server", () => false)));
+ var ex = Assert.Throws(() => fileSystem.Directory.CreateDirectory(@"\\server"));
// Assert
StringAssert.StartsWith("The UNC path should be of the form \\\\server\\share.", ex.Message);
@@ -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]
@@ -599,6 +599,7 @@ public void MockDirectory_Delete_ShouldDeleteDirectory()
}
[Test]
+ [WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockDirectory_Delete_ShouldDeleteDirectoryCaseInsensitively()
{
// Arrange
@@ -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
+ {
+ { "/bar/foo.txt", new MockFileData("Demo text content") }
+ });
+
+ // Act
+ TestDelegate action = () => fileSystem.Directory.Delete("/BAR", true);
+
+ // Assert
+ Assert.Throws(action);
+ }
+
+ [Test]
+ [UnixOnly(UnixSpecifics.CaseSensitivity)]
+ public void MockDirectory_Delete_ShouldDeleteDirectoryCaseSensitively()
+ {
+ // Arrange
+ var fileSystem = new MockFileSystem(new Dictionary
+ {
+ { "/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()
{
@@ -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
@@ -1184,11 +1219,12 @@ public void MockDirectory_GetCurrentDirectory_ShouldReturnValueFromFileSystemCon
Assert.AreEqual(directory, actual);
}
-
-
+
[Test]
- public void MockDirectory_GetCurrentDirectory_ShouldReturnDefaultPathWhenNotSet() {
- string directory = Path.GetTempPath();
+ public void MockDirectory_GetCurrentDirectory_ShouldReturnDefaultPathWhenNotSet()
+ {
+ string directory = XFS.Path(@"C:\");
+
var fileSystem = new MockFileSystem();
var actual = fileSystem.Directory.GetCurrentDirectory();
@@ -1249,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();
@@ -1281,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 MockDirectory_GetParent_Cases
{
get
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockDriveInfoFactoryTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockDriveInfoFactoryTests.cs
index 2b10ec883..c6b7d5900 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockDriveInfoFactoryTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockDriveInfoFactoryTests.cs
@@ -26,7 +26,7 @@ public void MockDriveInfoFactory_GetDrives_ShouldReturnDrives()
var actualNames = actualResults.Select(d => d.Name);
// Assert
- Assert.That(actualNames, Is.EquivalentTo(new[] { @"C:\", @"Z:\", @"D:\" }));
+ Assert.That(actualNames, Is.EquivalentTo(new[] { @"C:\", @"Z:\", @"d:\" }));
}
[Test]
@@ -47,7 +47,7 @@ public void MockDriveInfoFactory_GetDrives_ShouldReturnDrivesWithNoDuplicates()
var actualNames = actualResults.Select(d => d.Name);
// Assert
- Assert.That(actualNames, Is.EquivalentTo(new[] { @"C:\", @"Z:\", @"D:\" }));
+ Assert.That(actualNames, Is.EquivalentTo(new[] { @"C:\", @"Z:\", @"d:\" }));
}
[Test]
@@ -67,7 +67,7 @@ public void MockDriveInfoFactory_GetDrives_ShouldReturnOnlyLocalDrives()
var actualNames = actualResults.Select(d => d.Name);
// Assert
- Assert.That(actualNames, Is.EquivalentTo(new[] { @"C:\", @"Z:\", @"D:\" }));
+ Assert.That(actualNames, Is.EquivalentTo(new[] { @"C:\", @"Z:\", @"d:\" }));
}
[Test]
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockDriveInfoTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockDriveInfoTests.cs
index 8b33fd16f..88524b2f4 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockDriveInfoTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockDriveInfoTests.cs
@@ -21,7 +21,7 @@ public void MockDriveInfo_Constructor_ShouldInitializeLocalWindowsDrives(string
var driveInfo = new MockDriveInfo(fileSystem, path);
// Assert
- Assert.AreEqual(@"C:\", driveInfo.Name);
+ Assert.AreEqual(@"c:\", driveInfo.Name);
}
[Test]
@@ -35,7 +35,7 @@ public void MockDriveInfo_Constructor_ShouldInitializeLocalWindowsDrives_Special
var driveInfo = new MockDriveInfo(fileSystem, "c");
// Assert
- Assert.AreEqual(@"C:\", driveInfo.Name);
+ Assert.AreEqual(@"c:\", driveInfo.Name);
}
[TestCase(@"\\unc\share")]
@@ -59,7 +59,7 @@ public void MockDriveInfo_RootDirectory_ShouldReturnTheDirectoryBase()
var fileSystem = new MockFileSystem();
fileSystem.AddDirectory(XFS.Path(@"c:\Test"));
var driveInfo = new MockDriveInfo(fileSystem, "c:");
- var expectedDirectory = XFS.Path(@"C:\");
+ var expectedDirectory = XFS.Path(@"c:\");
// Act
var actualDirectory = driveInfo.RootDirectory;
@@ -67,5 +67,22 @@ public void MockDriveInfo_RootDirectory_ShouldReturnTheDirectoryBase()
// Assert
Assert.AreEqual(expectedDirectory, actualDirectory.FullName);
}
+
+ [TestCase("c:","c:\\")]
+ [TestCase("C:","C:\\")]
+ [TestCase("d:","d:\\")]
+ [TestCase("e:","e:\\")]
+ [TestCase("f:","f:\\")]
+ public void MockDriveInfo_ToString_ShouldReturnTheDrivePath(string path, string expectedPath)
+ {
+ // Arrange
+ var directoryPath = XFS.Path(path);
+
+ // Act
+ var mockDriveInfo = new MockDriveInfo(new MockFileSystem(), directoryPath);
+
+ // Assert
+ Assert.AreEqual(expectedPath, mockDriveInfo.ToString());
+ }
}
}
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileAppendAllTextTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileAppendAllTextTests.cs
index 8cc5c85f2..50c1defbf 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileAppendAllTextTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileAppendAllTextTests.cs
@@ -143,5 +143,16 @@ public void MockFile_AppendAllText_ShouldPersistNewTextWithCustomEncoding()
expected,
file.ReadAllBytes(path));
}
+
+ [Test]
+ public void MockFile_AppendAllText_ShouldWorkWithRelativePath()
+ {
+ var file = "file.txt";
+ var fileSystem = new MockFileSystem();
+
+ fileSystem.File.AppendAllText(file, "Foo");
+
+ Assert.That(fileSystem.File.Exists(file));
+ }
}
}
\ No newline at end of file
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileCopyTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileCopyTests.cs
index c41b353d5..f351c5757 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileCopyTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileCopyTests.cs
@@ -48,6 +48,28 @@ public void MockFile_Copy_ShouldCloneContents()
Assert.AreEqual("Original", mockFileSystem.File.ReadAllText(destFileName));
}
+ [Test]
+ public void MockFile_Copy_ShouldCloneBinaryContents()
+ {
+ var sourceFileName = XFS.Path(@"c:\source\demo.bin");
+ var destFileName = XFS.Path(@"c:\source\demo_copy.bin");
+
+ byte[] original = new byte[] { 0xC0 };
+ var mockFileSystem = new MockFileSystem();
+ mockFileSystem.AddFile(sourceFileName, new MockFileData(original));
+ mockFileSystem.File.Copy(sourceFileName, destFileName);
+
+ using (var stream = mockFileSystem.File.Open(sourceFileName, FileMode.Open, FileAccess.ReadWrite))
+ {
+ var binaryWriter = new System.IO.BinaryWriter(stream);
+
+ binaryWriter.Seek(0, SeekOrigin.Begin);
+ binaryWriter.Write("Modified");
+ }
+
+ CollectionAssert.AreEqual(original, mockFileSystem.File.ReadAllBytes(destFileName));
+ }
+
[Test]
public void MockFile_Copy_ShouldCreateFileAtNewDestination()
{
@@ -346,5 +368,18 @@ public void MockFile_Copy_ShouldThrowFileNotFoundExceptionWhenSourceDoesNotExist
Assert.Throws(action);
}
+
+ [Test]
+ public void MockFile_Copy_ShouldWorkWithRelativePaths()
+ {
+ var sourceFile = "source_file.txt";
+ var destinationFile = "destination_file.txt";
+ var fileSystem = new MockFileSystem();
+
+ fileSystem.File.Create(sourceFile).Close();
+ fileSystem.File.Copy(sourceFile, destinationFile);
+
+ Assert.That(fileSystem.File.Exists(destinationFile));
+ }
}
}
\ No newline at end of file
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileCreateTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileCreateTests.cs
index 9be6ff795..71cae6d86 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileCreateTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileCreateTests.cs
@@ -155,12 +155,12 @@ public void MockFile_Create_ShouldThrowDirectoryNotFoundExceptionIfCreatingAndPa
{
// Arrange
var fileSystem = new MockFileSystem();
+ var file = XFS.Path("C:\\path\\NotFound.ext");
// Act
- TestDelegate action = () => fileSystem.File.Create("C:\\Path\\NotFound.ext");
+ TestDelegate action = () => fileSystem.File.Create(file);
// Assert
- Assert.IsFalse(fileSystem.Directory.Exists("C:\\path"));
var exception = Assert.Throws(action);
Assert.That(exception.Message, Does.StartWith("Could not find a part of the path"));
}
@@ -279,5 +279,16 @@ public void MockFile_Create_EncryptedOption_EncryptsFileWhenStreamIsClose()
Assert.IsTrue(fileInfo.Attributes.HasFlag(FileAttributes.Encrypted));
}
#endif
+
+ [Test]
+ public void MockFile_Create_ShouldWorkWithRelativePath()
+ {
+ var relativeFile = "file.txt";
+ var fileSystem = new MockFileSystem();
+
+ fileSystem.File.Create(relativeFile).Close();
+
+ Assert.That(fileSystem.File.Exists(relativeFile));
+ }
}
}
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileDeleteTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileDeleteTests.cs
index c5a1e9c01..6f9fd93fc 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileDeleteTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileDeleteTests.cs
@@ -1,6 +1,7 @@
namespace System.IO.Abstractions.TestingHelpers.Tests
{
- using NUnit.Framework;
+ using System.Collections.Generic;
+ using NUnit.Framework;
using XFS = MockUnixSupport;
@@ -10,7 +11,7 @@ public class MockFileDeleteTests
public void MockFile_Delete_ShouldDeleteFile()
{
var fileSystem = new MockFileSystem();
- var path = XFS.Path("C:\\test");
+ var path = XFS.Path("C:\\some_folder\\test");
var directory = fileSystem.Path.GetDirectoryName(path);
fileSystem.AddFile(path, new MockFileData("Bla"));
@@ -35,5 +36,28 @@ public void MockFile_Delete_ShouldThrowArgumentExceptionIfPathContainsOnlyWhites
// Assert
Assert.Throws(action);
}
+
+ [Test]
+ public void MockFile_Delete_ShouldThrowDirectoryNotFoundExceptionIfParentFolderAbsent()
+ {
+ var fileSystem = new MockFileSystem();
+ var path = XFS.Path("C:\\test\\somefile.txt");
+
+ Assert.Throws(() => fileSystem.File.Delete(path));
+ }
+
+ [Test]
+ public void MockFile_Delete_ShouldSilentlyReturnIfNonExistingFileInExistingFolder()
+ {
+ var fileSystem = new MockFileSystem(new Dictionary()
+ {
+ { XFS.Path("C:\\temp\\exist.txt"), new MockFileData("foobar") },
+ });
+
+ string filePath = XFS.Path("C:\\temp\\somefile.txt");
+
+ // Delete() returns void, so there is nothing to check here beside absense of an exception
+ Assert.DoesNotThrow(() => fileSystem.File.Delete(filePath));
+ }
}
}
\ No newline at end of file
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileExistsTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileExistsTests.cs
index 868c249ba..3a4b37f1f 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileExistsTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileExistsTests.cs
@@ -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
{
- { 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
{
- { 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
{
- { 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
+ {
+ { 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);
@@ -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]
@@ -78,14 +94,12 @@ public void MockFile_Exists_ShouldReturnFalseForDirectories()
// Arrange
var fileSystem = new MockFileSystem(new Dictionary
{
- { 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);
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs
index e75cb3cec..c3b2a03b6 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs
@@ -167,7 +167,7 @@ public void MockFileInfo_IsReadOnly_ShouldSetReadOnlyAttributeOfFileInMemoryFile
[Test]
public void MockFileInfo_IsReadOnly_ShouldSetNotReadOnlyAttributeOfFileInMemoryFileSystem()
{
- var fileData = new MockFileData("Demo text content") {Attributes = FileAttributes.ReadOnly};
+ var fileData = new MockFileData("Demo text content") { Attributes = FileAttributes.ReadOnly };
var fileSystem = new MockFileSystem(new Dictionary
{
{ XFS.Path(@"c:\a.txt"), fileData }
@@ -210,7 +210,7 @@ public void MockFileInfo_OpenWrite_ShouldAddDataToFileInMemoryFileSystem()
{ XFS.Path(@"c:\a.txt"), fileData }
});
var fileInfo = new MockFileInfo(fileSystem, XFS.Path(@"c:\a.txt"));
- var bytesToAdd = new byte[] {65, 66, 67, 68, 69};
+ var bytesToAdd = new byte[] { 65, 66, 67, 68, 69 };
using (var file = fileInfo.OpenWrite())
@@ -491,6 +491,22 @@ public void MockFileInfo_CopyTo_ThrowsExceptionIfSourceDoesntExist()
Assert.Throws(action);
}
+ [TestCase(@"..\..\..\c.txt")]
+ [TestCase(@"c:\a\b\c.txt")]
+ [TestCase(@"c:\a\c.txt")]
+ [TestCase(@"c:\c.txt")]
+ public void MockFileInfo_ToString_ShouldReturnOriginalFilePath(string path)
+ {
+ //Arrange
+ var filePath = XFS.Path(path);
+
+ //Act
+ var mockFileInfo = new MockFileInfo(new MockFileSystem(), filePath);
+
+ //Assert
+ Assert.AreEqual(filePath, mockFileInfo.ToString());
+ }
+
#if NET40
[Test]
public void MockFileInfo_Replace_ShouldReplaceFileContents()
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileOpenTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileOpenTests.cs
index 5e7a065a1..2042f1b34 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileOpenTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileOpenTests.cs
@@ -249,14 +249,25 @@ public void MockFile_Open_ShouldThrowDirectoryNotFoundExceptionIfFileModeCreateA
{
// Arrange
var fileSystem = new MockFileSystem();
+ var file = XFS.Path("C:\\path\\NotFound.ext");
// Act
- TestDelegate action = () => fileSystem.File.Open("C:\\Path\\NotFound.ext", FileMode.Create);
+ TestDelegate action = () => fileSystem.File.Open(file, FileMode.Create);
// Assert
- Assert.IsFalse(fileSystem.Directory.Exists("C:\\path"));
var exception = Assert.Throws(action);
Assert.That(exception.Message, Does.StartWith("Could not find a part of the path"));
}
+
+ [Test]
+ public void MockFile_OpenWrite_ShouldWorkWithRelativePath()
+ {
+ var file = "file.txt";
+ var fileSystem = new MockFileSystem();
+
+ fileSystem.File.OpenWrite(file).Close();
+
+ Assert.That(fileSystem.File.Exists(file));
+ }
}
}
\ No newline at end of file
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileStreamTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileStreamTests.cs
index b2a14abfb..89fe72551 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileStreamTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileStreamTests.cs
@@ -28,8 +28,10 @@ public void MockFileStream_Flush_WritesByteToFile()
[Test]
public void MockFileStream_Dispose_ShouldNotResurrectFile()
{
+ // path in this test case is a subject to Directory.GetParent(path) Linux issue
+ // https://github.com/System-IO-Abstractions/System.IO.Abstractions/issues/395
var fileSystem = new MockFileSystem();
- var path = XFS.Path("C:\\test");
+ var path = XFS.Path("C:\\some_folder\\test");
var directory = fileSystem.Path.GetDirectoryName(path);
fileSystem.AddFile(path, new MockFileData("Bla"));
var stream = fileSystem.File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Delete);
@@ -104,5 +106,20 @@ public void MockFileStream_Dispose_MultipleCallsDontThrow()
// Assert
Assert.DoesNotThrow(() => stream.Dispose());
}
+
+ [Test]
+ public void MockFileStream_Dispose_OperationsAfterDisposeThrow()
+ {
+ var fileSystem = new MockFileSystem();
+ var path = XFS.Path("C:\\test");
+ fileSystem.AddFile(path, new MockFileData(new byte[0]));
+ var stream = fileSystem.FileInfo.FromFileName(path).OpenWrite();
+
+ // Act
+ stream.Dispose();
+
+ // Assert
+ Assert.Throws(() => stream.WriteByte(0));
+ }
}
}
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemTests.cs
index 6ddcd4fba..108ef2fe7 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemTests.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -16,7 +17,7 @@ public void MockFileSystem_GetFile_ShouldReturnNullWhenFileIsNotRegistered()
var fileSystem = new MockFileSystem(new Dictionary
{
{ @"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");
@@ -31,7 +32,7 @@ public void MockFileSystem_GetFile_ShouldReturnFileRegisteredInConstructor()
var fileSystem = new MockFileSystem(new Dictionary
{
{ @"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");
@@ -40,13 +41,14 @@ 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
{
{ @"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");
@@ -54,15 +56,47 @@ public void MockFileSystem_GetFile_ShouldReturnFileRegisteredInConstructorWhenPa
Assert.AreEqual(file1, result);
}
+ [Test]
+ [UnixOnly(UnixSpecifics.CaseSensitivity)]
+ public void MockFileSystem_GetFile_ShouldNotReturnFileRegisteredInConstructorWhenPathsDifferByCase()
+ {
+ var fileSystem = new MockFileSystem(new Dictionary
+ {
+ { "/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
{
- { @"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.");
}
@@ -70,7 +104,7 @@ public void MockFileSystem_AddFile_ShouldHandleNullFileDataAsEmpty()
[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
{
@@ -156,6 +190,7 @@ public void MockFileSystem_AddFile_ShouldMatchCapitalization_PerfectMatch()
}
[Test]
+ [WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockFileSystem_AddFile_ShouldMatchCapitalization_PartialMatch()
{
var fileSystem = new MockFileSystem();
@@ -174,6 +209,7 @@ public void MockFileSystem_AddFile_ShouldMatchCapitalization_PartialMatch()
}
[Test]
+ [WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
public void MockFileSystem_AddFile_ShouldMatchCapitalization_PartialMatch_FurtherLeft()
{
var fileSystem = new MockFileSystem();
@@ -292,5 +328,51 @@ public void MockFileSystem_GetFiles_ThrowsArgumentExceptionForInvalidCharacters(
// Assert
Assert.Throws(getFilesWithInvalidCharacterInPath);
}
+
+ [Test]
+ [TestCase(null)]
+ [TestCase(@"C:\somepath")]
+ public void MockFileSystem_DefaultState_CurrentDirectoryExists(string currentDirectory)
+ {
+ var fs = new MockFileSystem(null, currentDirectory);
+
+ var actualCurrentDirectory = fs.DirectoryInfo.FromDirectoryName(".");
+
+ Assert.IsTrue(actualCurrentDirectory.Exists);
+ }
+
+ [Test]
+ public void MockFileSystem_FileSystemWatcher_ShouldBeAssignable()
+ {
+ var path = XFS.Path(@"C:\root");
+ var fileSystem = new MockFileSystem {FileSystemWatcher = new TestFileSystemWatcherFactory()};
+ var watcher = fileSystem.FileSystemWatcher.FromPath(path);
+ Assert.AreEqual(path, watcher.Path);
+ }
+
+ private class TestFileSystemWatcherFactory : IFileSystemWatcherFactory
+ {
+ public FileSystemWatcherBase CreateNew() => new TestFileSystemWatcher(null);
+ public FileSystemWatcherBase FromPath(string path) => new TestFileSystemWatcher(path);
+ }
+
+ private class TestFileSystemWatcher : FileSystemWatcherBase
+ {
+ public TestFileSystemWatcher(string path) => Path = path;
+ public override string Path { get; set; }
+ public override bool IncludeSubdirectories { get; set; }
+ public override bool EnableRaisingEvents { get; set; }
+ public override string Filter { get; set; }
+ public override int InternalBufferSize { get; set; }
+ public override NotifyFilters NotifyFilter { get; set; }
+#if NET40
+ public override ISite Site { get; set; }
+ public override ISynchronizeInvoke SynchronizingObject { get; set; }
+ public override void BeginInit() {}
+ public override void EndInit() {}
+#endif
+ public override WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType) => default(WaitForChangedResult);
+ public override WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType, int timeout) => default(WaitForChangedResult);
+ }
}
}
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemWatcherFactoryTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemWatcherFactoryTests.cs
index 53cc83ec5..49696508a 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemWatcherFactoryTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileSystemWatcherFactoryTests.cs
@@ -1,8 +1,5 @@
using NUnit.Framework;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using XFS = System.IO.Abstractions.TestingHelpers.MockUnixSupport;
namespace System.IO.Abstractions.TestingHelpers.Tests
{
@@ -10,43 +7,18 @@ namespace System.IO.Abstractions.TestingHelpers.Tests
public class MockFileSystemWatcherFactoryTests
{
[Test]
- public void MockFileSystemWatcherFactory_CreateNew_ShouldReturnNonNullMockWatcher()
+ public void MockFileSystemWatcherFactory_CreateNew_ShouldThrowNotImplementedException()
{
- // Arrange
var factory = new MockFileSystemWatcherFactory();
-
- // Act
- var result = factory.CreateNew();
-
- // Assert
- Assert.IsNotNull(result);
+ Assert.Throws(() => factory.CreateNew());
}
[Test]
- public void MockFileSystemWatcherFactory_FromPath_ShouldReturnNonNullMockWatcher()
+ public void MockFileSystemWatcherFactory_FromPath_ShouldThrowNotImplementedException()
{
- // Arrange
+ var path = XFS.Path(@"y:\test");
var factory = new MockFileSystemWatcherFactory();
-
- // Act
- var result = factory.FromPath(@"y:\test");
-
- // Assert
- Assert.IsNotNull(result);
- }
-
- [Test]
- public void MockFileSystemWatcherFactory_FromPath_ShouldReturnWatcherForSpecifiedPath()
- {
- // Arrange
- const string path = @"z:\test";
- var factory = new MockFileSystemWatcherFactory();
-
- // Act
- var result = factory.FromPath(path);
-
- // Assert
- Assert.AreEqual(path, result.Path);
+ Assert.Throws(() => factory.FromPath(path));
}
}
}
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockFileTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockFileTests.cs
index 2468c9824..d26a382bd 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockFileTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockFileTests.cs
@@ -482,9 +482,14 @@ public void MockFile_Delete_Should_RemoveFiles()
[Test]
public void MockFile_Delete_No_File_Does_Nothing()
- {
- string filePath = XFS.Path(@"c:\something\demo.txt");
- var fileSystem = new MockFileSystem();
+ {
+ var fileSystem = new MockFileSystem(new Dictionary()
+ {
+ { XFS.Path(@"c:\something\exist.txt"), new MockFileData("Demo text content") },
+ });
+
+ string filePath = XFS.Path(@"c:\something\not_exist.txt");
+
fileSystem.File.Delete(filePath);
}
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/MockUnixSupportTests.cs b/System.IO.Abstractions.TestingHelpers.Tests/MockUnixSupportTests.cs
index 30dd6c0de..2641e431b 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/MockUnixSupportTests.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/MockUnixSupportTests.cs
@@ -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\"));
}
}
}
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/System.IO.Abstractions.TestingHelpers.Tests.csproj b/System.IO.Abstractions.TestingHelpers.Tests/System.IO.Abstractions.TestingHelpers.Tests.csproj
index ab213d6ef..2b48a0d01 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/System.IO.Abstractions.TestingHelpers.Tests.csproj
+++ b/System.IO.Abstractions.TestingHelpers.Tests/System.IO.Abstractions.TestingHelpers.Tests.csproj
@@ -1,6 +1,7 @@
- net40;netcoreapp2.0
+ netcoreapp2.0
+ $(TargetFrameworks);net40
0.0.0.1
The unit tests for our pre-built mocks
@@ -10,6 +11,7 @@
System.IO.Abstractions.TestingHelpers.Tests
../StrongName.snk
false
+ true
Full
@@ -39,13 +41,13 @@
-
-
+
+
-
-
+
+
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/UnixSpecifics.cs b/System.IO.Abstractions.TestingHelpers.Tests/UnixSpecifics.cs
index 6e81e34c8..bf7cd4f52 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/UnixSpecifics.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/UnixSpecifics.cs
@@ -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";
}
}
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/WindowsOnlyAttribute.cs b/System.IO.Abstractions.TestingHelpers.Tests/WindowsOnlyAttribute.cs
index d14431f3f..49be416ed 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/WindowsOnlyAttribute.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/WindowsOnlyAttribute.cs
@@ -16,7 +16,7 @@ public WindowsOnlyAttribute(string reason)
public void BeforeTest(ITest test)
{
- if (MockUnixSupport.IsUnixPlatform())
+ if (!MockUnixSupport.IsWindowsPlatform())
{
Assert.Inconclusive(reason);
}
diff --git a/System.IO.Abstractions.TestingHelpers.Tests/WindowsSpecifics.cs b/System.IO.Abstractions.TestingHelpers.Tests/WindowsSpecifics.cs
index a44dea526..86bde580e 100644
--- a/System.IO.Abstractions.TestingHelpers.Tests/WindowsSpecifics.cs
+++ b/System.IO.Abstractions.TestingHelpers.Tests/WindowsSpecifics.cs
@@ -9,5 +9,7 @@ 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 CaseInsensitivity = "Paths are case-insensitive on Windows";
}
}
diff --git a/System.IO.Abstractions.TestingHelpers/IMockFileDataAccessor.cs b/System.IO.Abstractions.TestingHelpers/IMockFileDataAccessor.cs
index fefb8ede4..6c2c6350a 100644
--- a/System.IO.Abstractions.TestingHelpers/IMockFileDataAccessor.cs
+++ b/System.IO.Abstractions.TestingHelpers/IMockFileDataAccessor.cs
@@ -54,6 +54,8 @@ public interface IMockFileDataAccessor
///
IEnumerable AllDirectories { get; }
+ StringOperations StringOperations { get; }
+
FileBase File { get; }
DirectoryBase Directory { get; }
IFileInfoFactory FileInfo {get; }
diff --git a/System.IO.Abstractions.TestingHelpers/MockDirectory.cs b/System.IO.Abstractions.TestingHelpers/MockDirectory.cs
index 250b9d541..c38d0ce4a 100644
--- a/System.IO.Abstractions.TestingHelpers/MockDirectory.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockDirectory.cs
@@ -11,17 +11,19 @@ namespace System.IO.Abstractions.TestingHelpers
[Serializable]
public class MockDirectory : DirectoryBase
{
- private readonly FileBase fileBase;
-
private readonly IMockFileDataAccessor mockFileDataAccessor;
-
private string currentDirectory;
- public MockDirectory(IMockFileDataAccessor mockFileDataAccessor, FileBase fileBase, string currentDirectory) : base(mockFileDataAccessor?.FileSystem)
+ // This constructor is retained to avoid breaking change
+ public MockDirectory(IMockFileDataAccessor mockFileDataAccessor, FileBase fileBase, string currentDirectory) :
+ this(mockFileDataAccessor, currentDirectory)
+ {
+ }
+
+ public MockDirectory(IMockFileDataAccessor mockFileDataAccessor, string currentDirectory) : base(mockFileDataAccessor?.FileSystem)
{
this.currentDirectory = currentDirectory;
this.mockFileDataAccessor = mockFileDataAccessor ?? throw new ArgumentNullException(nameof(mockFileDataAccessor));
- this.fileBase = fileBase;
}
public override DirectoryInfoBase CreateDirectory(string path)
@@ -35,6 +37,7 @@ public override DirectoryInfoBase CreateDirectory(string path, DirectorySecurity
return CreateDirectoryInternal(path, directorySecurity);
}
#endif
+
private DirectoryInfoBase CreateDirectoryInternal(string path, DirectorySecurity directorySecurity)
{
if (path == null)
@@ -74,7 +77,7 @@ public override void Delete(string path, bool recursive)
path = mockFileDataAccessor.Path.GetFullPath(path).TrimSlashes();
var affectedPaths = mockFileDataAccessor
.AllPaths
- .Where(p => p.StartsWith(path, StringComparison.OrdinalIgnoreCase))
+ .Where(p => mockFileDataAccessor.StringOperations.StartsWith(p, path))
.ToList();
if (!affectedPaths.Any())
@@ -99,7 +102,7 @@ public override bool Exists(string path)
{
path = path.TrimSlashes();
path = mockFileDataAccessor.Path.GetFullPath(path);
- return mockFileDataAccessor.AllDirectories.Any(p => p.Equals(path, StringComparison.OrdinalIgnoreCase));
+ return mockFileDataAccessor.AllDirectories.Any(p => mockFileDataAccessor.StringOperations.Equals(p, path));
}
catch (Exception)
{
@@ -128,12 +131,12 @@ public override DirectorySecurity GetAccessControl(string path, AccessControlSec
public override DateTime GetCreationTime(string path)
{
- return fileBase.GetCreationTime(path);
+ return mockFileDataAccessor.File.GetCreationTime(path);
}
public override DateTime GetCreationTimeUtc(string path)
{
- return fileBase.GetCreationTimeUtc(path);
+ return mockFileDataAccessor.File.GetCreationTimeUtc(path);
}
public override string GetCurrentDirectory()
@@ -174,45 +177,55 @@ public override string[] GetFiles(string path, string searchPattern)
}
public override string[] GetFiles(string path, string searchPattern, SearchOption searchOption)
+ {
+ return GetFilesInternal(mockFileDataAccessor.AllFiles, path, searchPattern, searchOption);
+ }
+
+ private string[] GetFilesInternal(
+ IEnumerable files,
+ string path,
+ string searchPattern,
+ SearchOption searchOption)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
-
+
if (path.Any(c => Path.GetInvalidPathChars().Contains(c)))
{
throw new ArgumentException("Invalid character(s) in path", nameof(path));
}
+ CheckSearchPattern(searchPattern);
+ path = path.TrimSlashes();
+ path = path.NormalizeSlashes();
+
if (!Exists(path))
{
- throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, StringResources.Manager.GetString("COULD_NOT_FIND_PART_OF_PATH_EXCEPTION"), path));
+ throw new DirectoryNotFoundException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ StringResources.Manager.GetString("COULD_NOT_FIND_PART_OF_PATH_EXCEPTION"),
+ path));
}
- return GetFilesInternal(mockFileDataAccessor.AllFiles, path, searchPattern, searchOption);
- }
-
- private string[] GetFilesInternal(IEnumerable files, string path, string searchPattern, SearchOption searchOption)
- {
- CheckSearchPattern(searchPattern);
- path = path.TrimSlashes();
path = EnsureAbsolutePath(path);
- if (!path.EndsWith(Path.DirectorySeparatorChar.ToString())
- && !path.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
+ if (!path.EndsWith(Path.DirectorySeparatorChar.ToString()))
{
path += Path.DirectorySeparatorChar;
}
- bool isUnix = XFS.IsUnixPlatform();
+ var isUnix = XFS.IsUnixPlatform();
- string allDirectoriesPattern = isUnix
+ var allDirectoriesPattern = isUnix
? @"([^<>:""/|?*]*/)*"
: @"([^<>:""/\\|?*]*\\)*";
string fileNamePattern;
string pathPatternSpecial = null;
+
if (searchPattern == "*")
{
fileNamePattern = isUnix ? @"[^/]*?/?" : @"[^\\]*?\\?";
@@ -244,22 +257,9 @@ private string[] GetFilesInternal(IEnumerable files, string path, string
searchOption == SearchOption.AllDirectories ? allDirectoriesPattern : string.Empty,
fileNamePattern);
-
return files
- .Where(p =>
- {
- if (Regex.IsMatch(p, pathPattern))
- {
- return true;
- }
-
- if (pathPatternSpecial != null && Regex.IsMatch(p, pathPatternSpecial))
- {
- return true;
- }
-
- return false;
- })
+ .Where(p => Regex.IsMatch(p, pathPattern)
+ || (pathPatternSpecial != null && Regex.IsMatch(p, pathPatternSpecial)))
.ToArray();
}
@@ -278,22 +278,22 @@ public override string[] GetFileSystemEntries(string path, string searchPattern)
public override DateTime GetLastAccessTime(string path)
{
- return fileBase.GetLastAccessTime(path);
+ return mockFileDataAccessor.File.GetLastAccessTime(path);
}
public override DateTime GetLastAccessTimeUtc(string path)
{
- return fileBase.GetLastAccessTimeUtc(path);
+ return mockFileDataAccessor.File.GetLastAccessTimeUtc(path);
}
public override DateTime GetLastWriteTime(string path)
{
- return fileBase.GetLastWriteTime(path);
+ return mockFileDataAccessor.File.GetLastWriteTime(path);
}
public override DateTime GetLastWriteTimeUtc(string path)
{
- return fileBase.GetLastWriteTimeUtc(path);
+ return mockFileDataAccessor.File.GetLastWriteTimeUtc(path);
}
#if NET40
@@ -302,7 +302,7 @@ public override string[] GetLogicalDrives()
return mockFileDataAccessor
.AllDirectories
.Select(d => new MockDirectoryInfo(mockFileDataAccessor, d).Root.FullName)
- .Select(r => r.ToLowerInvariant())
+ .Select(r => mockFileDataAccessor.StringOperations.ToUpper(r))
.Distinct()
.ToArray();
}
@@ -320,19 +320,22 @@ public override DirectoryInfoBase GetParent(string path)
throw new ArgumentException(StringResources.Manager.GetString("PATH_CANNOT_BE_THE_EMPTY_STRING_OR_ALL_WHITESPACE"), "path");
}
- if (MockPath.HasIllegalCharacters(path, false))
+ if (mockFileDataAccessor.PathVerifier.HasIllegalCharacters(path, false))
{
throw new ArgumentException("Path contains invalid path characters.", "path");
}
var absolutePath = mockFileDataAccessor.Path.GetFullPath(path);
- var sepAsString = string.Format(CultureInfo.InvariantCulture, "{0}", mockFileDataAccessor.Path.DirectorySeparatorChar);
-
+ var sepAsString = mockFileDataAccessor.Path.DirectorySeparatorChar.ToString();
var lastIndex = 0;
+
if (absolutePath != sepAsString)
{
- var startIndex = absolutePath.EndsWith(sepAsString, StringComparison.OrdinalIgnoreCase) ? absolutePath.Length - 1 : absolutePath.Length;
+ var startIndex = mockFileDataAccessor.StringOperations.EndsWith(absolutePath, sepAsString)
+ ? absolutePath.Length - 1
+ : absolutePath.Length;
lastIndex = absolutePath.LastIndexOf(mockFileDataAccessor.Path.DirectorySeparatorChar, startIndex - 1);
+
if (lastIndex < 0)
{
return null;
@@ -340,13 +343,25 @@ public override DirectoryInfoBase GetParent(string path)
}
var parentPath = absolutePath.Substring(0, lastIndex);
+
if (string.IsNullOrEmpty(parentPath))
{
+ // On the Unix platform, the parent of a path consisting of a slash followed by
+ // non-slashes is the root, '/'.
+ if (XFS.IsUnixPlatform())
+ {
+ absolutePath = absolutePath.TrimSlashes();
+
+ if (absolutePath.Length > 1 && absolutePath.LastIndexOf(mockFileDataAccessor.Path.DirectorySeparatorChar) == 0)
+ {
+ return new MockDirectoryInfo(mockFileDataAccessor, mockFileDataAccessor.Path.DirectorySeparatorChar.ToString());
+ }
+ }
+
return null;
}
- var parent = new MockDirectoryInfo(mockFileDataAccessor, parentPath);
- return parent;
+ return new MockDirectoryInfo(mockFileDataAccessor, parentPath);
}
public override void Move(string sourceDirName, string destDirName)
@@ -354,14 +369,15 @@ public override void Move(string sourceDirName, string destDirName)
var fullSourcePath = mockFileDataAccessor.Path.GetFullPath(sourceDirName).TrimSlashes();
var fullDestPath = mockFileDataAccessor.Path.GetFullPath(destDirName).TrimSlashes();
- if (string.Equals(fullSourcePath, fullDestPath, StringComparison.OrdinalIgnoreCase))
+ if (mockFileDataAccessor.StringOperations.Equals(fullSourcePath, fullDestPath))
{
throw new IOException("Source and destination path must be different.");
}
var sourceRoot = mockFileDataAccessor.Path.GetPathRoot(fullSourcePath);
var destinationRoot = mockFileDataAccessor.Path.GetPathRoot(fullDestPath);
- if (!string.Equals(sourceRoot, destinationRoot, StringComparison.OrdinalIgnoreCase))
+
+ if (!mockFileDataAccessor.StringOperations.Equals(sourceRoot, destinationRoot))
{
throw new IOException("Source and destination path must have identical roots. Move will not work across volumes.");
}
@@ -395,12 +411,12 @@ public override void SetAccessControl(string path, DirectorySecurity directorySe
public override void SetCreationTime(string path, DateTime creationTime)
{
- fileBase.SetCreationTime(path, creationTime);
+ mockFileDataAccessor.File.SetCreationTime(path, creationTime);
}
public override void SetCreationTimeUtc(string path, DateTime creationTimeUtc)
{
- fileBase.SetCreationTimeUtc(path, creationTimeUtc);
+ mockFileDataAccessor.File.SetCreationTimeUtc(path, creationTimeUtc);
}
public override void SetCurrentDirectory(string path)
@@ -410,22 +426,22 @@ public override void SetCurrentDirectory(string path)
public override void SetLastAccessTime(string path, DateTime lastAccessTime)
{
- fileBase.SetLastAccessTime(path, lastAccessTime);
+ mockFileDataAccessor.File.SetLastAccessTime(path, lastAccessTime);
}
public override void SetLastAccessTimeUtc(string path, DateTime lastAccessTimeUtc)
{
- fileBase.SetLastAccessTimeUtc(path, lastAccessTimeUtc);
+ mockFileDataAccessor.File.SetLastAccessTimeUtc(path, lastAccessTimeUtc);
}
public override void SetLastWriteTime(string path, DateTime lastWriteTime)
{
- fileBase.SetLastWriteTime(path, lastWriteTime);
+ mockFileDataAccessor.File.SetLastWriteTime(path, lastWriteTime);
}
public override void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc)
{
- fileBase.SetLastWriteTimeUtc(path, lastWriteTimeUtc);
+ mockFileDataAccessor.File.SetLastWriteTimeUtc(path, lastWriteTimeUtc);
}
public override IEnumerable EnumerateDirectories(string path)
@@ -445,17 +461,10 @@ public override IEnumerable EnumerateDirectories(string path, string sea
public override IEnumerable EnumerateDirectories(string path, string searchPattern, SearchOption searchOption)
{
mockFileDataAccessor.PathVerifier.IsLegalAbsoluteOrRelative(path, "path");
-
path = path.TrimSlashes();
path = mockFileDataAccessor.Path.GetFullPath(path);
-
- if (!Exists(path))
- {
- throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, StringResources.Manager.GetString("COULD_NOT_FIND_PART_OF_PATH_EXCEPTION"), path));
- }
-
- var dirs = GetFilesInternal(mockFileDataAccessor.AllDirectories, path, searchPattern, searchOption);
- return dirs.Where(p => string.Compare(p, path, StringComparison.OrdinalIgnoreCase) != 0);
+ return GetFilesInternal(mockFileDataAccessor.AllDirectories, path, searchPattern, searchOption)
+ .Where(p => !mockFileDataAccessor.StringOperations.Equals(p, path));
}
public override IEnumerable EnumerateFiles(string path)
@@ -501,7 +510,7 @@ private string EnsureAbsolutePath(string path)
: Path.Combine(GetCurrentDirectory(), path);
}
- static void CheckSearchPattern(string searchPattern)
+ private void CheckSearchPattern(string searchPattern)
{
if (searchPattern == null)
{
@@ -511,15 +520,17 @@ static void CheckSearchPattern(string searchPattern)
const string TWO_DOTS = "..";
Func createException = () => new ArgumentException(@"Search pattern cannot contain "".."" to move up directories and can be contained only internally in file/directory names, as in ""a..b"".", searchPattern);
- if (searchPattern.EndsWith(TWO_DOTS, StringComparison.OrdinalIgnoreCase))
+ if (mockFileDataAccessor.StringOperations.EndsWith(searchPattern, TWO_DOTS))
{
throw createException();
}
- int position;
- if ((position = searchPattern.IndexOf(TWO_DOTS, StringComparison.OrdinalIgnoreCase)) >= 0)
+ var position = mockFileDataAccessor.StringOperations.IndexOf(searchPattern, TWO_DOTS);
+
+ if (position >= 0)
{
var characterAfterTwoDots = searchPattern[position + 2];
+
if (characterAfterTwoDots == Path.DirectorySeparatorChar || characterAfterTwoDots == Path.AltDirectorySeparatorChar)
{
throw createException();
diff --git a/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs b/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs
index 90f2ce9a1..0a9b651bc 100644
--- a/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.Globalization;
using System.Linq;
using System.Security.AccessControl;
@@ -10,6 +9,7 @@ public class MockDirectoryInfo : DirectoryInfoBase
{
private readonly IMockFileDataAccessor mockFileDataAccessor;
private readonly string directoryPath;
+ private readonly string originalPath;
///
/// Initializes a new instance of the class.
@@ -21,6 +21,7 @@ public MockDirectoryInfo(IMockFileDataAccessor mockFileDataAccessor, string dire
{
this.mockFileDataAccessor = mockFileDataAccessor ?? throw new ArgumentNullException(nameof(mockFileDataAccessor));
+ originalPath = directoryPath;
directoryPath = mockFileDataAccessor.Path.GetFullPath(directoryPath);
this.directoryPath = directoryPath.TrimSlashes();
@@ -73,7 +74,8 @@ public override string FullName
get
{
var root = mockFileDataAccessor.Path.GetPathRoot(directoryPath);
- if (string.Equals(directoryPath, root, StringComparison.OrdinalIgnoreCase))
+
+ if (mockFileDataAccessor.StringOperations.Equals(directoryPath, root))
{
// drives have the trailing slash
return directoryPath;
@@ -283,11 +285,6 @@ public override DirectoryInfoBase Root
}
}
- public override string ToString()
- {
- return FullName;
- }
-
private MockFileData GetMockFileDataForRead()
{
return mockFileDataAccessor.GetFile(directoryPath) ?? MockFileData.NullObject;
@@ -298,5 +295,10 @@ private MockFileData GetMockFileDataForWrite()
return mockFileDataAccessor.GetFile(directoryPath)
?? throw new FileNotFoundException(StringResources.Manager.GetString("COULD_NOT_FIND_FILE_EXCEPTION"), directoryPath);
}
+
+ public override string ToString()
+ {
+ return originalPath;
+ }
}
}
diff --git a/System.IO.Abstractions.TestingHelpers/MockDriveInfo.cs b/System.IO.Abstractions.TestingHelpers/MockDriveInfo.cs
index 918c147f0..61ec413b4 100644
--- a/System.IO.Abstractions.TestingHelpers/MockDriveInfo.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockDriveInfo.cs
@@ -7,10 +7,7 @@ public class MockDriveInfo : DriveInfoBase
public MockDriveInfo(IMockFileDataAccessor mockFileDataAccessor, string name) : base(mockFileDataAccessor?.FileSystem)
{
- if (mockFileDataAccessor == null)
- {
- throw new ArgumentNullException(nameof(mockFileDataAccessor));
- }
+ this.mockFileDataAccessor = mockFileDataAccessor ?? throw new ArgumentNullException(nameof(mockFileDataAccessor));
if (name == null)
{
@@ -18,32 +15,25 @@ public MockDriveInfo(IMockFileDataAccessor mockFileDataAccessor, string name) :
}
const string DRIVE_SEPARATOR = @":\";
- if (name.Length == 1)
- {
- name = char.ToUpperInvariant(name[0]) + DRIVE_SEPARATOR;
- }
- else if (name.Length == 2 && name[1] == ':')
- {
- name = char.ToUpperInvariant(name[0]) + DRIVE_SEPARATOR;
- }
- else if (name.Length == 3 && name.EndsWith(DRIVE_SEPARATOR, StringComparison.Ordinal))
+
+ if (name.Length == 1
+ || (name.Length == 2 && name[1] == ':')
+ || (name.Length == 3 && mockFileDataAccessor.StringOperations.EndsWith(name, DRIVE_SEPARATOR)))
{
- name = char.ToUpperInvariant(name[0]) + DRIVE_SEPARATOR;
+ name = name[0] + DRIVE_SEPARATOR;
}
else
{
- MockPath.CheckInvalidPathChars(name);
+ mockFileDataAccessor.PathVerifier.CheckInvalidPathChars(name);
name = mockFileDataAccessor.Path.GetPathRoot(name);
- if (string.IsNullOrEmpty(name) || name.StartsWith(@"\\", StringComparison.Ordinal))
+ if (string.IsNullOrEmpty(name) || mockFileDataAccessor.StringOperations.StartsWith(name, @"\\"))
{
throw new ArgumentException(
@"Object must be a root directory (""C:\"") or a drive letter (""C"").");
}
}
- this.mockFileDataAccessor = mockFileDataAccessor;
-
Name = name;
IsReady = true;
}
@@ -58,11 +48,15 @@ public override DirectoryInfoBase RootDirectory
{
get
{
- var directory = mockFileDataAccessor.DirectoryInfo.FromDirectoryName(Name);
- return directory;
+ return mockFileDataAccessor.DirectoryInfo.FromDirectoryName(Name);
}
}
+ public override string ToString()
+ {
+ return Name;
+ }
+
public new long TotalFreeSpace { get; protected set; }
public new long TotalSize { get; protected set; }
public override string VolumeLabel { get; set; }
diff --git a/System.IO.Abstractions.TestingHelpers/MockDriveInfoFactory.cs b/System.IO.Abstractions.TestingHelpers/MockDriveInfoFactory.cs
index 00a8212dc..bd1596a00 100644
--- a/System.IO.Abstractions.TestingHelpers/MockDriveInfoFactory.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockDriveInfoFactory.cs
@@ -14,7 +14,7 @@ public MockDriveInfoFactory(IMockFileDataAccessor mockFileSystem)
public DriveInfoBase[] GetDrives()
{
- var driveLetters = new HashSet(new DriveEqualityComparer());
+ var driveLetters = new HashSet(new DriveEqualityComparer(mockFileSystem));
foreach (var path in mockFileSystem.AllPaths)
{
var pathRoot = mockFileSystem.Path.GetPathRoot(path);
@@ -47,12 +47,12 @@ public DriveInfoBase FromDriveName(string driveName)
private string NormalizeDriveName(string driveName)
{
- if (driveName.Length == 3 && driveName.EndsWith(@":\", StringComparison.OrdinalIgnoreCase))
+ if (driveName.Length == 3 && mockFileSystem.StringOperations.EndsWith(driveName, @":\"))
{
- return char.ToUpperInvariant(driveName[0]) + @":\";
+ return mockFileSystem.StringOperations.ToUpper(driveName[0]) + @":\";
}
- if (driveName.StartsWith(@"\\", StringComparison.OrdinalIgnoreCase))
+ if (mockFileSystem.StringOperations.StartsWith(driveName, @"\\"))
{
return null;
}
@@ -62,34 +62,27 @@ private string NormalizeDriveName(string driveName)
private class DriveEqualityComparer : IEqualityComparer
{
- public bool Equals(string x, string y)
- {
- if (ReferenceEquals(x, y))
- {
- return true;
- }
+ private readonly IMockFileDataAccessor mockFileSystem;
- if (ReferenceEquals(x, null))
- {
- return false;
- }
-
- if (ReferenceEquals(y, null))
- {
- return false;
- }
+ public DriveEqualityComparer(IMockFileDataAccessor mockFileSystem)
+ {
+ this.mockFileSystem = mockFileSystem ?? throw new ArgumentNullException(nameof(mockFileSystem));
+ }
- if (x[1] == ':' && y[1] == ':')
- {
- return char.ToUpperInvariant(x[0]) == char.ToUpperInvariant(y[0]);
- }
+ public bool Equals(string x, string y)
+ {
+ return ReferenceEquals(x, y) ||
+ (HasDrivePrefix(x) && HasDrivePrefix(y) && mockFileSystem.StringOperations.Equals(x[0], y[0]));
+ }
- return false;
+ private static bool HasDrivePrefix(string x)
+ {
+ return x != null && x.Length >= 2 && x[1] == ':';
}
public int GetHashCode(string obj)
{
- return obj.ToUpperInvariant().GetHashCode();
+ return mockFileSystem.StringOperations.ToUpper(obj).GetHashCode();
}
}
}
diff --git a/System.IO.Abstractions.TestingHelpers/MockFile.cs b/System.IO.Abstractions.TestingHelpers/MockFile.cs
index 1322e2e29..a2d24d91f 100644
--- a/System.IO.Abstractions.TestingHelpers/MockFile.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockFile.cs
@@ -10,12 +10,10 @@ namespace System.IO.Abstractions.TestingHelpers
public class MockFile : FileBase
{
private readonly IMockFileDataAccessor mockFileDataAccessor;
- private readonly MockPath mockPath;
public MockFile(IMockFileDataAccessor mockFileDataAccessor) : base(mockFileDataAccessor?.FileSystem)
{
this.mockFileDataAccessor = mockFileDataAccessor ?? throw new ArgumentNullException(nameof(mockFileDataAccessor));
- mockPath = new MockPath(mockFileDataAccessor);
}
public override void AppendAllLines(string path, IEnumerable contents)
@@ -57,12 +55,7 @@ public override void AppendAllText(string path, string contents, Encoding encodi
if (!mockFileDataAccessor.FileExists(path))
{
- var dir = mockFileDataAccessor.Path.GetDirectoryName(path);
- if (!mockFileDataAccessor.Directory.Exists(dir))
- {
- throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, StringResources.Manager.GetString("COULD_NOT_FIND_PART_OF_PATH_EXCEPTION"), path));
- }
-
+ VerifyDirectoryExists(path);
mockFileDataAccessor.AddFile(path, new MockFileData(contents, encoding));
}
else
@@ -112,11 +105,7 @@ public override void Copy(string sourceFileName, string destFileName, bool overw
throw new FileNotFoundException(string.Format(CultureInfo.InvariantCulture, StringResources.Manager.GetString("COULD_NOT_FIND_FILE_EXCEPTION"), sourceFileName));
}
- var directoryNameOfDestination = mockPath.GetDirectoryName(destFileName);
- if (!mockFileDataAccessor.Directory.Exists(directoryNameOfDestination))
- {
- throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, StringResources.Manager.GetString("COULD_NOT_FIND_PART_OF_PATH_EXCEPTION"), destFileName));
- }
+ VerifyDirectoryExists(destFileName);
var fileExists = mockFileDataAccessor.FileExists(destFileName);
if (fileExists)
@@ -155,16 +144,7 @@ private Stream CreateInternal(string path, int bufferSize, FileOptions options,
}
mockFileDataAccessor.PathVerifier.IsLegalAbsoluteOrRelative(path, nameof(path));
- var directoryPath = mockPath.GetDirectoryName(path);
-
- if (!mockFileDataAccessor.Directory.Exists(directoryPath))
- {
- throw new DirectoryNotFoundException(
- string.Format(
- CultureInfo.InvariantCulture,
- StringResources.Manager.GetString("COULD_NOT_FIND_PART_OF_PATH_EXCEPTION"),
- path));
- }
+ VerifyDirectoryExists(path);
var mockFileData = new MockFileData(new byte[0])
{
@@ -191,6 +171,11 @@ public override void Delete(string path)
{
mockFileDataAccessor.PathVerifier.IsLegalAbsoluteOrRelative(path, "path");
+ // We mimic exact behavior of the standard File.Delete() method
+ // which throws exception only if the folder does not exist,
+ // but silently returns if deleting a non-existing file in an existing folder.
+ VerifyDirectoryExists(path);
+
mockFileDataAccessor.RemoveFile(path);
}
@@ -564,15 +549,13 @@ public override void Replace(string sourceFileName, string destinationFileName,
throw new FileNotFoundException(string.Format(CultureInfo.InvariantCulture, StringResources.Manager.GetString("COULD_NOT_FIND_FILE_EXCEPTION"), destinationFileName));
}
- var mockFile = new MockFile(mockFileDataAccessor);
-
if (destinationBackupFileName != null)
{
- mockFile.Copy(destinationFileName, destinationBackupFileName, true);
+ Copy(destinationFileName, destinationBackupFileName, overwrite: true);
}
- mockFile.Delete(destinationFileName);
- mockFile.Move(sourceFileName, destinationFileName);
+ Delete(destinationFileName);
+ Move(sourceFileName, destinationFileName);
}
#endif
@@ -988,10 +971,16 @@ private void VerifyValueIsNotNull(object value, string parameterName)
private void VerifyDirectoryExists(string path)
{
- DirectoryInfoBase dir = mockFileDataAccessor.Directory.GetParent(path);
- if (!dir.Exists)
+ var pathOps = mockFileDataAccessor.Path;
+ var dir = pathOps.GetDirectoryName(pathOps.GetFullPath(path));
+
+ if (!mockFileDataAccessor.Directory.Exists(dir))
{
- throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, StringResources.Manager.GetString("COULD_NOT_FIND_PART_OF_PATH_EXCEPTION"), dir));
+ throw new DirectoryNotFoundException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ StringResources.Manager.GetString("COULD_NOT_FIND_PART_OF_PATH_EXCEPTION"),
+ path));
}
}
}
diff --git a/System.IO.Abstractions.TestingHelpers/MockFileData.cs b/System.IO.Abstractions.TestingHelpers/MockFileData.cs
index 6d433bc28..15aa84298 100644
--- a/System.IO.Abstractions.TestingHelpers/MockFileData.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockFileData.cs
@@ -96,7 +96,7 @@ public MockFileData(MockFileData template)
accessControl = template.accessControl;
Attributes = template.Attributes;
- TextContents = template.TextContents;
+ Contents = template.Contents.ToArray();
CreationTime = template.CreationTime;
LastAccessTime = template.LastAccessTime;
LastWriteTime = template.LastWriteTime;
diff --git a/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs b/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs
index 298d054be..257f3317c 100644
--- a/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs
@@ -168,7 +168,7 @@ public override FileInfoBase CopyTo(string destFileName, bool overwrite)
{
return this;
}
- new MockFile(mockFileSystem).Copy(FullName, destFileName, overwrite);
+ mockFileSystem.File.Copy(FullName, destFileName, overwrite);
return mockFileSystem.FileInfo.FromFileName(destFileName);
}
@@ -242,7 +242,7 @@ public override Stream OpenRead()
public override StreamReader OpenText()
{
- return new StreamReader(OpenRead());
+ return new StreamReader(OpenRead());
}
public override Stream OpenWrite()
@@ -296,7 +296,7 @@ public override bool IsReadOnly
set
{
if (MockFileData == null) throw new FileNotFoundException("File not found", path);
- if(value)
+ if (value)
MockFileData.Attributes |= FileAttributes.ReadOnly;
else
MockFileData.Attributes &= ~FileAttributes.ReadOnly;
@@ -311,5 +311,10 @@ public override long Length
return MockFileData.Contents.Length;
}
}
+
+ public override string ToString()
+ {
+ return path;
+ }
}
}
diff --git a/System.IO.Abstractions.TestingHelpers/MockFileStream.cs b/System.IO.Abstractions.TestingHelpers/MockFileStream.cs
index 68095d85a..7e3d2f291 100644
--- a/System.IO.Abstractions.TestingHelpers/MockFileStream.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockFileStream.cs
@@ -7,7 +7,12 @@ public class MockFileStream : MemoryStream
private readonly string path;
private readonly bool canWrite = true;
private readonly FileOptions options;
+
+#if NET40
+ private bool closed;
+#else
private bool disposed;
+#endif
public enum StreamType
{
@@ -64,8 +69,14 @@ public MockFileStream(
#if NET40
public override void Close()
{
+ if (closed)
+ {
+ return;
+ }
InternalFlush();
+ base.Close();
OnClose();
+ closed = true;
}
#else
protected override void Dispose(bool disposing)
diff --git a/System.IO.Abstractions.TestingHelpers/MockFileSystem.cs b/System.IO.Abstractions.TestingHelpers/MockFileSystem.cs
index 186dcebbe..cd3d15f64 100644
--- a/System.IO.Abstractions.TestingHelpers/MockFileSystem.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockFileSystem.cs
@@ -2,13 +2,16 @@
using System.Globalization;
using System.Linq;
using System.Reflection;
-using XFS = System.IO.Abstractions.TestingHelpers.MockUnixSupport;
namespace System.IO.Abstractions.TestingHelpers
{
+ using XFS = MockUnixSupport;
+
[Serializable]
public class MockFileSystem : IFileSystem, IMockFileDataAccessor
{
+ private const string DEFAULT_CURRENT_DIRECTORY = @"C:\";
+
private readonly IDictionary files;
[NonSerialized]
private readonly PathVerifier pathVerifier;
@@ -19,16 +22,16 @@ public MockFileSystem(IDictionary files, string currentDir
{
if (string.IsNullOrEmpty(currentDirectory))
{
- currentDirectory = IO.Path.GetTempPath();
+ currentDirectory = XFS.Path(DEFAULT_CURRENT_DIRECTORY);
}
+ StringOperations = new StringOperations(XFS.IsUnixPlatform());
pathVerifier = new PathVerifier(this);
+ this.files = new Dictionary(StringOperations.Comparer);
- this.files = new Dictionary(StringComparer.OrdinalIgnoreCase);
-
Path = new MockPath(this);
File = new MockFile(this);
- Directory = new MockDirectory(this, File, currentDirectory);
+ Directory = new MockDirectory(this, currentDirectory);
FileInfo = new MockFileInfoFactory(this);
FileStream = new MockFileStreamFactory(this);
DirectoryInfo = new MockDirectoryInfoFactory(this);
@@ -42,26 +45,23 @@ public MockFileSystem(IDictionary files, string currentDir
AddFile(entry.Key, entry.Value);
}
}
+
+ if (!FileExists(currentDirectory))
+ {
+ AddDirectory(currentDirectory);
+ }
}
+ public StringOperations StringOperations { get; }
public FileBase File { get; }
-
public DirectoryBase Directory { get; }
-
public IFileInfoFactory FileInfo { get; }
-
public IFileStreamFactory FileStream { get; }
-
public PathBase Path { get; }
-
public IDirectoryInfoFactory DirectoryInfo { get; }
-
public IDriveInfoFactory DriveInfo { get; }
-
- public IFileSystemWatcherFactory FileSystemWatcher { get; }
-
+ public IFileSystemWatcherFactory FileSystemWatcher { get; set; }
public IFileSystem FileSystem => this;
-
public PathVerifier PathVerifier => pathVerifier;
private string FixPath(string path, bool checkCaps = false)
@@ -93,7 +93,7 @@ private string GetPathWithCorrectDirectoryCapitalization(string fullPath)
if (Directory.Exists(leftHalf))
{
leftHalf = Path.GetFullPath(leftHalf).TrimSlashes();
- string baseDirectory = AllDirectories.First(dir => dir.Equals(leftHalf, StringComparison.OrdinalIgnoreCase));
+ string baseDirectory = AllDirectories.First(dir => StringOperations.Equals(dir, leftHalf));
return baseDirectory + Path.DirectorySeparatorChar + rightHalf;
}
}
@@ -145,7 +145,7 @@ public void AddFile(string path, MockFileData mockFile)
public void AddDirectory(string path)
{
var fixedPath = FixPath(path, true);
- var separator = XFS.Separator();
+ var separator = Path.DirectorySeparatorChar.ToString();
lock (files)
{
@@ -154,15 +154,15 @@ public void AddDirectory(string path)
throw new UnauthorizedAccessException(string.Format(CultureInfo.InvariantCulture, StringResources.Manager.GetString("ACCESS_TO_THE_PATH_IS_DENIED"), fixedPath));
var lastIndex = 0;
-
- bool isUnc =
- fixedPath.StartsWith(@"\\", StringComparison.OrdinalIgnoreCase) ||
- fixedPath.StartsWith(@"//", StringComparison.OrdinalIgnoreCase);
+ var isUnc =
+ StringOperations.StartsWith(fixedPath, @"\\") ||
+ StringOperations.StartsWith(fixedPath, @"//");
if (isUnc)
{
//First, confirm they aren't trying to create '\\server\'
- lastIndex = fixedPath.IndexOf(separator, 2, StringComparison.OrdinalIgnoreCase);
+ lastIndex = StringOperations.IndexOf(fixedPath, separator, 2);
+
if (lastIndex < 0)
throw new ArgumentException(@"The UNC path should be of the form \\server\share.", "path");
@@ -172,7 +172,7 @@ public void AddDirectory(string path)
*/
}
- while ((lastIndex = fixedPath.IndexOf(separator, lastIndex + 1, StringComparison.OrdinalIgnoreCase)) > -1)
+ while ((lastIndex = StringOperations.IndexOf(fixedPath, separator, lastIndex + 1)) > -1)
{
var segment = fixedPath.Substring(0, lastIndex + 1);
if (!Directory.Exists(segment))
@@ -181,7 +181,7 @@ public void AddDirectory(string path)
}
}
- var s = fixedPath.EndsWith(separator, StringComparison.OrdinalIgnoreCase) ? fixedPath : fixedPath + separator;
+ var s = StringOperations.EndsWith(fixedPath, separator) ? fixedPath : fixedPath + separator;
SetEntry(s, new MockDirectoryData());
}
}
@@ -227,12 +227,12 @@ public void MoveDirectory(string sourcePath, string destPath)
lock (files)
{
var affectedPaths = files.Keys
- .Where(p => p.StartsWith(sourcePath, StringComparison.OrdinalIgnoreCase))
+ .Where(p => StringOperations.StartsWith(p, sourcePath))
.ToList();
foreach(var path in affectedPaths)
{
- var newPath = path.Replace(sourcePath, destPath, StringComparison.OrdinalIgnoreCase);
+ var newPath = StringOperations.Replace(path, sourcePath, destPath);
files[newPath] = files[path];
files.Remove(path);
}
diff --git a/System.IO.Abstractions.TestingHelpers/MockFileSystemWatcher.cs b/System.IO.Abstractions.TestingHelpers/MockFileSystemWatcher.cs
deleted file mode 100644
index a1204412d..000000000
--- a/System.IO.Abstractions.TestingHelpers/MockFileSystemWatcher.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using System.ComponentModel;
-
-namespace System.IO.Abstractions.TestingHelpers
-{
- public class MockFileSystemWatcher : FileSystemWatcherBase
- {
- public override bool IncludeSubdirectories { get; set; }
- public override bool EnableRaisingEvents { get; set; }
- public override string Filter { get; set; }
- public override int InternalBufferSize { get; set; }
- public override NotifyFilters NotifyFilter { get; set; }
- public override string Path { get; set; }
-#if NET40
- public override ISite Site { get; set; }
- public override ISynchronizeInvoke SynchronizingObject { get; set; }
-#endif
-
-#if NET40
- public override void BeginInit()
- {
- }
-
- public override void EndInit()
- {
- }
-#endif
-
- public override WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType)
- {
- throw new NotImplementedException();
- }
-
- public override WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType, int timeout)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/System.IO.Abstractions.TestingHelpers/MockFileSystemWatcherFactory.cs b/System.IO.Abstractions.TestingHelpers/MockFileSystemWatcherFactory.cs
index 14a494074..fa832ba13 100644
--- a/System.IO.Abstractions.TestingHelpers/MockFileSystemWatcherFactory.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockFileSystemWatcherFactory.cs
@@ -1,21 +1,12 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace System.IO.Abstractions.TestingHelpers
+namespace System.IO.Abstractions.TestingHelpers
{
[Serializable]
public class MockFileSystemWatcherFactory : IFileSystemWatcherFactory
{
- public FileSystemWatcherBase CreateNew()
- {
- return new MockFileSystemWatcher();
- }
+ public FileSystemWatcherBase CreateNew() =>
+ throw new NotImplementedException(StringResources.Manager.GetString("FILE_SYSTEM_WATCHER_NOT_IMPLEMENTED_EXCEPTION"));
- public FileSystemWatcherBase FromPath(string path)
- {
- return new MockFileSystemWatcher {Path = path};
- }
+ public FileSystemWatcherBase FromPath(string path) =>
+ throw new NotImplementedException(StringResources.Manager.GetString("FILE_SYSTEM_WATCHER_NOT_IMPLEMENTED_EXCEPTION"));
}
}
diff --git a/System.IO.Abstractions.TestingHelpers/MockPath.cs b/System.IO.Abstractions.TestingHelpers/MockPath.cs
index ae44854ea..a1929b457 100644
--- a/System.IO.Abstractions.TestingHelpers/MockPath.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockPath.cs
@@ -12,8 +12,6 @@ public class MockPath : PathWrapper
{
private readonly IMockFileDataAccessor mockFileDataAccessor;
- private static readonly char[] InvalidAdditionalPathChars = { '*', '?' };
-
public MockPath(IMockFileDataAccessor mockFileDataAccessor) : base(mockFileDataAccessor?.FileSystem)
{
this.mockFileDataAccessor = mockFileDataAccessor ?? throw new ArgumentNullException(nameof(mockFileDataAccessor));
@@ -34,8 +32,8 @@ public override string GetFullPath(string path)
path = path.Replace(AltDirectorySeparatorChar, DirectorySeparatorChar);
bool isUnc =
- path.StartsWith(@"\\", StringComparison.OrdinalIgnoreCase) ||
- path.StartsWith(@"//", StringComparison.OrdinalIgnoreCase);
+ mockFileDataAccessor.StringOperations.StartsWith(path, @"\\") ||
+ mockFileDataAccessor.StringOperations.StartsWith(path, @"//");
string root = GetPathRoot(path);
@@ -58,7 +56,8 @@ public override string GetFullPath(string path)
throw new ArgumentException(@"The UNC path should be of the form \\server\share.", "path");
}
}
- else if (@"\".Equals(root, StringComparison.OrdinalIgnoreCase) || @"/".Equals(root, StringComparison.OrdinalIgnoreCase))
+ else if (mockFileDataAccessor.StringOperations.Equals(@"\", root) ||
+ mockFileDataAccessor.StringOperations.Equals(@"/", root))
{
// absolute path on the current drive or volume
pathSegments = GetSegments(GetPathRoot(mockFileDataAccessor.Directory.GetCurrentDirectory()), path);
@@ -69,9 +68,9 @@ public override string GetFullPath(string path)
}
// unc paths need at least two segments, the others need one segment
- bool isUnixRooted =
- mockFileDataAccessor.Directory.GetCurrentDirectory()
- .StartsWith(string.Format(CultureInfo.InvariantCulture, "{0}", DirectorySeparatorChar), StringComparison.OrdinalIgnoreCase);
+ var isUnixRooted = mockFileDataAccessor.StringOperations.StartsWith(
+ mockFileDataAccessor.Directory.GetCurrentDirectory(),
+ string.Format(CultureInfo.InvariantCulture, "{0}", DirectorySeparatorChar));
var minPathSegments = isUnc
? 2
@@ -80,7 +79,7 @@ public override string GetFullPath(string path)
var stack = new Stack();
foreach (var segment in pathSegments)
{
- if ("..".Equals(segment, StringComparison.OrdinalIgnoreCase))
+ if (mockFileDataAccessor.StringOperations.Equals("..", segment))
{
// only pop, if afterwards are at least the minimal amount of path segments
if (stack.Count > minPathSegments)
@@ -88,7 +87,7 @@ public override string GetFullPath(string path)
stack.Pop();
}
}
- else if (".".Equals(segment, StringComparison.OrdinalIgnoreCase))
+ else if (mockFileDataAccessor.StringOperations.Equals(".", segment))
{
// ignore .
}
@@ -137,33 +136,5 @@ public override string GetTempFileName()
return fullPath;
}
-
- internal static bool HasIllegalCharacters(string path, bool checkAdditional)
- {
- if (path == null)
- {
- throw new ArgumentNullException(nameof(path));
- }
-
- if (checkAdditional)
- {
- return path.IndexOfAny(Path.GetInvalidPathChars().Concat(InvalidAdditionalPathChars).ToArray()) >= 0;
- }
-
- return path.IndexOfAny(Path.GetInvalidPathChars()) >= 0;
- }
-
- internal static void CheckInvalidPathChars(string path, bool checkAdditional = false)
- {
- if (path == null)
- {
- throw new ArgumentNullException(nameof(path));
- }
-
- if (HasIllegalCharacters(path, checkAdditional))
- {
- throw new ArgumentException(StringResources.Manager.GetString("ILLEGAL_CHARACTERS_IN_PATH_EXCEPTION"));
- }
- }
}
}
diff --git a/System.IO.Abstractions.TestingHelpers/MockUnixSupport.cs b/System.IO.Abstractions.TestingHelpers/MockUnixSupport.cs
index cb3321c91..d96acd332 100644
--- a/System.IO.Abstractions.TestingHelpers/MockUnixSupport.cs
+++ b/System.IO.Abstractions.TestingHelpers/MockUnixSupport.cs
@@ -4,28 +4,13 @@ namespace System.IO.Abstractions.TestingHelpers
{
public static class MockUnixSupport
{
- public static string Path(string path, Func isUnixF = null)
- {
- var isUnix = isUnixF ?? IsUnixPlatform;
+ private static readonly Regex pathTransform = new Regex(@"^[a-zA-Z]:(?.*)$");
- if (isUnix())
- {
- path = Regex.Replace(path, @"^[a-zA-Z]:(?.*)$", "${path}");
- path = path.Replace(@"\", "/");
- }
+ public static string Path(string path) => IsUnixPlatform()
+ ? pathTransform.Replace(path, "${path}").Replace(@"\", "/")
+ : path;
- return path;
- }
-
- public static string Separator(Func isUnixF = null)
- {
- var isUnix = isUnixF ?? IsUnixPlatform;
- return isUnix() ? "/" : @"\";
- }
-
- public static bool IsUnixPlatform()
- {
- return IO.Path.DirectorySeparatorChar == '/';
- }
+ public static bool IsUnixPlatform() => IO.Path.DirectorySeparatorChar == '/';
+ public static bool IsWindowsPlatform() => IO.Path.DirectorySeparatorChar == '\\';
}
}
diff --git a/System.IO.Abstractions.TestingHelpers/PathVerifier.cs b/System.IO.Abstractions.TestingHelpers/PathVerifier.cs
index 43cc8adf3..a1d11cfdd 100644
--- a/System.IO.Abstractions.TestingHelpers/PathVerifier.cs
+++ b/System.IO.Abstractions.TestingHelpers/PathVerifier.cs
@@ -2,8 +2,11 @@
namespace System.IO.Abstractions.TestingHelpers
{
+ using XFS = MockUnixSupport;
+
public class PathVerifier
{
+ private static readonly char[] AdditionalInvalidPathChars = { '*', '?' };
private readonly IMockFileDataAccessor _mockFileDataAccessor;
internal PathVerifier(IMockFileDataAccessor mockFileDataAccessor)
@@ -28,12 +31,9 @@ public void IsLegalAbsoluteOrRelative(string path, string paramName)
throw new ArgumentException(StringResources.Manager.GetString("THE_PATH_IS_NOT_OF_A_LEGAL_FORM"), paramName);
}
- if (!MockUnixSupport.IsUnixPlatform())
+ if (XFS.IsWindowsPlatform() && !IsValidUseOfVolumeSeparatorChar(path))
{
- if (!IsValidUseOfVolumeSeparatorChar(path))
- {
- throw new NotSupportedException(StringResources.Manager.GetString("THE_PATH_IS_NOT_OF_A_LEGAL_FORM"));
- }
+ throw new NotSupportedException(StringResources.Manager.GetString("THE_PATH_IS_NOT_OF_A_LEGAL_FORM"));
}
if (ExtractFileName(path).IndexOfAny(_mockFileDataAccessor.Path.GetInvalidFileNameChars()) > -1)
@@ -42,7 +42,8 @@ public void IsLegalAbsoluteOrRelative(string path, string paramName)
}
var filePath = ExtractFilePath(path);
- if (MockPath.HasIllegalCharacters(filePath, false))
+
+ if (HasIllegalCharacters(filePath, checkAdditional: false))
{
throw new ArgumentException(StringResources.Manager.GetString("ILLEGAL_CHARACTERS_IN_PATH_EXCEPTION"));
}
@@ -68,5 +69,35 @@ private string ExtractFilePath(string fullFileName)
_mockFileDataAccessor.Path.AltDirectorySeparatorChar);
return string.Join(_mockFileDataAccessor.Path.DirectorySeparatorChar.ToString(), extractFilePath.Take(extractFilePath.Length - 1));
}
+
+ public bool HasIllegalCharacters(string path, bool checkAdditional)
+ {
+ if (path == null)
+ {
+ throw new ArgumentNullException(nameof(path));
+ }
+
+ var invalidPathChars = _mockFileDataAccessor.Path.GetInvalidPathChars();
+
+ if (checkAdditional)
+ {
+ return path.IndexOfAny(invalidPathChars.Concat(AdditionalInvalidPathChars).ToArray()) >= 0;
+ }
+
+ return path.IndexOfAny(invalidPathChars) >= 0;
+ }
+
+ public void CheckInvalidPathChars(string path, bool checkAdditional = false)
+ {
+ if (path == null)
+ {
+ throw new ArgumentNullException(nameof(path));
+ }
+
+ if (HasIllegalCharacters(path, checkAdditional))
+ {
+ throw new ArgumentException(StringResources.Manager.GetString("ILLEGAL_CHARACTERS_IN_PATH_EXCEPTION"));
+ }
+ }
}
}
diff --git a/System.IO.Abstractions.TestingHelpers/Properties/Resources.resx b/System.IO.Abstractions.TestingHelpers/Properties/Resources.resx
index 5e8750581..13097ff13 100644
--- a/System.IO.Abstractions.TestingHelpers/Properties/Resources.resx
+++ b/System.IO.Abstractions.TestingHelpers/Properties/Resources.resx
@@ -144,4 +144,7 @@
Could not find file '{0}'.
-
\ No newline at end of file
+
+ MockFileSystem does not have a built-in FileSystemWatcher implementation. You must provide your own mock or implementation of IFileSystemWatcherFactory and assign it to MockFileSystem.FileSystemWatcher.
+
+
diff --git a/System.IO.Abstractions.TestingHelpers/StringExtensions.cs b/System.IO.Abstractions.TestingHelpers/StringExtensions.cs
index b4a58919f..f8640c861 100644
--- a/System.IO.Abstractions.TestingHelpers/StringExtensions.cs
+++ b/System.IO.Abstractions.TestingHelpers/StringExtensions.cs
@@ -1,9 +1,12 @@
using System.Collections.Generic;
using System.Diagnostics.Contracts;
+using System.Linq;
using System.Text;
namespace System.IO.Abstractions.TestingHelpers
{
+ using XFS = MockUnixSupport;
+
public static class StringExtensions
{
[Pure]
@@ -66,14 +69,14 @@ public static string TrimSlashes(this string path)
var trimmed = path.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
- if (MockUnixSupport.IsUnixPlatform()
+ if (XFS.IsUnixPlatform()
&& (path[0] == Path.DirectorySeparatorChar || path[0] == Path.AltDirectorySeparatorChar)
&& trimmed == "")
{
return Path.DirectorySeparatorChar.ToString();
}
- if (!MockUnixSupport.IsUnixPlatform()
+ if (XFS.IsWindowsPlatform()
&& trimmed.Length == 2
&& char.IsLetter(trimmed[0])
&& trimmed[1] == ':')
@@ -83,5 +86,39 @@ public static string TrimSlashes(this string path)
return trimmed;
}
+
+ [Pure]
+ public static string NormalizeSlashes(this string path)
+ {
+ path = path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
+ var sep = Path.DirectorySeparatorChar.ToString();
+ var doubleSep = sep + sep;
+
+ var prefixSeps = new string(path.TakeWhile(c => c == Path.DirectorySeparatorChar).ToArray());
+ path = path.Substring(prefixSeps.Length);
+
+ // UNC Paths start with double slash but no reason
+ // to have more than 2 slashes at the start of a path
+ if (XFS.IsWindowsPlatform() && prefixSeps.Length > 2)
+ {
+ prefixSeps = prefixSeps.Substring(0, 2);
+ }
+ else if (prefixSeps.Length > 1)
+ {
+ prefixSeps = prefixSeps.Substring(0, 1);
+ }
+
+ while (true)
+ {
+ var newPath = path.Replace(doubleSep, sep);
+
+ if (path == newPath)
+ {
+ return prefixSeps + path;
+ }
+
+ path = newPath;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/System.IO.Abstractions.TestingHelpers/StringOperations.cs b/System.IO.Abstractions.TestingHelpers/StringOperations.cs
new file mode 100644
index 000000000..289426a8c
--- /dev/null
+++ b/System.IO.Abstractions.TestingHelpers/StringOperations.cs
@@ -0,0 +1,29 @@
+namespace System.IO.Abstractions.TestingHelpers
+{
+ [Serializable]
+ public class StringOperations
+ {
+ private readonly bool caseSensitive;
+ private readonly StringComparison comparison;
+
+ public StringOperations(bool caseSensitive)
+ {
+ this.caseSensitive = caseSensitive;
+ comparison = caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
+ }
+
+ public StringComparer Comparer => caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
+ public bool StartsWith(string s, string prefix) => s.StartsWith(prefix, comparison);
+ public bool EndsWith(string s, string suffix) => s.EndsWith(suffix, comparison);
+ public bool Equals(string x, string y) => string.Equals(x, y, comparison);
+ public bool Equals(char x, char y) => caseSensitive ? x == y : char.ToUpper(x) == char.ToUpper(y);
+ public int IndexOf(string s, string substring) => s.IndexOf(substring, comparison);
+ public int IndexOf(string s, string substring, int startIndex) => s.IndexOf(substring, startIndex, comparison);
+ public bool Contains(string s, string substring) => s.IndexOf(substring, comparison) >= 0;
+ public string Replace(string s, string oldValue, string newValue) => s.Replace(oldValue, newValue, comparison);
+ public char ToLower(char c) => caseSensitive ? c : char.ToLower(c);
+ public char ToUpper(char c) => caseSensitive ? c : char.ToUpper(c);
+ public string ToLower(string s) => caseSensitive ? s : s.ToLower();
+ public string ToUpper(string s) => caseSensitive ? s : s.ToUpper();
+ }
+}
diff --git a/System.IO.Abstractions.TestingHelpers/System.IO.Abstractions.TestingHelpers.csproj b/System.IO.Abstractions.TestingHelpers/System.IO.Abstractions.TestingHelpers.csproj
index b2dea9e9b..7c83ae1bd 100644
--- a/System.IO.Abstractions.TestingHelpers/System.IO.Abstractions.TestingHelpers.csproj
+++ b/System.IO.Abstractions.TestingHelpers/System.IO.Abstractions.TestingHelpers.csproj
@@ -1,8 +1,8 @@
- net40;netstandard1.4;netstandard2.0;
+ netstandard1.4;netstandard2.0
+ $(TargetFrameworks);net40
System.IO.Abstractions.TestingHelpers
- 0.0.0.1
A set of pre-built mocks to help when testing file system interactions.
System.IO.Abstractions
@@ -36,4 +36,12 @@
+
+
+
+ runtime; build; native; contentfiles; analyzers
+ all
+
+
+
diff --git a/System.IO.Abstractions/System.IO.Abstractions.csproj b/System.IO.Abstractions/System.IO.Abstractions.csproj
index 01be60823..5f8b13f8b 100644
--- a/System.IO.Abstractions/System.IO.Abstractions.csproj
+++ b/System.IO.Abstractions/System.IO.Abstractions.csproj
@@ -1,8 +1,8 @@
- net40;netstandard1.4;netstandard2.0;
- 0.0.0.1
+ netstandard1.4;netstandard2.0
+ $(TargetFrameworks);net40
Tatham Oddie
A set of abstractions to help make file system interactions testable.
@@ -11,7 +11,8 @@
https://github.com/System-IO-Abstractions/System.IO.Abstractions/blob/master/LICENSE
https://github.com/System-IO-Abstractions/System.IO.Abstractions
testing
- true
+ true
+ $(NoWarn);CS1591;CS1574
@@ -27,7 +28,7 @@
4.5.0
-
+
4.5.0
@@ -47,4 +48,12 @@
+
+
+
+ runtime; build; native; contentfiles; analyzers
+ all
+
+
+
diff --git a/after.System.IO.Abstractions.sln.targets b/after.System.IO.Abstractions.sln.targets
new file mode 100644
index 000000000..cf28d8236
--- /dev/null
+++ b/after.System.IO.Abstractions.sln.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
index 0c6c946fd..6e709c648 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,36 +1,33 @@
-image: Visual Studio 2017
+image:
+- Visual Studio 2017
+- Ubuntu
+
configuration: Release
+# Don't start CI for branches that already have a PR
skip_branch_with_pr: true
+# Don't start CI when tags are pushed
skip_tags: true
+# Limit CI to master/release branches (and PRs targeting them)
branches:
only:
- master
-
-version: 2.1.0.{build}
-
-pull_requests:
- do_not_increment_build_number: true
-
-dotnet_csproj:
- patch: true
- file: '**\*.csproj'
- version: '{version}'
- package_version: '{version}'
+ - release
environment:
INHERITDOC_VERSION: 1.2.2.1
TEMP_DIR: c:\temp
+ APPVEYOR_YML_DISABLE_PS_LINUX: true
install:
# Temporarily install InheritDoc using the NuGet CLI
-- nuget install inheritdoc -Version %INHERITDOC_VERSION% -OutputDirectory %TEMP_DIR%
+- cmd: nuget install inheritdoc -Version %INHERITDOC_VERSION% -OutputDirectory %TEMP_DIR%
-before_build:
+before_build:
- nuget restore
-
+
build:
publish_nuget: true
@@ -38,11 +35,26 @@ before_package:
# This step replaces the inheritdoc tags in the xml documentation with documentation from mscorlib.xml
- ps: '& $env:TEMP_DIR\InheritDoc.$env:INHERITDOC_VERSION\tools\InheritDoc.exe -b $env:APPVEYOR_BUILD_FOLDER -g "c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.X\mscorlib.xml" -o'
-deploy:
-- provider: NuGet
- api_key:
- secure: lUmSV95QwsQtvPkHT02PT5fswmVcW0oMIJvOGEincUNnUNtTe3DOIjVEOpC0CMkQ
- skip_symbols: false
- artifact: /.*\.nupkg/
- on:
- branch: master
+# Perform deployments only for Windows job
+for:
+-
+ matrix:
+ only:
+ - image: Visual Studio 2017
+ deploy:
+ - provider: NuGet
+ api_key:
+ secure: z0Zh4VyDdeKlFrTEnYbhqDc0xw9M5ahv/fQJsShk3HqmUWjQ/bh4M/r6ZWZgY/ZB
+ skip_symbols: false
+ artifact: /.*\.nupkg/
+ on:
+ branch: release
+
+ - provider: GitHub
+ tag: v$(appveyor_build_version)
+ prerelease: false
+ artifact: /.*\.nupkg/
+ auth_token:
+ secure: Rrk1zp93EpCyxec/GXKnRnJjX7vU+ClNZEBnxbM+1j6l+C56qSV7B/fUrVsJuZYV
+ on:
+ branch: release
diff --git a/version.json b/version.json
new file mode 100644
index 000000000..292054aac
--- /dev/null
+++ b/version.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
+ "version": "3.0",
+ "assemblyVersion": {
+ "precision": "major"
+ },
+ "publicReleaseRefSpec": [
+ "^refs/heads/release$"
+ ],
+ "cloudBuild": {
+ "buildNumber": {
+ "enabled": true,
+ "setVersionVariables": true
+ }
+ }
+}