Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public class MockFileSystemWatcherFactoryTests
public void MockFileSystemWatcherFactory_CreateNew_ShouldReturnNonNullMockWatcher()
{
// Arrange
var factory = new MockFileSystemWatcherFactory();
var fs = new MockFileSystem();
var factory = new MockFileSystemWatcherFactory(fs);

// Act
var result = factory.CreateNew();
Expand All @@ -26,7 +27,8 @@ public void MockFileSystemWatcherFactory_CreateNew_ShouldReturnNonNullMockWatche
public void MockFileSystemWatcherFactory_FromPath_ShouldReturnNonNullMockWatcher()
{
// Arrange
var factory = new MockFileSystemWatcherFactory();
var fs = new MockFileSystem();
var factory = new MockFileSystemWatcherFactory(fs);

// Act
var result = factory.FromPath(@"y:\test");
Expand All @@ -40,7 +42,8 @@ public void MockFileSystemWatcherFactory_FromPath_ShouldReturnWatcherForSpecifie
{
// Arrange
const string path = @"z:\test";
var factory = new MockFileSystemWatcherFactory();
var fs = new MockFileSystem();
var factory = new MockFileSystemWatcherFactory(fs);

// Act
var result = factory.FromPath(path);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;

namespace System.IO.Abstractions.TestingHelpers.Tests
{
[TestFixture]
public class MockFileSystemWatcherTests
{
[Test]
public void MockFileSystemWatcher_OnCreated_Listen()
{
var fs = new MockFileSystem();
fs.AddDirectory(@"C:\");
var count = 0;

using (var watcher = fs.FileSystemWatcher.FromPath(@"C:\"))
{
watcher.Created += (sender, e) => count++;
fs.File.Create(@"C:\test.txt").Close();
}

Thread.Sleep(500); // TODO: make this unnecessary
Assert.AreEqual(1, count);
}

[Test]
public void MockFileSystemWatcher_OnCreated_UnderSpecificRoot()
{
var fs = new MockFileSystem();
fs.AddDirectory(@"C:\root");
var count = 0;

using (var watcher = fs.FileSystemWatcher.FromPath(@"C:\root"))
{
watcher.Created += (sender, e) => count++;
fs.File.Create(@"C:\test.txt").Close();
fs.File.Create(@"C:\root\test.txt").Close();
}

Thread.Sleep(500); // TODO: make this unnecessary
Assert.AreEqual(1, count);
}

[Test]
public void MockFileSystemWatcher_WaitForChanged_SpecificChangeType()
{
var fs = new MockFileSystem();
fs.AddDirectory(@"C:\root");
var count = 0;

using (var watcher = fs.FileSystemWatcher.FromPath(@"C:\root"))
{
var task = Task.Factory
.StartNew(() => watcher.WaitForChanged(WatcherChangeTypes.Deleted, 1000))
.ContinueWith(_ => count++);
fs.File.Create(@"C:\root\test.txt").Close();
fs.File.Move(@"C:\root\test.txt", @"C:\root\other.txt");
Thread.Sleep(500); // TODO: make this unnecessary
Assert.AreEqual(0, count);
fs.File.Delete(@"C:\root\other.txt");
}

Thread.Sleep(500); // TODO: make this unnecessary
Assert.AreEqual(1, count);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;

namespace System.IO.Abstractions.TestingHelpers
Expand All @@ -21,6 +22,7 @@ public interface IMockFileDataAccessor
void AddFileFromEmbeddedResource(string path, Assembly resourceAssembly, string embeddedResourcePath);
void AddFilesFromEmbeddedNamespace(string path, Assembly resourceAssembly, string embeddedRresourcePath);

void MoveFile(string sourcePath, string destPath);
void MoveDirectory(string sourcePath, string destPath);

/// <summary>
Expand Down Expand Up @@ -60,9 +62,9 @@ public interface IMockFileDataAccessor
PathBase Path { get; }
IDirectoryInfoFactory DirectoryInfo { get; }
IDriveInfoFactory DriveInfo { get; }

PathVerifier PathVerifier { get; }

IFileSystem FileSystem { get; }

ConcurrentQueue<FileSystemEventArgs> Listen();
}
}
9 changes: 2 additions & 7 deletions System.IO.Abstractions.TestingHelpers/MockFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -362,16 +362,11 @@ public override void Move(string sourceFileName, string destFileName)
}
}


var sourceFile = mockFileDataAccessor.GetFile(sourceFileName);

if (sourceFile == null)
if (!mockFileDataAccessor.FileExists(sourceFileName))
throw new FileNotFoundException(string.Format(CultureInfo.InvariantCulture, "The file \"{0}\" could not be found.", sourceFileName), sourceFileName);

VerifyDirectoryExists(destFileName);

mockFileDataAccessor.AddFile(destFileName, new MockFileData(sourceFile.Contents));
mockFileDataAccessor.RemoveFile(sourceFileName);
mockFileDataAccessor.MoveFile(sourceFileName, destFileName);
}

public override Stream Open(string path, FileMode mode)
Expand Down
8 changes: 8 additions & 0 deletions System.IO.Abstractions.TestingHelpers/MockFileInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System.Security.AccessControl;

// TODO: make sure mock file system events are
// fired for operations on MockFileInfo

namespace System.IO.Abstractions.TestingHelpers
{
[Serializable]
Expand Down Expand Up @@ -217,6 +220,11 @@ public override void MoveTo(string destFileName)
}
Delete();
path = movedFileInfo.FullName;

// TODO: use File.Move instead
//var destPath = mockFileSystem.Path.GetFullPath(destFileName);
//mockFileSystem.MoveFile(path, destPath);
//path = destPath;
}

public override Stream Open(FileMode mode)
Expand Down
94 changes: 87 additions & 7 deletions System.IO.Abstractions.TestingHelpers/MockFileSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
Expand All @@ -10,9 +11,13 @@ namespace System.IO.Abstractions.TestingHelpers
public class MockFileSystem : IFileSystem, IMockFileDataAccessor
{
private readonly IDictionary<string, MockFileData> files;

[NonSerialized]
private readonly PathVerifier pathVerifier;

[NonSerialized]
private readonly List<ConcurrentQueue<FileSystemEventArgs>> queues;

public MockFileSystem() : this(null) { }

public MockFileSystem(IDictionary<string, MockFileData> files, string currentDirectory = "")
Expand All @@ -23,17 +28,17 @@ public MockFileSystem(IDictionary<string, MockFileData> files, string currentDir
}

pathVerifier = new PathVerifier(this);

queues = new List<ConcurrentQueue<FileSystemEventArgs>>();
this.files = new Dictionary<string, MockFileData>(StringComparer.OrdinalIgnoreCase);

Path = new MockPath(this);
File = new MockFile(this);
Directory = new MockDirectory(this, File, currentDirectory);
FileInfo = new MockFileInfoFactory(this);
FileStream = new MockFileStreamFactory(this);
DirectoryInfo = new MockDirectoryInfoFactory(this);
DriveInfo = new MockDriveInfoFactory(this);
FileSystemWatcher = new MockFileSystemWatcherFactory();
FileSystemWatcher = new MockFileSystemWatcherFactory(this);

if (files != null)
{
Expand Down Expand Up @@ -140,6 +145,8 @@ public void AddFile(string path, MockFileData mockFile)

SetEntry(fixedPath, mockFile ?? new MockFileData(string.Empty));
}

DispatchCreated(fixedPath);
}

public void AddDirectory(string path)
Expand Down Expand Up @@ -219,6 +226,19 @@ public void AddFilesFromEmbeddedNamespace(string path, Assembly resourceAssembly
}
}

public void MoveFile(string sourcePath, string destPath)
{
sourcePath = FixPath(sourcePath);
destPath = FixPath(destPath);
var entry = files[destPath] = files[sourcePath];
files.Remove(sourcePath);

if (!entry.IsDirectory)
{
DispatchMoved(sourcePath, destPath);
}
}

public void MoveDirectory(string sourcePath, string destPath)
{
sourcePath = FixPath(sourcePath);
Expand All @@ -233,8 +253,7 @@ public void MoveDirectory(string sourcePath, string destPath)
foreach(var path in affectedPaths)
{
var newPath = path.Replace(sourcePath, destPath, StringComparison.OrdinalIgnoreCase);
files[newPath] = files[path];
files.Remove(path);
MoveFile(path, newPath);
}
}
}
Expand All @@ -250,7 +269,15 @@ public void RemoveFile(string path)
throw new UnauthorizedAccessException(string.Format(CultureInfo.InvariantCulture, StringResources.Manager.GetString("ACCESS_TO_THE_PATH_IS_DENIED"), path));
}

files.Remove(path);
if (files.TryGetValue(path, out var entry))
{
files.Remove(path);

if (!entry.IsDirectory)
{
DispatchDeleted(path);
}
}
}
}

Expand Down Expand Up @@ -326,5 +353,58 @@ private MockFileData GetFileWithoutFixingPath(string path)
return result;
}
}

public ConcurrentQueue<FileSystemEventArgs> Listen()
{
lock (queues)
{
var queue = new ConcurrentQueue<FileSystemEventArgs>();
queues.Add(queue);
return queue;
}
}

private void Dispatch(FileSystemEventArgs e)
{
lock (queues)
{
foreach (var queue in queues)
{
queue.Enqueue(e);
}
}
}

private void DispatchCreated(string path) =>
Dispatch(new FileSystemEventArgs(
WatcherChangeTypes.Created,
Path.GetDirectoryName(path),
Path.GetFileName(path)));

private void DispatchDeleted(string path) =>
Dispatch(new FileSystemEventArgs(
WatcherChangeTypes.Deleted,
Path.GetDirectoryName(path),
Path.GetFileName(path)));

private void DispatchMoved(string oldPath, string newPath)
{
if (Path.GetDirectoryName(oldPath) == Path.GetDirectoryName(newPath))
{
DispatchRenamed(oldPath, newPath);
}
else
{
DispatchDeleted(oldPath);
DispatchCreated(newPath);
}
}

private void DispatchRenamed(string oldPath, string newPath) =>
Dispatch(new RenamedEventArgs(
WatcherChangeTypes.Renamed,
Path.GetDirectoryName(newPath),
Path.GetFileName(newPath),
Path.GetFileName(oldPath)));
}
}
Loading