Skip to content

Commit 85c51a2

Browse files
rkoeningerfgreinacher
authored andcommitted
PathVerifier should check specifically for invalid use of volume separator and tolerate alt dir separator (#327)
* Corrected names of existing File Copy/Move tests * PathVerifier throws NotSupEx instead of ArgEx on invalid use of vol sep Added 8 tests, updated 4 existing tests * Added spliting by alt dir sep char to PathVerifier * Used WindowsSpecifics.Drives instead of lengthy message * Extracted and simplified volume separator in path validity check * Comment why certain invalid filename chars not checked in relevant tests * Cleaned up unecessary code in Move/Copy NotSupportedException tests * Moved SpecialInvalidChars to single declaration Used [WindowsOnly] instead of if (IsUnix) Split delegates out of Assert.Throws onto separate line * ReadAllBytes_ShouldTolerateAltDirectorySeparatorInPath uses binary data ...and no longer hard-codes forward slash * Removed redundant use of MockUnixSupport.Path from WindowsOnly tests * Moved new file to changed project path
1 parent 4b8ff76 commit 85c51a2

5 files changed

Lines changed: 198 additions & 78 deletions

File tree

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

Lines changed: 72 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -96,20 +96,16 @@ public void MockFile_Copy_ShouldThrowArgumentNullExceptionWhenSourceIsNull_Param
9696
}
9797

