Skip to content

Commit a44f978

Browse files
committed
Merge pull request #78 from manne/directory
Adapted some Directory methods in TestingHelpers
2 parents 1d33ec7 + f64dcd8 commit a44f978

7 files changed

Lines changed: 202 additions & 21 deletions

File tree

TestHelpers.Tests/MockDirectoryInfoTests.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void MockDirectoryInfo_Exists(string path, bool expected)
5050
}
5151

5252
[Test]
53-
public void MockDirectoryInfo_FullName_ShouldReturnFullNameIncludingTrailingPathDelimiter()
53+
public void MockDirectoryInfo_FullName_ShouldReturnFullNameWithoutIncludingTrailingPathDelimiter()
5454
{
5555
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
5656
{
@@ -63,7 +63,7 @@ public void MockDirectoryInfo_FullName_ShouldReturnFullNameIncludingTrailingPath
6363

6464
var result = directoryInfo.FullName;
6565

66-
Assert.That(result, Is.EqualTo(@"c:\temp\folder\"));
66+
Assert.That(result, Is.EqualTo(@"c:\temp\folder"));
6767
}
6868

6969
[Test]
@@ -96,5 +96,20 @@ public void MockDirectoryInfo_GetFileSystemInfos_ShouldReturnDirectoriesAndNames
9696

9797
Assert.That(result.Length, Is.EqualTo(2));
9898
}
99+
100+
[Test]
101+
public void MockDirectoryInfo_GetParent_ShouldReturnDirectoriesAndNamesWithSearchPattern()
102+
{
103+
// Arrange
104+
var fileSystem = new MockFileSystem();
105+
fileSystem.AddDirectory(@"c:\a\b\c");
106+
var directoryInfo = new MockDirectoryInfo(fileSystem, @"c:\a\b\c");
107+
108+
// Act
109+
var result = directoryInfo.Parent;
110+
111+
// Assert
112+
Assert.AreEqual(@"c:\a\b", result.FullName);
113+
}
99114
}
100115
}

TestHelpers.Tests/MockDirectoryTests.cs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public void MockDirectory_GetFiles_ShouldReturnAllFilesBelowPathWhenPatternIsWil
2828
// Assert
2929
Assert.That(result, Is.EquivalentTo(expected));
3030
}
31-
31+
3232
private MockFileSystem SetupFileSystem()
3333
{
3434
return new MockFileSystem(new Dictionary<string, MockFileData>
@@ -649,5 +649,87 @@ public void MockDirectory_SetCurrentDirectory_ShouldChangeCurrentDirectory() {
649649

650650
Assert.AreEqual(directory, fileSystem.Directory.GetCurrentDirectory());
651651
}
652+
653+
[Test]
654+
public void MockDirectory_GetParent_ShouldThrowArgumentNullExceptionIfPathIsNull()
655+
{
656+
// Arrange
657+
var fileSystem = new MockFileSystem();
658+
659+
// Act
660+
TestDelegate act = () => fileSystem.Directory.GetParent(null);
661+
662+
// Assert
663+
Assert.Throws<ArgumentNullException>(act);
664+
}
665+
666+
[Test]
667+
public void MockDirectory_GetParent_ShouldThrowArgumentExceptionIfPathIsEmpty()
668+
{
669+
// Arrange
670+
var fileSystem = new MockFileSystem();
671+
672+
// Act
673+
TestDelegate act = () => fileSystem.Directory.GetParent(string.Empty);
674+
675+
// Assert
676+
Assert.Throws<ArgumentException>(act);
677+
}
678+
679+
[Test]
680+
public void MockDirectory_GetParent_ShouldReturnADirectoryInfoIfPathDoesNotExist()
681+
{
682+
// Arrange
683+
var fileSystem = new MockFileSystem();
684+
685+
// Act
686+
var actualResult = fileSystem.Directory.GetParent(@"c:\directory\does\not\exist");
687+
688+
// Assert
689+
Assert.IsNotNull(actualResult);
690+
}
691+
692+
[Test]
693+
public void MockDirectory_GetParent_ShouldThrowArgumentExceptionIfPathHasIllegalCharacters()
694+
{
695+
// Arrange
696+
var fileSystem = new MockFileSystem();
697+
698+
// Act
699+
TestDelegate act = () => fileSystem.Directory.GetParent("c:\\director\ty\\has\\illegal\\character");
700+
701+
// Assert
702+
Assert.Throws<ArgumentException>(act);
703+
}
704+
705+
[Test]
706+
public void MockDirectory_GetParent_ShouldReturnNullIfPathIsRoot()
707+
{
708+
// Arrange
709+
var fileSystem = new MockFileSystem();
710+
fileSystem.AddDirectory(@"c:\");
711+
712+
// Act
713+
var actualResult = fileSystem.Directory.GetParent(@"c:\");
714+
715+
// Assert
716+
Assert.IsNull(actualResult);
717+
}
718+
719+
[TestCase(@"c:\a", @"c:\")]
720+
[TestCase(@"c:\a\b\c\d", @"c:\a\b\c")]
721+
[TestCase(@"c:\a\b\c\d\", @"c:\a\b\c")]
722+
public void MockDirectory_GetParent_ShouldReturnTheParentWithoutTrailingDirectorySeparatorChar(string path, string expectedResult)
723+
{
724+
// Arrange
725+
var fileSystem = new MockFileSystem();
726+
fileSystem.AddDirectory(path);
727+
728+
// Act
729+
var actualResult = fileSystem.Directory.GetParent(path);
730+
731+
// Assert
732+
Assert.AreEqual(expectedResult, actualResult.FullName);
733+
}
652734
}
653735
}

TestHelpers.Tests/MockFileInfoTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ public void MockFileInfo_GetDirectory_ShouldReturnDirectoryInfoWithCorrectPath()
186186
// Act
187187
var result = fileInfo.Directory;
188188

189-
Assert.AreEqual(@"c:\temp\level1\level2\", result.FullName);
189+
Assert.AreEqual(@"c:\temp\level1\level2", result.FullName);
190190
}
191191

192192
[Test]

TestHelpers.Tests/MockFileSystemTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,21 @@ public void MockFileSystem_AddDirectory_ShouldCreateDirectory()
106106
// Assert
107107
Assert.IsTrue(fileSystem.Directory.Exists(baseDirectory));
108108
}
109+
110+
[Test]
111+
public void MockFileSystem_AddDirectory_ShouldThrowExceptionIfDirectoryIsReadOnly()
112+
{
113+
// Arrange
114+
const string baseDirectory = @"C:\Test";
115+
var fileSystem = new MockFileSystem();
116+
fileSystem.AddFile(baseDirectory, new MockFileData(string.Empty));
117+
fileSystem.File.SetAttributes(baseDirectory, FileAttributes.ReadOnly);
118+
119+
// Act
120+
TestDelegate act = () => fileSystem.AddDirectory(baseDirectory);
121+
122+
// Assert
123+
Assert.Throws<UnauthorizedAccessException>(act);
124+
}
109125
}
110126
}

TestingHelpers/MockDirectory.cs

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,32 @@ public override DirectoryInfoBase CreateDirectory(string path)
2828

2929
public override DirectoryInfoBase CreateDirectory(string path, DirectorySecurity directorySecurity)
3030
{
31+
if (path == null)
32+
{
33+
throw new ArgumentNullException("path");
34+
}
35+
36+
if (path.Length == 0)
37+
{
38+
throw new ArgumentException("Path cannot be the empty string or all whitespace.", "path");
39+
}
40+
41+
if (mockFileDataAccessor.FileExists(path))
42+
{
43+
var message = string.Format(CultureInfo.InvariantCulture, @"Cannot create ""{0}"" because a file or directory with the same name already exists.", path);
44+
var ex = new IOException(message);
45+
ex.Data.Add("Path", path);
46+
throw ex;
47+
}
48+
3149
path = EnsurePathEndsWithDirectorySeparator(mockFileDataAccessor.Path.GetFullPath(path));
50+
3251
if (!Exists(path))
52+
{
3353
mockFileDataAccessor.AddDirectory(path);
34-
var created = new MockDirectoryInfo(mockFileDataAccessor, path);
35-
36-
var parent = GetParent(path);
37-
if (parent != null)
38-
CreateDirectory(GetParent(path).FullName, directorySecurity);
54+
}
3955

56+
var created = new MockDirectoryInfo(mockFileDataAccessor, path);
4057
return created;
4158
}
4259

@@ -57,7 +74,7 @@ public override void Delete(string path, bool recursive)
5774
throw new DirectoryNotFoundException(path + " does not exist or could not be found.");
5875

5976
if (!recursive &&
60-
affectedPaths.Count() > 1)
77+
affectedPaths.Count > 1)
6178
throw new IOException("The directory specified by " + path + " is read-only, or recursive is false and " + path + " is not an empty directory.");
6279

6380
foreach (var affectedPath in affectedPaths)
@@ -218,11 +235,38 @@ public override string[] GetLogicalDrives()
218235

219236
public override DirectoryInfoBase GetParent(string path)
220237
{
221-
var parent = new DirectoryInfo(path).Parent;
222-
if (parent == null)
238+
if (path == null)
239+
{
240+
throw new ArgumentNullException("path");
241+
}
242+
243+
if (path.Length == 0)
244+
{
245+
throw new ArgumentException("Path cannot be the empty string or all whitespace.", "path");
246+
}
247+
248+
if (path.IndexOfAny(mockFileDataAccessor.Path.GetInvalidPathChars()) > -1)
249+
{
250+
throw new ArgumentException("Path contains invalid path characters.", "path");
251+
}
252+
253+
var absolutePath = mockFileDataAccessor.Path.GetFullPath(path);
254+
var sepAsString = mockFileDataAccessor.Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture);
255+
var startIndex = absolutePath.EndsWith(sepAsString, StringComparison.OrdinalIgnoreCase) ? absolutePath.Length - 1 : absolutePath.Length;
256+
var lastIndex = absolutePath.LastIndexOf(mockFileDataAccessor.Path.DirectorySeparatorChar, startIndex - 1);
257+
if (lastIndex < 0)
258+
{
223259
return null;
260+
}
261+
262+
var parentPath = absolutePath.Substring(0, lastIndex);
263+
if (string.IsNullOrEmpty(parentPath))
264+
{
265+
return null;
266+
}
224267

225-
return new MockDirectoryInfo(mockFileDataAccessor, parent.FullName);
268+
var parent = new MockDirectoryInfo(mockFileDataAccessor, parentPath);
269+
return parent;
226270
}
227271

228272
public override void Move(string sourceDirName, string destDirName) {

TestingHelpers/MockDirectoryInfo.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ public class MockDirectoryInfo : DirectoryInfoBase
1111
readonly IMockFileDataAccessor mockFileDataAccessor;
1212
readonly string directoryPath;
1313

14-
private static string EnsurePathEndsWithDirectorySeparator(string directoryPath) {
15-
if (!directoryPath.EndsWith(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase))
16-
directoryPath += Path.DirectorySeparatorChar;
17-
return directoryPath;
14+
private static string EnsurePathEndsWithDirectorySeparator(string path)
15+
{
16+
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase))
17+
path += Path.DirectorySeparatorChar;
18+
return path;
1819
}
1920

2021
public MockDirectoryInfo(IMockFileDataAccessor mockFileDataAccessor, string directoryPath)
@@ -72,7 +73,18 @@ public override string Extension
7273

7374
public override string FullName
7475
{
75-
get { return directoryPath; }
76+
get
77+
{
78+
var root = mockFileDataAccessor.Path.GetPathRoot(directoryPath);
79+
if (string.Equals(directoryPath, root, StringComparison.OrdinalIgnoreCase))
80+
{
81+
// drives have the trailing slash
82+
return directoryPath;
83+
}
84+
85+
// directories do not have a trailing slash
86+
return directoryPath.TrimEnd('\\');
87+
}
7688
}
7789

7890
public override DateTime LastAccessTime

TestingHelpers/MockFileSystem.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ public void AddFile(string path, MockFileData mockFile)
8080
lock (files)
8181
{
8282
if (!directory.Exists(directoryPath))
83-
directory.CreateDirectory(directoryPath);
83+
{
84+
AddDirectory(directoryPath);
85+
}
8486

8587
files[fixedPath] = mockFile;
8688
}
@@ -96,8 +98,18 @@ public void AddDirectory(string path)
9698
(files[fixedPath].Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
9799
throw new UnauthorizedAccessException(string.Format(CultureInfo.InvariantCulture, "Access to the path '{0}' is denied.", path));
98100

99-
files[fixedPath] = new MockDirectoryData();
100-
directory.CreateDirectory(fixedPath);
101+
var lastIndex = 0;
102+
while ((lastIndex = path.IndexOf('\\', lastIndex + 1)) > -1)
103+
{
104+
var segment = path.Substring(0, lastIndex + 1);
105+
if (!directory.Exists(segment))
106+
{
107+
files[segment] = new MockDirectoryData();
108+
}
109+
}
110+
111+
var s = path.EndsWith("\\", StringComparison.OrdinalIgnoreCase) ? path : path + "\\";
112+
files[s] = new MockDirectoryData();
101113
}
102114
}
103115

0 commit comments

Comments
 (0)