Skip to content

Commit 2c92589

Browse files
authored
fix: Directory.Move fails on Windows if destination has different case from source (#1256)
On Windows, `MockFileSystem.Directory.Move` no longer throws a `System.IO.IOException` when source and destination path only differ in casing.
1 parent 84843b8 commit 2c92589

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

src/TestableIO.System.IO.Abstractions.TestingHelpers/MockDirectory.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ public override void Move(string sourceDirName, string destDirName)
503503
var fullSourcePath = mockFileDataAccessor.Path.GetFullPath(sourceDirName).TrimSlashes();
504504
var fullDestPath = mockFileDataAccessor.Path.GetFullPath(destDirName).TrimSlashes();
505505

506-
if (mockFileDataAccessor.StringOperations.Equals(fullSourcePath, fullDestPath))
506+
if (string.Equals(fullSourcePath, fullDestPath, StringComparison.Ordinal))
507507
{
508508
throw new IOException("Source and destination path must be different.");
509509
}
@@ -537,9 +537,13 @@ public override void Move(string sourceDirName, string destDirName)
537537

538538
if (mockFileDataAccessor.Directory.Exists(fullDestPath) || mockFileDataAccessor.File.Exists(fullDestPath))
539539
{
540-
throw CommonExceptions.CannotCreateBecauseSameNameAlreadyExists(fullDestPath);
540+
// In Windows, file/dir names are case sensetive, C:\\temp\\src and C:\\temp\\SRC and treated different
541+
if (XFS.IsUnixPlatform() ||
542+
!string.Equals(fullSourcePath, fullDestPath, StringComparison.OrdinalIgnoreCase))
543+
{
544+
throw CommonExceptions.CannotCreateBecauseSameNameAlreadyExists(fullDestPath);
545+
}
541546
}
542-
543547
mockFileDataAccessor.MoveDirectory(fullSourcePath, fullDestPath);
544548
}
545549

@@ -653,15 +657,15 @@ public override IEnumerable<string> EnumerateDirectories(string path, string sea
653657
.Where(p => !mockFileDataAccessor.StringOperations.Equals(p, path))
654658
.Select(p => FixPrefix(p, originalPath));
655659
}
656-
660+
657661
private string FixPrefix(string path, string originalPath)
658662
{
659663
var normalizedOriginalPath = mockFileDataAccessor.Path.GetFullPath(originalPath);
660664
var pathWithoutOriginalPath = path.Substring(normalizedOriginalPath.Length)
661665
.TrimStart(mockFileDataAccessor.Path.DirectorySeparatorChar);
662666
return mockFileDataAccessor.Path.Combine(originalPath, pathWithoutOriginalPath);
663667
}
664-
668+
665669
#if FEATURE_ENUMERATION_OPTIONS
666670
/// <inheritdoc />
667671
public override IEnumerable<string> EnumerateDirectories(string path, string searchPattern, EnumerationOptions enumerationOptions)

tests/TestableIO.System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,4 +2204,19 @@ public async Task MockDirectory_Exists_ShouldReturnTrue_IfArgIsFrontSlashAndRoot
22042204

22052205
await That(fileSystem.Directory.Exists("/")).IsEqualTo(true);
22062206
}
2207+
2208+
[Test]
2209+
public static void MockDirectory_Move_ShouldNotThrowException_InWindows_When_SourceAndDestinationDifferOnlyInCasing()
2210+
{
2211+
// Arrange
2212+
MockFileSystem mockFs = new MockFileSystem();
2213+
string tempDir = mockFs.Path.GetTempPath();
2214+
string src = mockFs.Path.Combine(tempDir, "src");
2215+
string dest = mockFs.Path.Combine(tempDir, "SRC");
2216+
IDirectoryInfo srcDir = mockFs.DirectoryInfo.New(src);
2217+
srcDir.Create();
2218+
2219+
// Act & Assert
2220+
Assert.DoesNotThrow(() => mockFs.Directory.Move(src, dest));
2221+
}
22072222
}

0 commit comments

Comments
 (0)