9898
[Test]
99-
public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenSourceFileNameContainsInvalidChars_Message()
99+
[WindowsOnly(WindowsSpecifics.StrictPathRules)]
100+
public void MockFile_Copy_ShouldThrowArgumentExceptionWhenSourceFileNameContainsInvalidChars_Message()
100101
{
101-
if (XFS.IsUnixPlatform())
102-
{
103-
Assert.Pass("Path.GetInvalidChars() does not return anything on Mono");
104-
return;
105-
}
106-
107-
var destFilePath = XFS.Path(@"c:\something\demo.txt");
102+
var destFilePath = @"c:\something\demo.txt";
108103
var fileSystem = new MockFileSystem();
104+
var excludeChars = Shared.SpecialInvalidPathChars(fileSystem);
109105

110-
foreach (var invalidChar in fileSystem.Path.GetInvalidFileNameChars().Where(x => x != fileSystem.Path.DirectorySeparatorChar))
106+
foreach (var invalidChar in fileSystem.Path.GetInvalidFileNameChars().Except(excludeChars))
111107
{
112-
var sourceFilePath = XFS.Path(@"c:\something\demo.txt") + invalidChar;
108+
var sourceFilePath = @"c:\something\demo.txt" + invalidChar;
113109

114110
var exception =
115111
Assert.Throws<ArgumentException>(() => fileSystem.File.Copy(sourceFilePath, destFilePath));
@@ -120,20 +116,15 @@ public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenSourceFileNameCont
120116
}
121117

122118
[Test]
123-
public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenSourcePathContainsInvalidChars_Message()
119+
[WindowsOnly(WindowsSpecifics.StrictPathRules)]
120+
public void MockFile_Copy_ShouldThrowArgumentExceptionWhenSourcePathContainsInvalidChars_Message()
124121
{
125-
if (XFS.IsUnixPlatform())
126-
{
127-
Assert.Pass("Path.GetInvalidChars() does not return anything on Mono");
128-
return;
129-
}
130-
131-
var destFilePath = XFS.Path(@"c:\something\demo.txt");
122+
var destFilePath = @"c:\something\demo.txt";
132123
var fileSystem = new MockFileSystem();
133124

134125
foreach (var invalidChar in fileSystem.Path.GetInvalidPathChars())
135126
{
136-
var sourceFilePath = XFS.Path(@"c:\some" + invalidChar + @"thing\demo.txt");
127+
var sourceFilePath = @"c:\some" + invalidChar + @"thing\demo.txt";
137128

138129
var exception =
139130
Assert.Throws<ArgumentException>(() => fileSystem.File.Copy(sourceFilePath, destFilePath));
@@ -144,20 +135,15 @@ public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenSourcePathContains
144135
}
145136

146137
[Test]
147-
public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenTargetPathContainsInvalidChars_Message()
138+
[WindowsOnly(WindowsSpecifics.StrictPathRules)]
139+
public void MockFile_Copy_ShouldThrowArgumentExceptionWhenTargetPathContainsInvalidChars_Message()
148140
{
149-
if (XFS.IsUnixPlatform())
150-
{
151-
Assert.Pass("Path.GetInvalidChars() does not return anything on Mono");
152-
return;
153-
}
154-
155-
var sourceFilePath = XFS.Path(@"c:\something\demo.txt");
141+
var sourceFilePath = @"c:\something\demo.txt";
156142
var fileSystem = new MockFileSystem();
157143

158144
foreach (var invalidChar in fileSystem.Path.GetInvalidPathChars())
159145
{
160-
var destFilePath = XFS.Path(@"c:\some" + invalidChar + @"thing\demo.txt");
146+
var destFilePath = @"c:\some" + invalidChar + @"thing\demo.txt";
161147

162148
var exception =
163149
Assert.Throws<ArgumentException>(() => fileSystem.File.Copy(sourceFilePath, destFilePath));
@@ -168,20 +154,16 @@ public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenTargetPathContains
168154
}
169155

170156
[Test]
171-
public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenTargetFileNameContainsInvalidChars_Message()
157+
[WindowsOnly(WindowsSpecifics.StrictPathRules)]
158+
public void MockFile_Copy_ShouldThrowArgumentExceptionWhenTargetFileNameContainsInvalidChars_Message()
172159
{
173-
if (XFS.IsUnixPlatform())
174-
{
175-
Assert.Pass("Path.GetInvalidChars() does not return anything on Mono");
176-
return;
177-
}
178-
179-
var sourceFilePath = XFS.Path(@"c:\something\demo.txt");
160+
var sourceFilePath = @"c:\something\demo.txt";
180161
var fileSystem = new MockFileSystem();
162+
var excludeChars = Shared.SpecialInvalidPathChars(fileSystem);
181163

182-
foreach (var invalidChar in fileSystem.Path.GetInvalidFileNameChars().Where(x => x != fileSystem.Path.DirectorySeparatorChar))
164+
foreach (var invalidChar in fileSystem.Path.GetInvalidFileNameChars().Except(excludeChars))
183165
{
184-
var destFilePath = XFS.Path(@"c:\something\demo.txt") + invalidChar;
166+
var destFilePath = @"c:\something\demo.txt" + invalidChar;
185167

186168
var exception =
187169
Assert.Throws<ArgumentException>(() => fileSystem.File.Copy(sourceFilePath, destFilePath));
@@ -191,6 +173,58 @@ public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenTargetFileNameCont
191173
}
192174
}
193175

176+
[Test]
177+
[WindowsOnly(WindowsSpecifics.Drives)]
178+
public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenSourcePathContainsInvalidUseOfDriveSeparator()
179+
{
180+
var badSourcePath = @"C::\something\demo.txt";
181+
var destinationPath = @"C:\elsewhere\demo.txt";
182+
var fileSystem = new MockFileSystem();
183+
184+
TestDelegate action = () => fileSystem.File.Copy(badSourcePath, destinationPath);
185+
186+
Assert.Throws<NotSupportedException>(action);
187+
}
188+
189+
[Test]
190+
[WindowsOnly(WindowsSpecifics.Drives)]
191+
public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenSourcePathContainsInvalidDriveLetter()
192+
{
193+
var badSourcePath = @"0:\something\demo.txt";
194+
var destinationPath = @"C:\elsewhere\demo.txt";
195+
var fileSystem = new MockFileSystem();
196+
197+
TestDelegate action = () => fileSystem.File.Copy(badSourcePath, destinationPath);
198+
199+
Assert.Throws<NotSupportedException>(action);
200+
}
201+
202+
[Test]
203+
[WindowsOnly(WindowsSpecifics.Drives)]
204+
public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenDestinationPathContainsInvalidUseOfDriveSeparator()
205+
{
206+
var sourcePath = @"C:\something\demo.txt";
207+
var badDestinationPath = @"C:\elsewhere:\demo.txt";
208+
var fileSystem = new MockFileSystem();
209+
210+
TestDelegate action = () => fileSystem.File.Copy(sourcePath, badDestinationPath);
211+
212+
Assert.Throws<NotSupportedException>(action);
213+
}
214+
215+
[Test]
216+
[WindowsOnly(WindowsSpecifics.Drives)]
217+
public void MockFile_Copy_ShouldThrowNotSupportedExceptionWhenDestinationPathContainsInvalidDriveLetter()
218+
{
219+
var sourcePath = @"C:\something\demo.txt";
220+
var badDestinationPath = @"^:\elsewhere\demo.txt";
221+
var fileSystem = new MockFileSystem();
222+
223+
TestDelegate action = () => fileSystem.File.Copy(sourcePath, badDestinationPath);
224+
225+
Assert.Throws<NotSupportedException>(action);
226+
}
227+
194228
[Test]
195229
public void MockFile_Copy_ShouldThrowArgumentExceptionWhenSourceIsEmpty_Message()
196230
{

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

Lines changed: 72 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,16 @@ public void MockFile_Move_ShouldThrowArgumentNullExceptionWhenSourceIsNull_Param
8585
}
8686

8787
[Test]
88-
public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenSourceFileNameContainsInvalidChars_Message()
88+
[WindowsOnly(WindowsSpecifics.StrictPathRules)]
89+
public void MockFile_Move_ShouldThrowArgumentExceptionWhenSourceFileNameContainsInvalidChars_Message()
8990
{
90-
if (XFS.IsUnixPlatform())
91-
{
92-
Assert.Pass("Path.GetInvalidChars() does not return anything on Mono");
93-
return;
94-
}
95-
96-
var destFilePath = XFS.Path(@"c:\something\demo.txt");
91+
var destFilePath = @"c:\something\demo.txt";
9792
var fileSystem = new MockFileSystem();
93+
var excludeChars = Shared.SpecialInvalidPathChars(fileSystem);
9894

99-
foreach (var invalidChar in fileSystem.Path.GetInvalidFileNameChars().Where(x => x != fileSystem.Path.DirectorySeparatorChar))
95+
foreach (var invalidChar in fileSystem.Path.GetInvalidFileNameChars().Except(excludeChars))
10096
{
101-
var sourceFilePath = XFS.Path(@"c:\something\demo.txt") + invalidChar;
97+
var sourceFilePath = @"c:\something\demo.txt" + invalidChar;
10298

10399
var exception =
104100
Assert.Throws<ArgumentException>(() => fileSystem.File.Move(sourceFilePath, destFilePath));
@@ -109,20 +105,15 @@ public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenSourceFileNameCont
109105
}
110106

111107
[Test]
112-
public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenSourcePathContainsInvalidChars_Message()
108+
[WindowsOnly(WindowsSpecifics.StrictPathRules)]
109+
public void MockFile_Move_ShouldThrowArgumentExceptionWhenSourcePathContainsInvalidChars_Message()
113110
{
114-
if (XFS.IsUnixPlatform())
115-
{
116-
Assert.Pass("Path.GetInvalidChars() does not return anything on Mono");
117-
return;
118-
}
119-
120-
var destFilePath = XFS.Path(@"c:\something\demo.txt");
111+
var destFilePath = @"c:\something\demo.txt";
121112
var fileSystem = new MockFileSystem();
122113

123114
foreach (var invalidChar in fileSystem.Path.GetInvalidPathChars())
124115
{
125-
var sourceFilePath = XFS.Path(@"c:\some" + invalidChar + @"thing\demo.txt");
116+
var sourceFilePath = @"c:\some" + invalidChar + @"thing\demo.txt";
126117

127118
var exception =
128119
Assert.Throws<ArgumentException>(() => fileSystem.File.Move(sourceFilePath, destFilePath));
@@ -133,20 +124,15 @@ public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenSourcePathContains
133124
}
134125

135126
[Test]
136-
public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenTargetPathContainsInvalidChars_Message()
127+
[WindowsOnly(WindowsSpecifics.StrictPathRules)]
128+
public void MockFile_Move_ShouldThrowArgumentExceptionWhenTargetPathContainsInvalidChars_Message()
137129
{
138-
if (XFS.IsUnixPlatform())
139-
{
140-
Assert.Pass("Path.GetInvalidChars() does not return anything on Mono");
141-
return;
142-
}
143-
144-
var sourceFilePath = XFS.Path(@"c:\something\demo.txt");
130+
var sourceFilePath = @"c:\something\demo.txt";
145131
var fileSystem = new MockFileSystem();
146132

147133
foreach (var invalidChar in fileSystem.Path.GetInvalidPathChars())
148134
{
149-
var destFilePath = XFS.Path(@"c:\some" + invalidChar + @"thing\demo.txt");
135+
var destFilePath = @"c:\some" + invalidChar + @"thing\demo.txt";
150136

151137
var exception =
152138
Assert.Throws<ArgumentException>(() => fileSystem.File.Move(sourceFilePath, destFilePath));
@@ -157,20 +143,16 @@ public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenTargetPathContains
157143
}
158144

159145
[Test]
160-
public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenTargetFileNameContainsInvalidChars_Message()
146+
[WindowsOnly(WindowsSpecifics.StrictPathRules)]
147+
public void MockFile_Move_ShouldThrowArgumentExceptionWhenTargetFileNameContainsInvalidChars_Message()
161148
{
162-
if (XFS.IsUnixPlatform())
163-
{
164-
Assert.Pass("Path.GetInvalidChars() does not return anything on Mono");
165-
return;
166-
}
167-
168-
var sourceFilePath = XFS.Path(@"c:\something\demo.txt");
149+
var sourceFilePath = @"c:\something\demo.txt";
169150
var fileSystem = new MockFileSystem();
151+
var excludeChars = Shared.SpecialInvalidPathChars(fileSystem);
170152

171-
foreach (var invalidChar in fileSystem.Path.GetInvalidFileNameChars().Where(x => x != fileSystem.Path.DirectorySeparatorChar))
153+
foreach (var invalidChar in fileSystem.Path.GetInvalidFileNameChars().Except(excludeChars))
172154
{
173-
var destFilePath = XFS.Path(@"c:\something\demo.txt") + invalidChar;
155+
var destFilePath = @"c:\something\demo.txt" + invalidChar;
174156

175157
var exception =
176158
Assert.Throws<ArgumentException>(() => fileSystem.File.Move(sourceFilePath, destFilePath));
@@ -180,6 +162,58 @@ public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenTargetFileNameCont
180162
}
181163
}
182164

165+
[Test]
166+
[WindowsOnly(WindowsSpecifics.Drives)]
167+
public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenSourcePathContainsInvalidUseOfDriveSeparator()
168+
{
169+
var badSourcePath = @"C::\something\demo.txt";
170+
var destinationPath = @"C:\elsewhere\demo.txt";
171+
var fileSystem = new MockFileSystem();
172+
173+
TestDelegate action = () => fileSystem.File.Move(badSourcePath, destinationPath);
174+
175+
Assert.Throws<NotSupportedException>(action);
176+
}
177+
178+
[Test]
179+
[WindowsOnly(WindowsSpecifics.Drives)]
180+
public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenSourcePathContainsInvalidDriveLetter()
181+
{
182+
var badSourcePath = @"0:\something\demo.txt";
183+
var destinationPath = @"C:\elsewhere\demo.txt";
184+
var fileSystem = new MockFileSystem();
185+
186+
TestDelegate action = () => fileSystem.File.Move(badSourcePath, destinationPath);
187+
188+
Assert.Throws<NotSupportedException>(action);
189+
}
190+
191+
[Test]
192+
[WindowsOnly(WindowsSpecifics.Drives)]
193+
public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenDestinationPathContainsInvalidUseOfDriveSeparator()
194+
{
195+
var sourcePath = @"C:\something\demo.txt";
196+
var badDestinationPath = @"C:\elsewhere:\demo.txt";
197+
var fileSystem = new MockFileSystem();
198+
199+
TestDelegate action = () => fileSystem.File.Move(sourcePath, badDestinationPath);
200+
201+
Assert.Throws<NotSupportedException>(action);
202+
}
203+
204+
[Test]
205+
[WindowsOnly(WindowsSpecifics.Drives)]
206+
public void MockFile_Move_ShouldThrowNotSupportedExceptionWhenDestinationPathContainsInvalidDriveLetter()
207+
{
208+
var sourcePath = @"C:\something\demo.txt";
209+
var badDestinationPath = @"^:\elsewhere\demo.txt";
210+
var fileSystem = new MockFileSystem();
211+
212+
TestDelegate action = () => fileSystem.File.Move(sourcePath, badDestinationPath);
213+
214+
Assert.Throws<NotSupportedException>(action);
215+
}
216+
183217
[Test]
184218
public void MockFile_Move_ShouldThrowArgumentExceptionWhenSourceIsEmpty_Message()
185219
{

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,18 @@ public void MockFile_ReadAllBytes_ShouldThrowFileNotFoundExceptionIfFileDoesNotE
4747

4848
Assert.Throws<FileNotFoundException>(action);
4949
}
50+
51+
[Test]
52+
public void MockFile_ReadAllBytes_ShouldTolerateAltDirectorySeparatorInPath()
53+
{
54+
var fileSystem = new MockFileSystem();
55+
var path = XFS.Path("C:" + fileSystem.Path.DirectorySeparatorChar + "test.dat");
56+
var altPath = XFS.Path("C:" + fileSystem.Path.AltDirectorySeparatorChar + "test.dat");
57+
var data = new byte[] { 0x12, 0x34, 0x56, 0x78 };
58+
59+
fileSystem.AddFile(path, new MockFileData(data));
60+
61+
Assert.AreEqual(data, fileSystem.File.ReadAllBytes(altPath));
62+
}
5063
}
5164
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace System.IO.Abstractions.TestingHelpers.Tests
2+
{
3+
internal static class Shared
4+
{
5+
/// <summary>
6+
/// These chars are not valid path chars but do not cause the same
7+
/// errors that other <code>Path.GetInvalidFileNameChars()</code> will.
8+
/// </summary>
9+
public static char[] SpecialInvalidPathChars(IFileSystem fileSystem) => new[]
10+
{
11+
// These are not allowed in a file name, but
12+
// inserting them a path does not make it invalid
13+
fileSystem.Path.DirectorySeparatorChar,
14+
fileSystem.Path.AltDirectorySeparatorChar,
15+
16+
// Raises a different type of exception from other
17+
// invalid chars and is covered by other tests
18+
fileSystem.Path.VolumeSeparatorChar
19+
};
20+
}
21+
}

0 commit comments

Comments
 (0)