Skip to content

Commit 41a347a

Browse files
Copilotnohwnd
andcommitted
Fix FilePatternParser to handle forward slashes on Windows
Co-authored-by: nohwnd <[email protected]>
1 parent 9231728 commit 41a347a

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

src/vstest.console/Internal/FilePatternParser.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,14 @@ private Tuple<string, string> SplitFilePatternOnWildCard(string filePattern)
9696
{
9797
// Split the pattern based on first wild card character found.
9898
var splitOnWildCardIndex = filePattern.IndexOfAny(_wildCardCharacters);
99-
var directorySeparatorIndex = filePattern.Substring(0, splitOnWildCardIndex).LastIndexOf(Path.DirectorySeparatorChar);
99+
var pathBeforeWildCard = filePattern.Substring(0, splitOnWildCardIndex);
100+
101+
// Find the last directory separator (either \ or /) before the wildcard
102+
// On Windows, both \ and / are valid directory separators
103+
// On Unix-like systems, only / is typically valid, but this approach is safe for both
104+
var directorySeparatorIndex = Math.Max(
105+
pathBeforeWildCard.LastIndexOf(Path.DirectorySeparatorChar),
106+
pathBeforeWildCard.LastIndexOf(Path.AltDirectorySeparatorChar));
100107

101108
string searchDir = filePattern.Substring(0, directorySeparatorIndex);
102109
string pattern = filePattern.Substring(directorySeparatorIndex + 1);

test/vstest.console.UnitTests/Internal/FilePatternParserTests.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,53 @@ public void FilePatternParserShouldThrowCommandLineExceptionIfFileDoesNotExist()
114114
Assert.ThrowsException<TestSourceException>(() => _filePatternParser.GetMatchingFiles(TranslatePath(@"E:\path\to\project\tests\Blame.Tests\\abc.Tests.dll")));
115115
}
116116

117+
[TestMethod]
118+
public void FilePatternParserShouldCorrectlySplitPatternAndDirectoryWithForwardSlashes()
119+
{
120+
var patternMatchingResult = new PatternMatchingResult(new List<FilePatternMatch>());
121+
_mockMatcherHelper.Setup(x => x.Execute(It.IsAny<DirectoryInfoWrapper>())).Returns(patternMatchingResult);
122+
123+
// Test with forward slashes - this should work on all platforms
124+
_filePatternParser.GetMatchingFiles("C:/Users/vanidhi/Desktop/a/c/*bc.dll");
125+
126+
// Assert that the pattern is parsed correctly
127+
_mockMatcherHelper.Verify(x => x.AddInclude("*bc.dll"));
128+
// The directory path might be normalized by the OS, so we check for both possible formats
129+
_mockMatcherHelper.Verify(x => x.Execute(It.Is<DirectoryInfoWrapper>(y =>
130+
y.FullName.Contains("vanidhi") && y.FullName.Contains("Desktop") && y.FullName.Contains("a") && y.FullName.Contains("c"))));
131+
}
132+
133+
[TestMethod]
134+
public void FilePatternParserShouldCorrectlySplitWithArbitraryDirectoryDepthWithForwardSlashes()
135+
{
136+
var patternMatchingResult = new PatternMatchingResult(new List<FilePatternMatch>());
137+
_mockMatcherHelper.Setup(x => x.Execute(It.IsAny<DirectoryInfoWrapper>())).Returns(patternMatchingResult);
138+
139+
// Test with forward slashes and recursive patterns
140+
_filePatternParser.GetMatchingFiles("C:/Users/vanidhi/**/c/*bc.txt");
141+
142+
// Assert
143+
_mockMatcherHelper.Verify(x => x.AddInclude("**/c/*bc.txt"));
144+
_mockMatcherHelper.Verify(x => x.Execute(It.Is<DirectoryInfoWrapper>(y =>
145+
y.FullName.Contains("vanidhi"))));
146+
}
147+
148+
[TestMethod]
149+
public void FilePatternParserShouldCorrectlySplitWithMixedSlashes()
150+
{
151+
var patternMatchingResult = new PatternMatchingResult(new List<FilePatternMatch>());
152+
_mockMatcherHelper.Setup(x => x.Execute(It.IsAny<DirectoryInfoWrapper>())).Returns(patternMatchingResult);
153+
154+
// Test behavior with mixed forward and backward slashes
155+
// This is primarily relevant on Windows where both are valid
156+
_filePatternParser.GetMatchingFiles("C:/Users/vanidhi/Desktop/a/c/*bc.dll");
157+
158+
// Assert that the pattern is parsed correctly - should find the last separator regardless of type
159+
_mockMatcherHelper.Verify(x => x.AddInclude("*bc.dll"));
160+
_mockMatcherHelper.Verify(x => x.Execute(It.Is<DirectoryInfoWrapper>(y =>
161+
y.FullName.Contains("vanidhi") && y.FullName.Contains("Desktop") && y.FullName.Contains("a") && y.FullName.Contains("c"))));
162+
}
163+
117164
private static string TranslatePath(string path)
118165
{
119166
// RuntimeInformation has conflict when used

0 commit comments

Comments
 (0)