Skip to content

FileSystemWatcherMock: Drops sub directories in args.Name #899

@pw-sgr

Description

@pw-sgr

When watching a directory with IncludeSubdirectories = true and not changing the SimulationMode for the filesystem, the sub directories are trimmed from FileSystemEventArgs.FullPath.

In FileSystemWatcherMock.ToFileSystemEventArgs the event args are modified by using reflection, if the simulation mode is not native.

Expected Behavior

The name should be correct and not drop nested directories

Possible Fix

As the comment in FileSystemWatcherMock.ToFileSystemEventArgs points out, the FileSystemEventArgs combines the directory and name, the problem is that the name does not include the complete relative path. So a plausable fix, which would also remove the need for reflection, would be to adjust FileSystemWatcherMock.TransformPathAndName to return the relative path as name, instead of just the file/dir name.

I'm open to implement it.

Work around

Setting the SimulationMode on the MockFileSystem would give the correct FullPath, but Name stays unchanged.

Example

// Minimal example as top-level statment
using System.IO.Abstractions;
using System.Runtime.InteropServices;
using Testably.Abstractions;
using Testably.Abstractions.Testing;

string rootPath;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    rootPath = @".\Temp\" + Guid.NewGuid();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
    rootPath = "/tmp/" + Guid.NewGuid();
}
else
{
    throw new PlatformNotSupportedException();
}

string firstPath = Path.Combine(rootPath, "first");
string nestedPath = Path.Combine(firstPath, "second");
var realFileSystem = new RealFileSystem();

try
{
    var mockFileSystem = new MockFileSystem();
    mockFileSystem.Directory.CreateDirectory(nestedPath);
    realFileSystem.Directory.CreateDirectory(nestedPath);

    IFileSystemWatcher mockWatcher = mockFileSystem.FileSystemWatcher.New(rootPath);
    mockWatcher.IncludeSubdirectories = true;
    mockWatcher.EnableRaisingEvents = true;

    IFileSystemWatcher realWatcher = realFileSystem.FileSystemWatcher.New(rootPath);
    realWatcher.IncludeSubdirectories = true;
    realWatcher.EnableRaisingEvents = true;

    FileSystemEventArgs? mockArgs = null;
    FileSystemEventArgs? realArgs = null;

    mockWatcher.Created += (_, args) =>
    {
        mockArgs = args;
    };

    realWatcher.Created += (_, args) =>
    {
        realArgs = args;
    };

    string nestedFile = Path.Combine(nestedPath, "file.txt");
    string nestedDir = Path.Combine(nestedPath, "dir");
    await mockFileSystem.File.WriteAllTextAsync(nestedFile, "Hello World!");
    mockFileSystem.Directory.CreateDirectory(nestedDir);
    await realFileSystem.File.WriteAllTextAsync(nestedFile, "Hello World!");
    realFileSystem.Directory.CreateDirectory(nestedDir);

    await Task.Delay(1000);

    Console.WriteLine("Mock != Real");
    Console.WriteLine("Name: {0} != {1}", mockArgs?.Name, realArgs?.Name);
    Console.WriteLine("FullPath: {0} != {1}", mockArgs?.FullPath, realArgs?.FullPath);
}
finally
{
    realFileSystem.Directory.Delete(firstPath, true);
}

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions