Skip to content

Commit a2062c9

Browse files
updateamanfgreinacher
authored andcommitted
Do not delete directories that start with the same path (#433)
Fixes the bug where Directory.Delete was deleting all similarly named directories. Now it will only delete the directory and subdirectories Fixes #428
1 parent 14e634e commit a2062c9

File tree

2 files changed

+56
-23
lines changed

2 files changed

+56
-23
lines changed

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

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public void MockDirectory_GetFiles_ShouldFilterByExtensionBasedSearchPatternWith
182182
var result = fileSystem.Directory.GetFiles(XFS.Path(@"c:\"), "*.gif", SearchOption.AllDirectories);
183183

184184
// Assert
185-
Assert.That(result, Is.EquivalentTo( expected));
185+
Assert.That(result, Is.EquivalentTo(expected));
186186
}
187187

188188
[Test]
@@ -598,6 +598,29 @@ public void MockDirectory_Delete_ShouldDeleteDirectory()
598598
Assert.IsFalse(fileSystem.Directory.Exists(XFS.Path(@"c:\bar")));
599599
}
600600

601+
[Test]
602+
public void MockDirectory_Delete_ShouldNotDeleteAllDirectories()
603+
{
604+
// Arrange
605+
var folder1Path = XFS.Path(@"D:\Test\Program");
606+
var folder1SubFolderPath = XFS.Path(@"D:\Test\Program\Subfolder");
607+
var folder2Path = XFS.Path(@"D:\Test\Program_bak");
608+
609+
var fileSystem = new MockFileSystem();
610+
611+
fileSystem.AddDirectory(folder1Path);
612+
fileSystem.AddDirectory(folder2Path);
613+
fileSystem.AddDirectory(folder1SubFolderPath);
614+
615+
// Act
616+
fileSystem.Directory.Delete(folder1Path, recursive: true);
617+
618+
// Assert
619+
Assert.IsFalse(fileSystem.Directory.Exists(folder1Path));
620+
Assert.IsFalse(fileSystem.Directory.Exists(folder1SubFolderPath));
621+
Assert.IsTrue(fileSystem.Directory.Exists(folder2Path));
622+
}
623+
601624
[Test]
602625
[WindowsOnly(WindowsSpecifics.CaseInsensitivity)]
603626
public void MockDirectory_Delete_ShouldDeleteDirectoryCaseInsensitively()
@@ -700,7 +723,7 @@ public void MockDirectory_Delete_ShouldDeleteDirectoryRecursively()
700723
public void MockDirectory_GetFileSystemEntries_Returns_Files_And_Directories()
701724
{
702725
string testPath = XFS.Path(@"c:\foo\bar.txt");
703-
string testDir = XFS.Path(@"c:\foo\bar");
726+
string testDir = XFS.Path(@"c:\foo\bar");
704727
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
705728
{
706729
{ testPath, new MockFileData("Demo text content") },
@@ -829,7 +852,7 @@ public void MockDirectory_GetFiles_ShouldFindFilesContainingTwoOrMoreDots()
829852
var actualResult = fileSystem.Directory.GetFiles(XFS.Path(@"c:\"), XFS.Path(@"foo..r\*"));
830853

831854
// Assert
832-
Assert.That(actualResult, Is.EquivalentTo(new [] { testPath }));
855+
Assert.That(actualResult, Is.EquivalentTo(new[] { testPath }));
833856
}
834857

835858
#if NET40
@@ -925,7 +948,7 @@ public void MockDirectory_GetDirectories_WithTopDirectories_ShouldOnlyReturnTopD
925948
var actualResult = fileSystem.Directory.GetDirectories(XFS.Path(@"c:\Folder\"), "*.foo");
926949

927950
// Assert
928-
Assert.That(actualResult, Is.EquivalentTo(new []{XFS.Path(@"C:\Folder\.foo"), XFS.Path(@"C:\Folder\foo.foo")}));
951+
Assert.That(actualResult, Is.EquivalentTo(new[] { XFS.Path(@"C:\Folder\.foo"), XFS.Path(@"C:\Folder\foo.foo") }));
929952
}
930953

931954
[Test]
@@ -1211,17 +1234,18 @@ public void MockDirectory_Move_ShouldMoveDirectoryWithReadOnlySubDirectory()
12111234
}
12121235

12131236
[Test]
1214-
public void MockDirectory_GetCurrentDirectory_ShouldReturnValueFromFileSystemConstructor() {
1237+
public void MockDirectory_GetCurrentDirectory_ShouldReturnValueFromFileSystemConstructor()
1238+
{
12151239
string directory = XFS.Path(@"D:\folder1\folder2");
12161240
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>(), directory);
12171241

12181242
var actual = fileSystem.Directory.GetCurrentDirectory();
12191243

12201244
Assert.AreEqual(directory, actual);
12211245
}
1222-
1246+
12231247
[Test]
1224-
public void MockDirectory_GetCurrentDirectory_ShouldReturnDefaultPathWhenNotSet()
1248+
public void MockDirectory_GetCurrentDirectory_ShouldReturnDefaultPathWhenNotSet()
12251249
{
12261250
string directory = XFS.Path(@"C:\");
12271251

@@ -1233,7 +1257,8 @@ public void MockDirectory_GetCurrentDirectory_ShouldReturnDefaultPathWhenNotSet(
12331257
}
12341258

12351259
[Test]
1236-
public void MockDirectory_SetCurrentDirectory_ShouldChangeCurrentDirectory() {
1260+
public void MockDirectory_SetCurrentDirectory_ShouldChangeCurrentDirectory()
1261+
{
12371262
string directory = XFS.Path(@"D:\folder1\folder2");
12381263
var fileSystem = new MockFileSystem();
12391264

@@ -1278,7 +1303,7 @@ public void MockDirectory_GetParent_ShouldReturnADirectoryInfoIfPathDoesNotExist
12781303
var fileSystem = new MockFileSystem();
12791304

12801305
// Act
1281-
var actualResult = fileSystem.Directory.GetParent(XFS.Path(@"c:\directory\does\not\exist"));
1306+
var actualResult = fileSystem.Directory.GetParent(XFS.Path(@"c:\directory\does\not\exist"));
12821307

12831308
// Assert
12841309
Assert.IsNotNull(actualResult);
@@ -1331,9 +1356,9 @@ public static IEnumerable<string[]> MockDirectory_GetParent_Cases
13311356
{
13321357
get
13331358
{
1334-
yield return new [] { XFS.Path(@"c:\a"), XFS.Path(@"c:\") };
1335-
yield return new [] { XFS.Path(@"c:\a\b\c\d"), XFS.Path(@"c:\a\b\c") };
1336-
yield return new [] { XFS.Path(@"c:\a\b\c\d\"), XFS.Path(@"c:\a\b\c") };
1359+
yield return new[] { XFS.Path(@"c:\a"), XFS.Path(@"c:\") };
1360+
yield return new[] { XFS.Path(@"c:\a\b\c\d"), XFS.Path(@"c:\a\b\c") };
1361+
yield return new[] { XFS.Path(@"c:\a\b\c\d\"), XFS.Path(@"c:\a\b\c") };
13371362
}
13381363
}
13391364

System.IO.Abstractions.TestingHelpers/MockDirectory.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ public class MockDirectory : DirectoryBase
1414
private readonly IMockFileDataAccessor mockFileDataAccessor;
1515
private string currentDirectory;
1616

17-
// This constructor is retained to avoid breaking change
1817
public MockDirectory(IMockFileDataAccessor mockFileDataAccessor, FileBase fileBase, string currentDirectory) :
1918
this(mockFileDataAccessor, currentDirectory)
2019
{
@@ -75,25 +74,34 @@ public override void Delete(string path)
7574
public override void Delete(string path, bool recursive)
7675
{
7776
path = mockFileDataAccessor.Path.GetFullPath(path).TrimSlashes();
77+
78+
var stringOps = mockFileDataAccessor.StringOperations;
79+
var pathWithDirectorySeparatorChar = $"{path}{Path.DirectorySeparatorChar}";
80+
7881
var affectedPaths = mockFileDataAccessor
7982
.AllPaths
80-
.Where(p => mockFileDataAccessor.StringOperations.StartsWith(p, path))
83+
.Where(p => stringOps.Equals(p, path) || stringOps.StartsWith(p, pathWithDirectorySeparatorChar))
8184
.ToList();
8285

8386
if (!affectedPaths.Any())
87+
{
8488
throw new DirectoryNotFoundException(path + " does not exist or could not be found.");
85-
86-
if (!recursive &&
87-
affectedPaths.Count > 1)
89+
}
90+
91+
if (!recursive && affectedPaths.Count > 1)
92+
{
8893
throw new IOException("The directory specified by " + path + " is read-only, or recursive is false and " + path + " is not an empty directory.");
89-
94+
}
95+
9096
foreach (var affectedPath in affectedPaths)
97+
{
9198
mockFileDataAccessor.RemoveFile(affectedPath);
99+
}
92100
}
93101

94102
public override bool Exists(string path)
95103
{
96-
if (path == "/" && XFS.IsUnixPlatform())
104+
if (path == "/" && XFS.IsUnixPlatform())
97105
{
98106
return true;
99107
}
@@ -111,16 +119,16 @@ public override bool Exists(string path)
111119
}
112120

113121
public override DirectorySecurity GetAccessControl(string path)
114-
{
122+
{
115123
mockFileDataAccessor.PathVerifier.IsLegalAbsoluteOrRelative(path, "path");
116124
path = path.TrimSlashes();
117-
125+
118126
if (!mockFileDataAccessor.Directory.Exists(path))
119127
{
120128
throw CommonExceptions.CouldNotFindPartOfPath(path);
121129
}
122130

123-
var directoryData = (MockDirectoryData) mockFileDataAccessor.GetFile(path);
131+
var directoryData = (MockDirectoryData)mockFileDataAccessor.GetFile(path);
124132
return directoryData.AccessControl;
125133
}
126134

@@ -417,7 +425,7 @@ public override void SetCreationTimeUtc(string path, DateTime creationTimeUtc)
417425

418426
public override void SetCurrentDirectory(string path)
419427
{
420-
currentDirectory = path;
428+
currentDirectory = path;
421429
}
422430

423431
public override void SetLastAccessTime(string path, DateTime lastAccessTime)

0 commit comments

Comments
 (0)