Skip to content

Commit a072541

Browse files
Matt Dwenfgreinacher
authored andcommitted
Rewrite internal path keys when using MockDirectory.Move (#344)
* Test that a directory with read only sub directories can be moved * Directory move should throw exception if destination directory exists * Directory move should throw exception if source directory does not exist * Rewrite path keys when using MockDirectory.Move * Verify source directory no longer exists when moving directory
1 parent a6e3e17 commit a072541

4 files changed

Lines changed: 85 additions & 20 deletions

File tree

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,32 @@ public void MockDirectory_Move_ShouldMoveDirectoryAtrributes()
11491149
Assert.IsTrue(destDirectoryInfo.Attributes.HasFlag(FileAttributes.System));
11501150
}
11511151

1152+
[Test]
1153+
public void MockDirectory_Move_ShouldMoveDirectoryWithReadOnlySubDirectory()
1154+
{
1155+
// Arrange
1156+
var sourceDirName = XFS.Path(@"a:\folder1\");
1157+
var sourceSubDirName = XFS.Path(@"a:\folder1\sub\");
1158+
1159+
var destDirName = XFS.Path(@"a:\folder2\");
1160+
var destSubDirName = XFS.Path(@"a:\folder2\sub\");
1161+
1162+
var fileSystem = new MockFileSystem();
1163+
fileSystem.AddDirectory(sourceSubDirName);
1164+
1165+
var subDirectoryInfo = fileSystem.DirectoryInfo.FromDirectoryName(sourceSubDirName);
1166+
subDirectoryInfo.Attributes |= FileAttributes.ReadOnly;
1167+
1168+
var sourceDirectoryInfo = fileSystem.DirectoryInfo.FromDirectoryName(sourceDirName);
1169+
1170+
// Act
1171+
fileSystem.DirectoryInfo.FromDirectoryName(sourceDirName).MoveTo(destDirName);
1172+
1173+
// Assert
1174+
Assert.IsFalse(fileSystem.Directory.Exists(sourceSubDirName));
1175+
Assert.IsTrue(fileSystem.FileExists(destSubDirName));
1176+
}
1177+
11521178
[Test]
11531179
public void MockDirectory_GetCurrentDirectory_ShouldReturnValueFromFileSystemConstructor() {
11541180
string directory = XFS.Path(@"D:\folder1\folder2");
@@ -1310,6 +1336,38 @@ public void MockDirectory_Move_ShouldThrowAnIOExceptionIfDirectoriesAreOnDiffere
13101336
Assert.Throws<IOException>(action, "Source and destination path must have identical roots. Move will not work across volumes.");
13111337
}
13121338

1339+
[Test]
1340+
public void MockDirectory_Move_ShouldThrowADirectoryNotFoundExceptionIfDesinationDirectoryDoesNotExist()
1341+
{
1342+
// Arrange
1343+
string sourcePath = XFS.Path(@"c:\a");
1344+
string destPath = XFS.Path(@"c:\b");
1345+
var fileSystem = new MockFileSystem();
1346+
1347+
// Act
1348+
TestDelegate action = () => fileSystem.Directory.Move(sourcePath, destPath);
1349+
1350+
// Assert
1351+
Assert.Throws<DirectoryNotFoundException>(action, "Could not find a part of the path 'c:\a'.");
1352+
}
1353+
1354+
[Test]
1355+
public void MockDirectory_Move_ShouldThrowAnIOExceptionIfDesinationDirectoryExists()
1356+
{
1357+
// Arrange
1358+
string sourcePath = XFS.Path(@"c:\a");
1359+
string destPath = XFS.Path(@"c:\b");
1360+
var fileSystem = new MockFileSystem();
1361+
fileSystem.AddDirectory(sourcePath);
1362+
fileSystem.AddDirectory(destPath);
1363+
1364+
// Act
1365+
TestDelegate action = () => fileSystem.Directory.Move(sourcePath, destPath);
1366+
1367+
// Assert
1368+
Assert.Throws<IOException>(action, "Cannot create 'c:\b\' because a file or directory with the same name already exists.'");
1369+
}
1370+
13131371
[Test]
13141372
public void MockDirectory_EnumerateFiles_ShouldReturnAllFilesBelowPathWhenPatternIsWildcardAndSearchOptionIsAllDirectories()
13151373
{

System.IO.Abstractions.TestingHelpers/IMockFileDataAccessor.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public interface IMockFileDataAccessor
2121
void AddFileFromEmbeddedResource(string path, Assembly resourceAssembly, string embeddedResourcePath);
2222
void AddFilesFromEmbeddedNamespace(string path, Assembly resourceAssembly, string embeddedRresourcePath);
2323

24+
void MoveDirectory(string sourcePath, string destPath);
25+
2426
/// <summary>
2527
/// Removes the file.
2628
/// </summary>

System.IO.Abstractions.TestingHelpers/MockDirectory.cs

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -355,32 +355,17 @@ public override void Move(string sourceDirName, string destDirName)
355355
throw new IOException("Source and destination path must have identical roots. Move will not work across volumes.");
356356
}
357357

358-
//Make sure that the destination exists
359-
mockFileDataAccessor.Directory.CreateDirectory(fullDestPath);
360-
361-
//Copy over the attributes
362-
var sourceDirectoryInfo = mockFileDataAccessor.DirectoryInfo.FromDirectoryName(sourceDirName);
363-
var destDirectoryInfo = mockFileDataAccessor.DirectoryInfo.FromDirectoryName(destDirName);
364-
destDirectoryInfo.Attributes = sourceDirectoryInfo.Attributes;
365-
366-
//Recursively move all the subdirectories from the source into the destination directory
367-
var subdirectories = GetDirectories(fullSourcePath);
368-
foreach (var subdirectory in subdirectories)
358+
if (!mockFileDataAccessor.Directory.Exists(fullSourcePath))
369359
{
370-
var newSubdirPath = subdirectory.Replace(fullSourcePath, fullDestPath, StringComparison.OrdinalIgnoreCase);
371-
Move(subdirectory, newSubdirPath);
360+
throw new DirectoryNotFoundException($"Could not find a part of the path '{sourceDirName}'.");
372361
}
373362

374-
//Move the files in destination directory
375-
var files = GetFiles(fullSourcePath);
376-
foreach (var file in files)
363+
if (mockFileDataAccessor.Directory.Exists(fullDestPath) || mockFileDataAccessor.File.Exists(fullDestPath))
377364
{
378-
var newFilePath = file.Replace(fullSourcePath, fullDestPath, StringComparison.OrdinalIgnoreCase);
379-
mockFileDataAccessor.FileInfo.FromFileName(file).MoveTo(newFilePath);
365+
throw new IOException($"Cannot create '{fullDestPath}' because a file or directory with the same name already exists.");
380366
}
381367

382-
//Delete the source directory
383-
Delete(fullSourcePath);
368+
mockFileDataAccessor.MoveDirectory(fullSourcePath, fullDestPath);
384369
}
385370

386371
public override void SetAccessControl(string path, DirectorySecurity directorySecurity)

System.IO.Abstractions.TestingHelpers/MockFileSystem.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,26 @@ public void AddFilesFromEmbeddedNamespace(string path, Assembly resourceAssembly
211211
}
212212
}
213213

214+
public void MoveDirectory(string sourcePath, string destPath)
215+
{
216+
sourcePath = FixPath(sourcePath);
217+
destPath = FixPath(destPath);
218+
219+
lock (files)
220+
{
221+
var affectedPaths = files.Keys
222+
.Where(p => p.StartsWith(sourcePath, StringComparison.OrdinalIgnoreCase))
223+
.ToList();
224+
225+
foreach(var path in affectedPaths)
226+
{
227+
var newPath = path.Replace(sourcePath, destPath, StringComparison.OrdinalIgnoreCase);
228+
files[newPath] = files[path];
229+
files.Remove(path);
230+
}
231+
}
232+
}
233+
214234
public void RemoveFile(string path)
215235
{
216236
path = FixPath(path);

0 commit comments

Comments
 (0)