Merge pull request #2767 from dotnet/prkrishn/filesystemglobber
Copy FileSystemGlobbing and HashCodeCombiner sources
This commit is contained in:
commit
9e768d9cad
75 changed files with 3999 additions and 43 deletions
|
@ -0,0 +1,100 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Abstractions;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests
|
||||
{
|
||||
public class FileAbstractionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void TempFolderStartsInitiallyEmpty()
|
||||
{
|
||||
using (var scenario = new DisposableFileSystem())
|
||||
{
|
||||
var contents = scenario.DirectoryInfo.EnumerateFileSystemInfos();
|
||||
|
||||
Assert.Equal(Path.GetFileName(scenario.RootPath), scenario.DirectoryInfo.Name);
|
||||
Assert.Equal(scenario.RootPath, scenario.DirectoryInfo.FullName);
|
||||
Assert.Equal(0, contents.Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FilesAreEnumerated()
|
||||
{
|
||||
using (var scenario = new DisposableFileSystem()
|
||||
.CreateFile("alpha.txt"))
|
||||
{
|
||||
var contents = new DirectoryInfoWrapper(scenario.DirectoryInfo).EnumerateFileSystemInfos();
|
||||
var alphaTxt = contents.OfType<FileInfoBase>().Single();
|
||||
|
||||
Assert.Equal(1, contents.Count());
|
||||
Assert.Equal("alpha.txt", alphaTxt.Name);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FoldersAreEnumerated()
|
||||
{
|
||||
using (var scenario = new DisposableFileSystem()
|
||||
.CreateFolder("beta"))
|
||||
{
|
||||
var contents1 = new DirectoryInfoWrapper(scenario.DirectoryInfo).EnumerateFileSystemInfos();
|
||||
var beta = contents1.OfType<DirectoryInfoBase>().Single();
|
||||
var contents2 = beta.EnumerateFileSystemInfos();
|
||||
|
||||
Assert.Equal(1, contents1.Count());
|
||||
Assert.Equal("beta", beta.Name);
|
||||
Assert.Equal(0, contents2.Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SubFoldersAreEnumerated()
|
||||
{
|
||||
using (var scenario = new DisposableFileSystem()
|
||||
.CreateFolder("beta")
|
||||
.CreateFile(Path.Combine("beta", "alpha.txt")))
|
||||
{
|
||||
var contents1 = new DirectoryInfoWrapper(scenario.DirectoryInfo).EnumerateFileSystemInfos();
|
||||
var beta = contents1.OfType<DirectoryInfoBase>().Single();
|
||||
var contents2 = beta.EnumerateFileSystemInfos();
|
||||
var alphaTxt = contents2.OfType<FileInfoBase>().Single();
|
||||
|
||||
Assert.Equal(1, contents1.Count());
|
||||
Assert.Equal("beta", beta.Name);
|
||||
Assert.Equal(1, contents2.Count());
|
||||
Assert.Equal("alpha.txt", alphaTxt.Name);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDirectoryCanTakeDotDot()
|
||||
{
|
||||
using (var scenario = new DisposableFileSystem()
|
||||
.CreateFolder("gamma")
|
||||
.CreateFolder("beta")
|
||||
.CreateFile(Path.Combine("beta", "alpha.txt")))
|
||||
{
|
||||
var directoryInfoBase = new DirectoryInfoWrapper(scenario.DirectoryInfo);
|
||||
var gamma = directoryInfoBase.GetDirectory("gamma");
|
||||
var dotdot = gamma.GetDirectory("..");
|
||||
var contents1 = dotdot.EnumerateFileSystemInfos();
|
||||
var beta = dotdot.GetDirectory("beta");
|
||||
var contents2 = beta.EnumerateFileSystemInfos();
|
||||
var alphaTxt = contents2.OfType<FileInfoBase>().Single();
|
||||
|
||||
Assert.Equal("..", dotdot.Name);
|
||||
Assert.Equal(2, contents1.Count());
|
||||
Assert.Equal("beta", beta.Name);
|
||||
Assert.Equal(1, contents2.Count());
|
||||
Assert.Equal("alpha.txt", alphaTxt.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,469 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Abstractions;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests
|
||||
{
|
||||
public class FunctionalTests : IDisposable
|
||||
{
|
||||
private readonly DisposableFileSystem _context;
|
||||
|
||||
public FunctionalTests()
|
||||
{
|
||||
_context = CreateContext();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_context.Dispose();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("sub/source2.cs", "sub/source2.cs")]
|
||||
[InlineData("sub\\source2.cs", "sub\\source2.cs")]
|
||||
[InlineData("sub/source2.cs", "sub\\source2.cs")]
|
||||
public void DuplicatePatterns(string pattern1, string pattern2)
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude(pattern1);
|
||||
matcher.AddInclude(pattern2);
|
||||
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"src/project/sub/source2.cs");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("src/project", "source1.cs", new string[] { "source1.cs" })]
|
||||
[InlineData("src/project", "Source1.cs", new string[] { })]
|
||||
[InlineData("src/project", "compiler/preprocess/**/*.cs", new string[] { "compiler/preprocess/preprocess-source1.cs",
|
||||
"compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"compiler/preprocess/sub/sub/preprocess-source3.cs" })]
|
||||
[InlineData("src/project", "compiler/Preprocess/**.cs", new string[] { })]
|
||||
public void IncludeCaseSensitive(string root, string includePattern, string[] expectedFiles)
|
||||
{
|
||||
var matcher = new Matcher(StringComparison.Ordinal);
|
||||
matcher.AddInclude(includePattern);
|
||||
|
||||
ExecuteAndVerify(matcher, root, expectedFiles.Select(f => root + "/" + f).ToArray());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("src/project", "source1.cs", new string[] { "source1.cs" })]
|
||||
[InlineData("src/project", "Source1.cs", new string[] { "Source1.cs" })]
|
||||
[InlineData("src/project", "compiler/preprocess/**/*.cs", new string[] { "compiler/preprocess/preprocess-source1.cs",
|
||||
"compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"compiler/preprocess/sub/sub/preprocess-source3.cs" })]
|
||||
[InlineData("src/project", "compiler/Preprocess/**.cs", new string[] { "compiler/Preprocess/preprocess-source1.cs",
|
||||
"compiler/Preprocess/sub/preprocess-source2.cs",
|
||||
"compiler/Preprocess/sub/sub/preprocess-source3.cs" })]
|
||||
public void IncludeCaseInsensitive(string root, string includePattern, string[] expectedFiles)
|
||||
{
|
||||
var matcher = new Matcher(StringComparison.OrdinalIgnoreCase);
|
||||
matcher.AddInclude(includePattern);
|
||||
|
||||
ExecuteAndVerify(matcher, root, expectedFiles.Select(f => root + "/" + f).ToArray());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("src/project/compiler/preprocess/", "source.cs", new string[] { "preprocess-source1.cs",
|
||||
"sub/preprocess-source2.cs",
|
||||
"sub/sub/preprocess-source3.cs",
|
||||
"sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "preprocess-source1.cs", new string[] {
|
||||
"sub/preprocess-source2.cs",
|
||||
"sub/sub/preprocess-source3.cs",
|
||||
"sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "preprocesS-source1.cs", new string[] {
|
||||
"preprocess-source1.cs",
|
||||
"sub/preprocess-source2.cs",
|
||||
"sub/sub/preprocess-source3.cs",
|
||||
"sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "**/Preprocess*", new string[] { "preprocess-source1.cs",
|
||||
"sub/preprocess-source2.cs",
|
||||
"sub/sub/preprocess-source3.cs",
|
||||
"sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "**/preprocess*", new string[] { })]
|
||||
[InlineData("src/project/compiler/preprocess/", "**/*source*.cs", new string[] { "sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "**/*Source*.cs", new string[] {
|
||||
"preprocess-source1.cs",
|
||||
"sub/preprocess-source2.cs",
|
||||
"sub/sub/preprocess-source3.cs",
|
||||
"sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "sub/sub/*", new string[] { "preprocess-source1.cs",
|
||||
"sub/preprocess-source2.cs" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "sub/Sub/*", new string[] { "preprocess-source1.cs",
|
||||
"sub/preprocess-source2.cs",
|
||||
"sub/sub/preprocess-source3.cs",
|
||||
"sub/sub/preprocess-source3.txt" })]
|
||||
public void ExcludeCaseSensitive(string root, string excludePattern, string[] expectedFiles)
|
||||
{
|
||||
var matcher = new Matcher(StringComparison.Ordinal);
|
||||
matcher.AddInclude("**/*.*");
|
||||
matcher.AddExclude(excludePattern);
|
||||
|
||||
ExecuteAndVerify(matcher, root, expectedFiles.Select(f => root + "/" + f).ToArray());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("src/project/compiler/preprocess/", "source.cs", new string[] { "preprocess-source1.cs",
|
||||
"sub/preprocess-source2.cs",
|
||||
"sub/sub/preprocess-source3.cs",
|
||||
"sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "preprocess-source1.cs", new string[] {
|
||||
"sub/preprocess-source2.cs",
|
||||
"sub/sub/preprocess-source3.cs",
|
||||
"sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "preprocesS-source1.cs", new string[] {
|
||||
"sub/preprocess-source2.cs",
|
||||
"sub/sub/preprocess-source3.cs",
|
||||
"sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "**/Preprocess*", new string[] { })]
|
||||
[InlineData("src/project/compiler/preprocess/", "**/preprocess*", new string[] { })]
|
||||
[InlineData("src/project/compiler/preprocess/", "**/*source*.cs", new string[] { "sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "**/*Source*.cs", new string[] { "sub/sub/preprocess-source3.txt" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "sub/sub/*", new string[] { "preprocess-source1.cs",
|
||||
"sub/preprocess-source2.cs" })]
|
||||
[InlineData("src/project/compiler/preprocess/", "sub/Sub/*", new string[] { "preprocess-source1.cs",
|
||||
"sub/preprocess-source2.cs" })]
|
||||
public void ExcludeCaseInsensitive(string root, string excludePattern, string[] expectedFiles)
|
||||
{
|
||||
var matcher = new Matcher(StringComparison.OrdinalIgnoreCase);
|
||||
matcher.AddInclude("**/*.*");
|
||||
matcher.AddExclude(excludePattern);
|
||||
|
||||
ExecuteAndVerify(matcher, root, expectedFiles.Select(f => root + "/" + f).ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecursiveAndDoubleParentsWithRecursiveSearch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude("**/*.cs")
|
||||
.AddInclude(@"../../lib/**/*.cs");
|
||||
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"src/project/source1.cs",
|
||||
"src/project/sub/source2.cs",
|
||||
"src/project/sub/source3.cs",
|
||||
"src/project/sub2/source4.cs",
|
||||
"src/project/sub2/source5.cs",
|
||||
"src/project/compiler/preprocess/preprocess-source1.cs",
|
||||
"src/project/compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.cs",
|
||||
"src/project/compiler/shared/shared1.cs",
|
||||
"src/project/compiler/shared/sub/shared2.cs",
|
||||
"src/project/compiler/shared/sub/sub/sharedsub.cs",
|
||||
"lib/source6.cs",
|
||||
"lib/sub3/source7.cs",
|
||||
"lib/sub4/source8.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecursiveAndDoubleParentsSearch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude("**/*.cs")
|
||||
.AddInclude(@"../../lib/*.cs");
|
||||
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"src/project/source1.cs",
|
||||
"src/project/sub/source2.cs",
|
||||
"src/project/sub/source3.cs",
|
||||
"src/project/sub2/source4.cs",
|
||||
"src/project/sub2/source5.cs",
|
||||
"src/project/compiler/preprocess/preprocess-source1.cs",
|
||||
"src/project/compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.cs",
|
||||
"src/project/compiler/shared/shared1.cs",
|
||||
"src/project/compiler/shared/sub/shared2.cs",
|
||||
"src/project/compiler/shared/sub/sub/sharedsub.cs",
|
||||
"lib/source6.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WildcardAndDoubleParentWithRecursiveSearch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude(@"..\..\lib\**\*.cs");
|
||||
matcher.AddInclude(@"*.cs");
|
||||
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"src/project/source1.cs",
|
||||
"lib/source6.cs",
|
||||
"lib/sub3/source7.cs",
|
||||
"lib/sub4/source8.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WildcardAndDoubleParentsSearch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude(@"..\..\lib\*.cs");
|
||||
matcher.AddInclude(@"*.cs");
|
||||
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"src/project/source1.cs",
|
||||
"lib/source6.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoubleParentsWithRecursiveSearch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude(@"..\..\lib\**\*.cs");
|
||||
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"lib/source6.cs",
|
||||
"lib/sub3/source7.cs",
|
||||
"lib/sub4/source8.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OneLevelParentAndRecursiveSearch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude(@"../project2/**/*.cs");
|
||||
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"src/project2/source1.cs",
|
||||
"src/project2/sub/source2.cs",
|
||||
"src/project2/sub/source3.cs",
|
||||
"src/project2/sub2/source4.cs",
|
||||
"src/project2/sub2/source5.cs",
|
||||
"src/project2/compiler/preprocess/preprocess-source1.cs",
|
||||
"src/project2/compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"src/project2/compiler/preprocess/sub/sub/preprocess-source3.cs",
|
||||
"src/project2/compiler/shared/shared1.cs",
|
||||
"src/project2/compiler/shared/sub/shared2.cs",
|
||||
"src/project2/compiler/shared/sub/sub/sharedsub.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecursiveSuffixSearch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude(@"**.txt");
|
||||
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.txt",
|
||||
"src/project/compiler/shared/shared1.txt",
|
||||
"src/project/compiler/shared/sub/shared2.txt",
|
||||
"src/project/content1.txt");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FolderExclude()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude(@"**/*.*");
|
||||
matcher.AddExclude(@"obj");
|
||||
matcher.AddExclude(@"bin");
|
||||
matcher.AddExclude(@".*");
|
||||
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"src/project/source1.cs",
|
||||
"src/project/sub/source2.cs",
|
||||
"src/project/sub/source3.cs",
|
||||
"src/project/sub2/source4.cs",
|
||||
"src/project/sub2/source5.cs",
|
||||
"src/project/compiler/preprocess/preprocess-source1.cs",
|
||||
"src/project/compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.cs",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.txt",
|
||||
"src/project/compiler/shared/shared1.cs",
|
||||
"src/project/compiler/shared/shared1.txt",
|
||||
"src/project/compiler/shared/sub/shared2.cs",
|
||||
"src/project/compiler/shared/sub/shared2.txt",
|
||||
"src/project/compiler/shared/sub/sub/sharedsub.cs",
|
||||
"src/project/compiler/resources/resource.res",
|
||||
"src/project/compiler/resources/sub/resource2.res",
|
||||
"src/project/compiler/resources/sub/sub/resource3.res",
|
||||
"src/project/content1.txt");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FolderInclude()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude(@"compiler/");
|
||||
ExecuteAndVerify(matcher, @"src/project",
|
||||
"src/project/compiler/preprocess/preprocess-source1.cs",
|
||||
"src/project/compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.cs",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.txt",
|
||||
"src/project/compiler/shared/shared1.cs",
|
||||
"src/project/compiler/shared/shared1.txt",
|
||||
"src/project/compiler/shared/sub/shared2.cs",
|
||||
"src/project/compiler/shared/sub/shared2.txt",
|
||||
"src/project/compiler/shared/sub/sub/sharedsub.cs",
|
||||
"src/project/compiler/resources/resource.res",
|
||||
"src/project/compiler/resources/sub/resource2.res",
|
||||
"src/project/compiler/resources/sub/sub/resource3.res");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("source1.cs", "src/project/source1.cs")]
|
||||
[InlineData("../project2/source1.cs", "src/project2/source1.cs")]
|
||||
public void SingleFile(string pattern, string expect)
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude(pattern);
|
||||
ExecuteAndVerify(matcher, "src/project", expect);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SingleFileAndRecursive()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude("**/*.cs");
|
||||
matcher.AddInclude("../project2/source1.cs");
|
||||
ExecuteAndVerify(matcher, "src/project",
|
||||
"src/project/source1.cs",
|
||||
"src/project/sub/source2.cs",
|
||||
"src/project/sub/source3.cs",
|
||||
"src/project/sub2/source4.cs",
|
||||
"src/project/sub2/source5.cs",
|
||||
"src/project/compiler/preprocess/preprocess-source1.cs",
|
||||
"src/project/compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.cs",
|
||||
"src/project/compiler/shared/shared1.cs",
|
||||
"src/project/compiler/shared/sub/shared2.cs",
|
||||
"src/project/compiler/shared/sub/sub/sharedsub.cs",
|
||||
"src/project2/source1.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StemCorrectWithDifferentWildCards()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude("sub/*.cs");
|
||||
matcher.AddInclude("**/*.cs");
|
||||
|
||||
var directoryPath = Path.Combine(_context.RootPath, "src/project");
|
||||
var results = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(directoryPath)));
|
||||
|
||||
var actual = results.Files.Select(match => match.Stem);
|
||||
var expected = new string[] {
|
||||
"source1.cs",
|
||||
"source2.cs",
|
||||
"source3.cs",
|
||||
"sub2/source4.cs",
|
||||
"sub2/source5.cs",
|
||||
"compiler/preprocess/preprocess-source1.cs",
|
||||
"compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"compiler/preprocess/sub/sub/preprocess-source3.cs",
|
||||
"compiler/shared/shared1.cs",
|
||||
"compiler/shared/sub/shared2.cs",
|
||||
"compiler/shared/sub/sub/sharedsub.cs"
|
||||
};
|
||||
|
||||
Assert.Equal(
|
||||
expected.OrderBy(e => e),
|
||||
actual.OrderBy(e => e),
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultipleSubDirsAfterFirstWildcardMatch_HasCorrectStem()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
matcher.AddInclude("compiler/**/*.cs");
|
||||
|
||||
var directoryPath = Path.Combine(_context.RootPath, "src/project");
|
||||
var results = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(directoryPath)));
|
||||
|
||||
var actual = results.Files.Select(match => match.Stem);
|
||||
var expected = new string[] {
|
||||
"preprocess/preprocess-source1.cs",
|
||||
"preprocess/sub/preprocess-source2.cs",
|
||||
"preprocess/sub/sub/preprocess-source3.cs",
|
||||
"shared/shared1.cs",
|
||||
"shared/sub/shared2.cs",
|
||||
"shared/sub/sub/sharedsub.cs"
|
||||
};
|
||||
|
||||
Assert.Equal(
|
||||
expected.OrderBy(e => e),
|
||||
actual.OrderBy(e => e),
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private DisposableFileSystem CreateContext()
|
||||
{
|
||||
var context = new DisposableFileSystem();
|
||||
context.CreateFiles(
|
||||
"src/project/source1.cs",
|
||||
"src/project/sub/source2.cs",
|
||||
"src/project/sub/source3.cs",
|
||||
"src/project/sub2/source4.cs",
|
||||
"src/project/sub2/source5.cs",
|
||||
"src/project/compiler/preprocess/preprocess-source1.cs",
|
||||
"src/project/compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.cs",
|
||||
"src/project/compiler/preprocess/sub/sub/preprocess-source3.txt",
|
||||
"src/project/compiler/shared/shared1.cs",
|
||||
"src/project/compiler/shared/shared1.txt",
|
||||
"src/project/compiler/shared/sub/shared2.cs",
|
||||
"src/project/compiler/shared/sub/shared2.txt",
|
||||
"src/project/compiler/shared/sub/sub/sharedsub.cs",
|
||||
"src/project/compiler/resources/resource.res",
|
||||
"src/project/compiler/resources/sub/resource2.res",
|
||||
"src/project/compiler/resources/sub/sub/resource3.res",
|
||||
"src/project/content1.txt",
|
||||
"src/project/obj/object.o",
|
||||
"src/project/bin/object",
|
||||
"src/project/.hidden/file1.hid",
|
||||
"src/project/.hidden/sub/file2.hid",
|
||||
"src/project2/source1.cs",
|
||||
"src/project2/sub/source2.cs",
|
||||
"src/project2/sub/source3.cs",
|
||||
"src/project2/sub2/source4.cs",
|
||||
"src/project2/sub2/source5.cs",
|
||||
"src/project2/compiler/preprocess/preprocess-source1.cs",
|
||||
"src/project2/compiler/preprocess/sub/preprocess-source2.cs",
|
||||
"src/project2/compiler/preprocess/sub/sub/preprocess-source3.cs",
|
||||
"src/project2/compiler/preprocess/sub/sub/preprocess-source3.txt",
|
||||
"src/project2/compiler/shared/shared1.cs",
|
||||
"src/project2/compiler/shared/shared1.txt",
|
||||
"src/project2/compiler/shared/sub/shared2.cs",
|
||||
"src/project2/compiler/shared/sub/shared2.txt",
|
||||
"src/project2/compiler/shared/sub/sub/sharedsub.cs",
|
||||
"src/project2/compiler/resources/resource.res",
|
||||
"src/project2/compiler/resources/sub/resource2.res",
|
||||
"src/project2/compiler/resources/sub/sub/resource3.res",
|
||||
"src/project2/content1.txt",
|
||||
"src/project2/obj/object.o",
|
||||
"src/project2/bin/object",
|
||||
"lib/source6.cs",
|
||||
"lib/sub3/source7.cs",
|
||||
"lib/sub4/source8.cs",
|
||||
"res/resource1.text",
|
||||
"res/resource2.text",
|
||||
"res/resource3.text",
|
||||
".hidden/file1.hid",
|
||||
".hidden/sub/file2.hid");
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
private void ExecuteAndVerify(Matcher matcher, string directoryPath, params string[] expectFiles)
|
||||
{
|
||||
directoryPath = Path.Combine(_context.RootPath, directoryPath);
|
||||
var results = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(directoryPath)));
|
||||
|
||||
var actual = results.Files.Select(match => Path.GetFullPath(Path.Combine(_context.RootPath, directoryPath, match.Path)));
|
||||
var expected = expectFiles.Select(relativePath => Path.GetFullPath(Path.Combine(_context.RootPath, relativePath)));
|
||||
|
||||
Assert.Equal(
|
||||
expected.OrderBy(e => e),
|
||||
actual.OrderBy(e => e),
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Abstractions;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.PatternContexts;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternContexts
|
||||
{
|
||||
public class PatternContextLinearIncludeTests
|
||||
{
|
||||
[Fact]
|
||||
public void PredictBeforeEnterDirectoryShouldThrow()
|
||||
{
|
||||
var pattern = MockLinearPatternBuilder.New().Add("a").Build();
|
||||
var context = new PatternContextLinearInclude(pattern);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
context.Declare((segment, last) =>
|
||||
{
|
||||
Assert.False(true, "No segment should be declared.");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new string[] { "a", "b" }, new string[] { "root" }, "a", false)]
|
||||
[InlineData(new string[] { "a", "b" }, new string[] { "root", "a" }, "b", true)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root" }, "a", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a" }, "b", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b" }, "c", true)]
|
||||
public void PredictReturnsCorrectResult(string[] testSegments, string[] pushDirectory, string expectSegment, bool expectLast)
|
||||
{
|
||||
var pattern = MockLinearPatternBuilder.New().Add(testSegments).Build();
|
||||
var context = new PatternContextLinearInclude(pattern);
|
||||
PatternContextHelper.PushDirectory(context, pushDirectory);
|
||||
|
||||
context.Declare((segment, last) =>
|
||||
{
|
||||
var literal = segment as MockNonRecursivePathSegment;
|
||||
|
||||
Assert.NotNull(segment);
|
||||
Assert.Equal(expectSegment, literal.Value);
|
||||
Assert.Equal(expectLast, last);
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "b" })]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "c" })]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b", "d" })]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b", "c" })]
|
||||
public void PredictNotCallBackWhenEnterUnmatchDirectory(string[] testSegments, string[] pushDirectory)
|
||||
{
|
||||
var pattern = MockLinearPatternBuilder.New().Add(testSegments).Build();
|
||||
var context = new PatternContextLinearInclude(pattern);
|
||||
PatternContextHelper.PushDirectory(context, pushDirectory);
|
||||
|
||||
context.Declare((segment, last) =>
|
||||
{
|
||||
Assert.False(true, "No segment should be declared.");
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", }, "b", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b" }, "d", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b" }, "c", true)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b", "c" }, "d", false)]
|
||||
public void TestFileForIncludeReturnsCorrectResult(string[] testSegments, string[] pushDirectory, string filename, bool expectResult)
|
||||
{
|
||||
var pattern = MockLinearPatternBuilder.New().Add(testSegments).Build();
|
||||
var context = new PatternContextLinearInclude(pattern);
|
||||
PatternContextHelper.PushDirectory(context, pushDirectory);
|
||||
|
||||
var result = context.Test(new FakeFileInfo(filename));
|
||||
|
||||
Assert.Equal(expectResult, result.IsSuccessful);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", }, "b", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b" }, "c", true)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b" }, "d", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b", "c" }, "d", false)]
|
||||
public void TestFileForExcludeReturnsCorrectResult(string[] testSegments, string[] pushDirectory, string filename, bool expectResult)
|
||||
{
|
||||
var pattern = MockLinearPatternBuilder.New().Add(testSegments).Build();
|
||||
var context = new PatternContextLinearExclude(pattern);
|
||||
PatternContextHelper.PushDirectory(context, pushDirectory);
|
||||
|
||||
var result = context.Test(new FakeFileInfo(filename));
|
||||
|
||||
Assert.Equal(expectResult, result.IsSuccessful);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root" }, "a", true)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a" }, "b", true)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a" }, "c", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b" }, "c", false)]
|
||||
public void TestDirectoryForIncludeReturnsCorrectResult(string[] testSegments, string[] pushDirectory, string directoryName, bool expectResult)
|
||||
{
|
||||
var pattern = MockLinearPatternBuilder.New().Add(testSegments).Build();
|
||||
var context = new PatternContextLinearInclude(pattern);
|
||||
PatternContextHelper.PushDirectory(context, pushDirectory);
|
||||
|
||||
var result = context.Test(new FakeDirectoryInfo(directoryName));
|
||||
|
||||
Assert.Equal(expectResult, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root" }, "a", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a" }, "b", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a" }, "c", false)]
|
||||
[InlineData(new string[] { "a", "b", "c" }, new string[] { "root", "a", "b" }, "c", true)]
|
||||
public void TestDirectoryForExcludeReturnsCorrectResult(string[] testSegments, string[] pushDirectory, string directoryName, bool expectResult)
|
||||
{
|
||||
var pattern = MockLinearPatternBuilder.New().Add(testSegments).Build();
|
||||
var context = new PatternContextLinearExclude(pattern);
|
||||
PatternContextHelper.PushDirectory(context, pushDirectory);
|
||||
|
||||
var result = context.Test(new FakeDirectoryInfo(directoryName));
|
||||
|
||||
Assert.Equal(expectResult, result);
|
||||
}
|
||||
|
||||
private class FakeDirectoryInfo : DirectoryInfoBase
|
||||
{
|
||||
public FakeDirectoryInfo(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public override string FullName { get { throw new NotImplementedException(); } }
|
||||
|
||||
public override string Name { get; }
|
||||
|
||||
public override DirectoryInfoBase ParentDirectory { get { throw new NotImplementedException(); } }
|
||||
|
||||
public override IEnumerable<FileSystemInfoBase> EnumerateFileSystemInfos() { throw new NotImplementedException(); }
|
||||
|
||||
public override DirectoryInfoBase GetDirectory(string path) { throw new NotImplementedException(); }
|
||||
|
||||
public override FileInfoBase GetFile(string path) { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
private class FakeFileInfo : FileInfoBase
|
||||
{
|
||||
public FakeFileInfo(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public override string FullName { get { throw new NotImplementedException(); } }
|
||||
|
||||
public override string Name { get; }
|
||||
|
||||
public override DirectoryInfoBase ParentDirectory { get { throw new NotImplementedException(); } }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.PathSegments;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.PatternContexts;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.Patterns;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternContexts
|
||||
{
|
||||
public class PatternContextRaggedIncludeTests
|
||||
{
|
||||
[Fact]
|
||||
public void PredictBeforeEnterDirectoryShouldThrow()
|
||||
{
|
||||
var builder = new PatternBuilder();
|
||||
var pattern = builder.Build("**") as IRaggedPattern;
|
||||
var context = new PatternContextRaggedInclude(pattern);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
context.Declare((segment, last) =>
|
||||
{
|
||||
Assert.False(true, "No segment should be declared.");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/a/b/**/c/d", new string[] { "root" }, "a", false)]
|
||||
[InlineData("/a/b/**/c/d", new string[] { "root", "a" }, "b", false)]
|
||||
[InlineData("/a/b/**/c/d", new string[] { "root", "a", "b" }, null, false)]
|
||||
[InlineData("/a/b/**/c/d", new string[] { "root", "a", "b", "whatever" }, null, false)]
|
||||
[InlineData("/a/b/**/c/d", new string[] { "root", "a", "b", "whatever", "anything" }, null, false)]
|
||||
public void PredictReturnsCorrectResult(string patternString, string[] pushDirectory, string expectSegment, bool expectWildcard)
|
||||
{
|
||||
var builder = new PatternBuilder();
|
||||
var pattern = builder.Build(patternString) as IRaggedPattern;
|
||||
Assert.NotNull(pattern);
|
||||
|
||||
var context = new PatternContextRaggedInclude(pattern);
|
||||
PatternContextHelper.PushDirectory(context, pushDirectory);
|
||||
|
||||
context.Declare((segment, last) =>
|
||||
{
|
||||
if (expectSegment != null)
|
||||
{
|
||||
var mockSegment = segment as LiteralPathSegment;
|
||||
|
||||
Assert.NotNull(mockSegment);
|
||||
Assert.Equal(false, last);
|
||||
Assert.Equal(expectSegment, mockSegment.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal(Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.PathSegments.WildcardPathSegment.MatchAll, segment);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/a/b/**/c/d", new string[] { "root", "b" })]
|
||||
[InlineData("/a/b/**/c/d", new string[] { "root", "a", "c" })]
|
||||
public void PredictNotCallBackWhenEnterUnmatchDirectory(string patternString, string[] pushDirectory)
|
||||
{
|
||||
var builder = new PatternBuilder();
|
||||
var pattern = builder.Build(patternString) as IRaggedPattern;
|
||||
var context = new PatternContextRaggedInclude(pattern);
|
||||
PatternContextHelper.PushDirectory(context, pushDirectory);
|
||||
|
||||
context.Declare((segment, last) =>
|
||||
{
|
||||
Assert.False(true, "No segment should be declared.");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,472 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests
|
||||
{
|
||||
public class PatternMatchingTests
|
||||
{
|
||||
[Fact]
|
||||
public void EmptyCollectionWhenNoFilesPresent()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("alpha.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MatchingFileIsFound()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("alpha.txt")
|
||||
.Files("alpha.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("alpha.txt");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MismatchedFileIsIgnored()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("alpha.txt")
|
||||
.Files("omega.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FolderNamesAreTraversed()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("beta/alpha.txt")
|
||||
.Files("beta/alpha.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("beta/alpha.txt");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"beta/alpha.txt", @"beta/alpha.txt")]
|
||||
[InlineData(@"beta\alpha.txt", @"beta/alpha.txt")]
|
||||
[InlineData(@"beta/alpha.txt", @"beta\alpha.txt")]
|
||||
[InlineData(@"beta\alpha.txt", @"beta\alpha.txt")]
|
||||
[InlineData(@"\beta\alpha.txt", @"beta\alpha.txt")]
|
||||
public void SlashPolarityIsIgnored(string includePattern, string filePath)
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include(includePattern)
|
||||
.Files("one/two.txt", filePath, "three/four.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("beta/alpha.txt");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"*.txt", new[] { "alpha.txt", "beta.txt" })]
|
||||
[InlineData(@"alpha.*", new[] { "alpha.txt" })]
|
||||
[InlineData(@"*.*", new[] { "alpha.txt", "beta.txt", "gamma.dat" })]
|
||||
[InlineData(@"*", new[] { "alpha.txt", "beta.txt", "gamma.dat" })]
|
||||
[InlineData(@"*et*", new[] { "beta.txt" })]
|
||||
[InlineData(@"b*et*t", new[] { "beta.txt" })]
|
||||
[InlineData(@"b*et*x", new string[0])]
|
||||
public void PatternMatchingWorks(string includePattern, string[] matchesExpected)
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include(includePattern)
|
||||
.Files("alpha.txt", "beta.txt", "gamma.dat")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact(matchesExpected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"1234*5678", new[] { "12345678" })]
|
||||
[InlineData(@"12345*5678", new string[0])]
|
||||
[InlineData(@"12*3456*78", new[] { "12345678" })]
|
||||
[InlineData(@"12*23*", new string[0])]
|
||||
[InlineData(@"*67*78", new string[0])]
|
||||
[InlineData(@"*45*56", new string[0])]
|
||||
public void PatternBeginAndEndCantOverlap(string includePattern, string[] matchesExpected)
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include(includePattern)
|
||||
.Files("12345678")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact(matchesExpected);
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"*mm*/*", new[] { "gamma/hello.txt" })]
|
||||
[InlineData(@"/*mm*/*", new[] { "gamma/hello.txt" })]
|
||||
[InlineData(@"*alpha*/*", new[] { "alpha/hello.txt" })]
|
||||
[InlineData(@"/*alpha*/*", new[] { "alpha/hello.txt" })]
|
||||
[InlineData(@"*/*", new[] { "alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt" })]
|
||||
[InlineData(@"/*/*", new[] { "alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt" })]
|
||||
[InlineData(@"*.*/*", new[] { "alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt" })]
|
||||
[InlineData(@"/*.*/*", new[] { "alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt" })]
|
||||
public void PatternMatchingWorksInFolders(string includePattern, string[] matchesExpected)
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include(includePattern)
|
||||
.Files("alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact(matchesExpected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"", new string[] { })]
|
||||
[InlineData(@"./", new string[] { "alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt" })]
|
||||
[InlineData(@"./alpha/hello.txt", new string[] { "alpha/hello.txt" })]
|
||||
[InlineData(@"./**/hello.txt", new string[] { "alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt" })]
|
||||
[InlineData(@"././**/hello.txt", new string[] { "alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt" })]
|
||||
[InlineData(@"././**/./hello.txt", new string[] { "alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt" })]
|
||||
[InlineData(@"././**/./**/hello.txt", new string[] { "alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt" })]
|
||||
[InlineData(@"./*mm*/hello.txt", new string[] { "gamma/hello.txt" })]
|
||||
[InlineData(@"./*mm*/*", new string[] { "gamma/hello.txt" })]
|
||||
public void PatternMatchingCurrent(string includePattern, string[] matchesExpected)
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include(includePattern)
|
||||
.Files("alpha/hello.txt", "beta/hello.txt", "gamma/hello.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact(matchesExpected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StarDotStarIsSameAsStar()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("*.*")
|
||||
.Files("alpha.txt", "alpha.", ".txt", ".", "alpha", "txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("alpha.txt", "alpha.", ".txt", ".", "alpha", "txt");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncompletePatternsDoNotInclude()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("*/*.txt")
|
||||
.Files("one/x.txt", "two/x.txt", "x.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("one/x.txt", "two/x.txt");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncompletePatternsDoNotExclude()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("*/*.txt")
|
||||
.Exclude("one/hello.txt")
|
||||
.Files("one/x.txt", "two/x.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("one/x.txt", "two/x.txt");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TrailingRecursiveWildcardMatchesAllFiles()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("one/**")
|
||||
.Files("one/x.txt", "two/x.txt", "one/x/y.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("one/x.txt", "one/x/y.txt");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LeadingRecursiveWildcardMatchesAllLeadingPaths()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("**/*.cs")
|
||||
.Files("one/x.cs", "two/x.cs", "one/two/x.cs", "x.cs")
|
||||
.Files("one/x.txt", "two/x.txt", "one/two/x.txt", "x.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("one/x.cs", "two/x.cs", "one/two/x.cs", "x.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InnerRecursiveWildcardMuseStartWithAndEndWith()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("one/**/*.cs")
|
||||
.Files("one/x.cs", "two/x.cs", "one/two/x.cs", "x.cs")
|
||||
.Files("one/x.txt", "two/x.txt", "one/two/x.txt", "x.txt")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("one/x.cs", "one/two/x.cs");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void ExcludeMayEndInDirectoryName()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("*.cs", "*/*.cs", "*/*/*.cs")
|
||||
.Exclude("bin", "one/two")
|
||||
.Files("one/x.cs", "two/x.cs", "one/two/x.cs", "x.cs", "bin/x.cs", "bin/two/x.cs")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("one/x.cs", "two/x.cs", "x.cs");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void RecursiveWildcardSurroundingContainsWith()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("**/x/**")
|
||||
.Files("x/1", "1/x/2", "1/x", "x", "1", "1/2")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("x/1", "1/x/2");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void SequentialFoldersMayBeRequired()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("a/b/**/1/2/**/2/3/**")
|
||||
.Files("1/2/2/3/x", "1/2/3/y", "a/1/2/4/2/3/b", "a/2/3/1/2/b")
|
||||
.Files("a/b/1/2/2/3/x", "a/b/1/2/3/y", "a/b/a/1/2/4/2/3/b", "a/b/a/2/3/1/2/b")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("a/b/1/2/2/3/x", "a/b/a/1/2/4/2/3/b");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecursiveAloneIncludesEverything()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("**")
|
||||
.Files("1/2/2/3/x", "1/2/3/y")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("1/2/2/3/x", "1/2/3/y");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExcludeCanHaveSurroundingRecursiveWildcards()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("**")
|
||||
.Exclude("**/x/**")
|
||||
.Files("x/1", "1/x/2", "1/x", "x", "1", "1/2")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("1/x", "x", "1", "1/2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LeadingDotDotCanComeThroughPattern()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("*.cs")
|
||||
.Include("../2/*.cs")
|
||||
.Files("1/x.cs", "1/x.txt", "2/x.cs", "2/x.txt")
|
||||
.SubDirectory("1")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("x.cs", "../2/x.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LeadingDotDotWithRecursiveCanComeThroughPattern()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("*.cs")
|
||||
.Include("../2/**/*.cs")
|
||||
.Files("1/x.cs", "1/x.txt", "2/x.cs", "2/x.txt", "2/3/x.cs", "2/3/4/z.cs", "2/3/x.txt")
|
||||
.SubDirectory("1")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("x.cs", "../2/x.cs", "../2/3/x.cs", "../2/3/4/z.cs");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExcludeFolderRecursively()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("*.*")
|
||||
.Include("../sibling/**/*.*")
|
||||
.Exclude("../sibling/exc/**/*.*")
|
||||
.Exclude("../sibling/inc/2.txt")
|
||||
.Files("main/1.txt", "main/2.txt", "sibling/1.txt", "sibling/inc/1.txt", "sibling/inc/2.txt", "sibling/exc/1.txt", "sibling/exc/2.txt")
|
||||
.SubDirectory("main")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("1.txt", "2.txt", "../sibling/1.txt", "../sibling/inc/1.txt");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExcludeFolderByName()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("*.*")
|
||||
.Include("../sibling/**/*.*")
|
||||
.Exclude("../sibling/exc/")
|
||||
.Exclude("../sibling/inc/2.txt")
|
||||
.Files("main/1.txt", "main/2.txt", "sibling/1.txt", "sibling/inc/1.txt", "sibling/inc/2.txt", "sibling/exc/1.txt", "sibling/exc/2.txt")
|
||||
.SubDirectory("main")
|
||||
.Execute();
|
||||
|
||||
scenario.AssertExact("1.txt", "2.txt", "../sibling/1.txt", "../sibling/inc/1.txt");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultipleRecursiveWildcardStemMatch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("sub/**/bar/**/*.txt")
|
||||
.Files("root.txt", "sub/one.txt", "sub/two.txt", "sub/sub2/bar/baz/three.txt", "sub/sub3/sub4/bar/three.txt")
|
||||
.Execute();
|
||||
|
||||
// Check the stem of the matched items
|
||||
Assert.Equal(new[] {
|
||||
new FilePatternMatch(path: "sub/sub2/bar/baz/three.txt", stem: "sub2/bar/baz/three.txt"),
|
||||
new FilePatternMatch(path: "sub/sub3/sub4/bar/three.txt", stem: "sub3/sub4/bar/three.txt")
|
||||
}, scenario.Result.Files.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecursiveWildcardStemMatch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("sub/**/*.txt")
|
||||
.Files("root.txt", "sub/one.txt", "sub/two.txt", "sub/sub2/three.txt")
|
||||
.Execute();
|
||||
|
||||
// Check the stem of the matched items
|
||||
Assert.Equal(new[] {
|
||||
new FilePatternMatch(path: "sub/one.txt", stem: "one.txt"),
|
||||
new FilePatternMatch(path: "sub/two.txt", stem: "two.txt"),
|
||||
new FilePatternMatch(path: "sub/sub2/three.txt", stem: "sub2/three.txt")
|
||||
}, scenario.Result.Files.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WildcardMidSegmentMatch()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("sub/w*.txt")
|
||||
.Files("root.txt", "sub/woah.txt", "sub/wow.txt", "sub/blah.txt")
|
||||
.Execute();
|
||||
|
||||
// Check the stem of the matched items
|
||||
Assert.Equal(new[] {
|
||||
new FilePatternMatch(path: "sub/woah.txt", stem: "woah.txt"),
|
||||
new FilePatternMatch(path: "sub/wow.txt", stem: "wow.txt")
|
||||
}, scenario.Result.Files.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StemMatchOnExactFile()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("sub/sub/three.txt")
|
||||
.Files("root.txt", "sub/one.txt", "sub/two.txt", "sub/sub/three.txt")
|
||||
.Execute();
|
||||
|
||||
// Check the stem of the matched items
|
||||
Assert.Equal(new[] {
|
||||
new FilePatternMatch(path: "sub/sub/three.txt", stem: "three.txt"),
|
||||
}, scenario.Result.Files.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SimpleStemMatching()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("sub/*")
|
||||
.Files("root.txt", "sub/one.txt", "sub/two.txt", "sub/sub/three.txt")
|
||||
.Execute();
|
||||
|
||||
// Check the stem of the matched items
|
||||
Assert.Equal(new[] {
|
||||
new FilePatternMatch(path: "sub/one.txt", stem: "one.txt"),
|
||||
new FilePatternMatch(path: "sub/two.txt", stem: "two.txt")
|
||||
}, scenario.Result.Files.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StemMatchingWithFileExtension()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("sub/*.txt")
|
||||
.Files("root.txt", "sub/one.txt", "sub/two.txt", "sub/three.dat")
|
||||
.Execute();
|
||||
|
||||
// Check the stem of the matched items
|
||||
Assert.Equal(new[] {
|
||||
new FilePatternMatch(path: "sub/one.txt", stem: "one.txt"),
|
||||
new FilePatternMatch(path: "sub/two.txt", stem: "two.txt")
|
||||
}, scenario.Result.Files.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StemMatchingWithParentDir()
|
||||
{
|
||||
var matcher = new Matcher();
|
||||
var scenario = new FileSystemGlobbingTestContext(@"c:\files\", matcher)
|
||||
.Include("../files/sub/*.txt")
|
||||
.Files("root.txt", "sub/one.txt", "sub/two.txt", "sub/three.dat")
|
||||
.Execute();
|
||||
|
||||
// Check the stem of the matched items
|
||||
Assert.Equal(new[] {
|
||||
new FilePatternMatch(path: "../files/sub/one.txt", stem: "one.txt"),
|
||||
new FilePatternMatch(path: "../files/sub/two.txt", stem: "two.txt")
|
||||
}, scenario.Result.Files.ToArray());
|
||||
}
|
||||
|
||||
// exclude: **/.*/**
|
||||
// exclude: node_modules/*
|
||||
// exclude: **/.cs
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.PathSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternSegments
|
||||
{
|
||||
public class CurrentPathSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("anything")]
|
||||
[InlineData("")]
|
||||
[InlineData(null)]
|
||||
public void Match(string testSample)
|
||||
{
|
||||
var pathSegment = new CurrentPathSegment();
|
||||
Assert.False(pathSegment.Match(testSample));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.PathSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternSegments
|
||||
{
|
||||
public class LiteralPathSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void ThrowArgumentNullException()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() =>
|
||||
{
|
||||
var pathSegment = new LiteralPathSegment(value: null, comparisonType: StringComparison.OrdinalIgnoreCase);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AllowEmptyInDefaultConstructor()
|
||||
{
|
||||
var pathSegment = new LiteralPathSegment(string.Empty, comparisonType: StringComparison.Ordinal);
|
||||
Assert.NotNull(pathSegment);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("something", "anything", StringComparison.Ordinal, false)]
|
||||
[InlineData("something", "Something", StringComparison.Ordinal, false)]
|
||||
[InlineData("something", "something", StringComparison.Ordinal, true)]
|
||||
[InlineData("something", "anything", StringComparison.OrdinalIgnoreCase, false)]
|
||||
[InlineData("something", "Something", StringComparison.OrdinalIgnoreCase, true)]
|
||||
[InlineData("something", "something", StringComparison.OrdinalIgnoreCase, true)]
|
||||
public void Match(string initialValue, string testSample, StringComparison comparisonType, bool expectation)
|
||||
{
|
||||
var pathSegment = new LiteralPathSegment(initialValue, comparisonType);
|
||||
Assert.Equal(initialValue, pathSegment.Value);
|
||||
Assert.Equal(expectation, pathSegment.Match(testSample));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.PathSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternSegments
|
||||
{
|
||||
public class ParentPathSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(".", false)]
|
||||
[InlineData("..", true)]
|
||||
[InlineData("...", false)]
|
||||
public void Match(string testSample, bool expectation)
|
||||
{
|
||||
var pathSegment = new ParentPathSegment();
|
||||
Assert.Equal(expectation, pathSegment.Match(testSample));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.PathSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternSegments
|
||||
{
|
||||
public class RecursiveWildcardSegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void Match()
|
||||
{
|
||||
var pathSegment = new RecursiveWildcardSegment();
|
||||
Assert.False(pathSegment.Match("Anything"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.PathSegments;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternSegments
|
||||
{
|
||||
public class WildcardPathSegmentTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(StringComparison.Ordinal)]
|
||||
[InlineData(StringComparison.OrdinalIgnoreCase)]
|
||||
public void DefaultConstructor(StringComparison comparisonType)
|
||||
{
|
||||
var paramBegin = "begin";
|
||||
var paramContains = new List<string> { "1", "2", "three" };
|
||||
var paramEnd = "end";
|
||||
|
||||
var segment = new WildcardPathSegment(paramBegin, paramContains, paramEnd, comparisonType);
|
||||
|
||||
Assert.Equal(paramBegin, segment.BeginsWith);
|
||||
Assert.Equal<string>(paramContains, segment.Contains);
|
||||
Assert.Equal(paramEnd, segment.EndsWith);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("GetPositiveOrdinalIgnoreCaseDataSample")]
|
||||
public void PositiveOrdinalIgnoreCaseMatch(string testSample, object segment)
|
||||
{
|
||||
var wildcardPathSegment = (WildcardPathSegment)segment;
|
||||
Assert.True(
|
||||
wildcardPathSegment.Match(testSample),
|
||||
string.Format("[TestSample: {0}] [Wildcard: {1}]", testSample, Serialize(wildcardPathSegment)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("GetNegativeOrdinalIgnoreCaseDataSample")]
|
||||
public void NegativeOrdinalIgnoreCaseMatch(string testSample, object segment)
|
||||
{
|
||||
var wildcardPathSegment = (WildcardPathSegment)segment;
|
||||
Assert.False(
|
||||
wildcardPathSegment.Match(testSample),
|
||||
string.Format("[TestSample: {0}] [Wildcard: {1}]", testSample, Serialize(wildcardPathSegment)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("GetPositiveOrdinalDataSample")]
|
||||
public void PositiveOrdinalMatch(string testSample, object segment)
|
||||
{
|
||||
var wildcardPathSegment = (WildcardPathSegment)segment;
|
||||
Assert.True(
|
||||
wildcardPathSegment.Match(testSample),
|
||||
string.Format("[TestSample: {0}] [Wildcard: {1}]", testSample, Serialize(wildcardPathSegment)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("GetNegativeOrdinalDataSample")]
|
||||
public void NegativeOrdinalMatch(string testSample, object segment)
|
||||
{
|
||||
var wildcardPathSegment = (WildcardPathSegment)segment;
|
||||
Assert.False(
|
||||
wildcardPathSegment.Match(testSample),
|
||||
string.Format("[TestSample: {0}] [Wildcard: {1}]", testSample, Serialize(wildcardPathSegment)));
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetPositiveOrdinalIgnoreCaseDataSample()
|
||||
{
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "abc", "a", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "abBb123c", "a", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "aaac", "a", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "acccc", "a", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "aacc", "a", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "aacc", "aa", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "acc", "ac", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "abcdefgh", "ab", "cd", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "abCDEfgh", "ab", "cd", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "ab123cd321ef123gh", "ab", "cd", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "abcd321ef123gh", "ab", "cd", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "ababcd321ef123gh", "ab", "cd", "ef", "gh");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetNegativeOrdinalIgnoreCaseDataSample()
|
||||
{
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "aa", "a", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "cc", "a", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "ab", "a", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "ab", "a", "b", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "bc", "a", "b", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "ac", "a", "b", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "abc", "a", "b", "b", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "ab", "ab", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "ab", "abb", "c");
|
||||
yield return WrapResult(StringComparison.OrdinalIgnoreCase, "ac", "ac", "c");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetPositiveOrdinalDataSample()
|
||||
{
|
||||
yield return WrapResult(StringComparison.Ordinal, "abc", "a", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "abBb123c", "a", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "aaac", "a", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "Aaac", "A", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "acccC", "a", "C");
|
||||
yield return WrapResult(StringComparison.Ordinal, "aacc", "a", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "aAcc", "aA", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "acc", "ac", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "abcDefgh", "ab", "cD", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.Ordinal, "aB123cd321ef123gh", "aB", "cd", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.Ordinal, "abcd321ef123gh", "ab", "cd", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ababcdCD321ef123gh", "ab", "cd", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ababcdCD321ef123gh", "ab", "CD", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ababcd321eF123gh", "ab", "cd", "eF", "gh");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetNegativeOrdinalDataSample()
|
||||
{
|
||||
yield return WrapResult(StringComparison.Ordinal, "aa", "a", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "abc", "A", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "cc", "a", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ab", "a", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ab", "a", "b", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "bc", "a", "b", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ac", "a", "b", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "abc", "a", "b", "b", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ab", "ab", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ab", "abb", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ac", "ac", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "abBb123C", "a", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "Aaac", "a", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "aAac", "A", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "aCc", "a", "C");
|
||||
yield return WrapResult(StringComparison.Ordinal, "aacc", "aA", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "acc", "aC", "c");
|
||||
yield return WrapResult(StringComparison.Ordinal, "abcDefgh", "ab", "cd", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.Ordinal, "aB123cd321ef123gh", "aB", "cd", "EF", "gh");
|
||||
yield return WrapResult(StringComparison.Ordinal, "abcd321ef123gh", "ab", "cd", "efF", "gh");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ababcdCD321ef123gh", "AB", "cd", "ef", "gh");
|
||||
yield return WrapResult(StringComparison.Ordinal, "ababcdCD321ef123gh", "ab", "CD", "EF", "gh");
|
||||
}
|
||||
|
||||
private static object[] WrapResult(StringComparison comparisonType, params string[] values)
|
||||
{
|
||||
if (values == null || values.Length < 3)
|
||||
{
|
||||
throw new InvalidOperationException("At least three values are required to create a data sample");
|
||||
}
|
||||
|
||||
var beginWith = values[1];
|
||||
var endWith = values[values.Length - 1];
|
||||
var contains = values.Skip(2).Take(values.Length - 3);
|
||||
|
||||
return new object[] { values[0], new WildcardPathSegment(beginWith, contains.ToList(), endWith, comparisonType) };
|
||||
}
|
||||
|
||||
private static string Serialize(WildcardPathSegment segment)
|
||||
{
|
||||
return string.Format("{0}:{1}:{2}",
|
||||
segment.BeginsWith,
|
||||
string.Join(",", segment.Contains.ToArray()),
|
||||
segment.EndsWith);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal.Patterns;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.Patterns
|
||||
{
|
||||
public class PatternTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("abc", 1)]
|
||||
[InlineData("/abc", 1)]
|
||||
[InlineData("abc/efg", 2)]
|
||||
[InlineData("abc/efg/h*j", 3)]
|
||||
[InlineData("abc/efg/h*j/*.*", 4)]
|
||||
[InlineData("abc/efg/hij", 3)]
|
||||
[InlineData("abc/efg/hij/klm", 4)]
|
||||
[InlineData("../abc/efg/hij/klm", 5)]
|
||||
[InlineData("../../abc/efg/hij/klm", 6)]
|
||||
public void BuildLinearPattern(string sample, int segmentCount)
|
||||
{
|
||||
var builder = new PatternBuilder();
|
||||
var pattern = builder.Build(sample);
|
||||
|
||||
Assert.True(pattern is ILinearPattern);
|
||||
Assert.Equal(segmentCount, (pattern as ILinearPattern).Segments.Count);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("abc/efg/**")]
|
||||
[InlineData("/abc/efg/**")]
|
||||
[InlineData("abc/efg/**/hij/klm")]
|
||||
[InlineData("abc/efg/**/hij/**/klm")]
|
||||
[InlineData("abc/efg/**/hij/**/klm/**")]
|
||||
[InlineData("abc/efg/**/hij/**/klm/**/")]
|
||||
[InlineData("**/hij/**/klm")]
|
||||
[InlineData("**/hij/**")]
|
||||
[InlineData("/**/hij/**")]
|
||||
[InlineData("**/**/hij/**")]
|
||||
[InlineData("ab/**/**/hij/**")]
|
||||
[InlineData("ab/**/**/hij/**/")]
|
||||
[InlineData("/ab/**/**/hij/**/")]
|
||||
[InlineData("/ab/**/**/hij/**")]
|
||||
public void BuildLinearPatternNegative(string sample)
|
||||
{
|
||||
var builder = new PatternBuilder();
|
||||
var pattern = builder.Build(sample) as ILinearPattern;
|
||||
|
||||
Assert.Null(pattern);
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData("/abc/", 2, 1, 0, 0)]
|
||||
[InlineData("abc/", 2, 1, 0, 0)]
|
||||
[InlineData("abc/efg/", 3, 2, 0, 0)]
|
||||
[InlineData("abc/efg/h*j/*.*/", 5, 4, 0, 0)]
|
||||
[InlineData("abc/efg/**", 3, 2, 0, 0)]
|
||||
[InlineData("/abc/efg/**", 3, 2, 0, 0)]
|
||||
[InlineData("abc/efg/**/hij/klm", 5, 2, 0, 2)]
|
||||
[InlineData("abc/efg/**/hij/**/klm", 6, 2, 1, 1)]
|
||||
[InlineData("abc/efg/**/hij/**/klm/**", 7, 2, 2, 0)]
|
||||
[InlineData("abc/efg/**/hij/**/klm/**/", 8, 2, 2, 0)]
|
||||
[InlineData("**/hij/**/klm", 4, 0, 1, 1)]
|
||||
[InlineData("**/hij/**", 3, 0, 1, 0)]
|
||||
[InlineData("/**/hij/**", 3, 0, 1, 0)]
|
||||
[InlineData("**/**/hij/**", 4, 0, 1, 0)]
|
||||
[InlineData("ab/**/**/hij/**", 5, 1, 1, 0)]
|
||||
[InlineData("ab/**/**/hij/**/", 6, 1, 1, 0)]
|
||||
[InlineData("/ab/**/**/hij/**/", 6, 1, 1, 0)]
|
||||
[InlineData("/ab/**/**/hij/**", 5, 1, 1, 0)]
|
||||
[InlineData("**/*.suffix", 2, 0, 0, 1)]
|
||||
[InlineData("**.suffix", 2, 0, 0, 1)]
|
||||
[InlineData("ab/**.suffix", 3, 1, 0, 1)]
|
||||
public void BuildRaggedPattern(string sample,
|
||||
int segmentCount,
|
||||
int startSegmentsCount,
|
||||
int containSegmentCount,
|
||||
int endSegmentCount)
|
||||
{
|
||||
var builder = new PatternBuilder();
|
||||
var pattern = builder.Build(sample) as IRaggedPattern;
|
||||
|
||||
Assert.NotNull(pattern);
|
||||
Assert.Equal(segmentCount, pattern.Segments.Count);
|
||||
Assert.Equal(startSegmentsCount, pattern.StartsWith.Count);
|
||||
Assert.Equal(endSegmentCount, pattern.EndsWith.Count);
|
||||
Assert.Equal(containSegmentCount, pattern.Contains.Count);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("abc")]
|
||||
[InlineData("/abc")]
|
||||
[InlineData("abc/efg")]
|
||||
[InlineData("abc/efg/h*j")]
|
||||
[InlineData("abc/efg/h*j/*.*")]
|
||||
[InlineData("abc/efg/hij")]
|
||||
[InlineData("abc/efg/hij/klm")]
|
||||
public void BuildRaggedPatternNegative(string sample)
|
||||
{
|
||||
var builder = new PatternBuilder();
|
||||
var pattern = builder.Build(sample) as IRaggedPattern;
|
||||
|
||||
Assert.Null(pattern);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("a/../")]
|
||||
[InlineData("a/..")]
|
||||
[InlineData("/a/../")]
|
||||
[InlineData("./a/../")]
|
||||
[InlineData("**/../")]
|
||||
[InlineData("*.cs/../")]
|
||||
public void ThrowExceptionForInvalidParentsPath(string sample)
|
||||
{
|
||||
// parent segment is only allowed at the beginning of the pattern
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
var builder = new PatternBuilder();
|
||||
var pattern = builder.Build(sample);
|
||||
|
||||
Assert.Null(pattern);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ThrowExceptionForNull()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() =>
|
||||
{
|
||||
var builder = new PatternBuilder();
|
||||
builder.Build(null);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility
|
||||
{
|
||||
public class DisposableFileSystem : IDisposable
|
||||
{
|
||||
public DisposableFileSystem()
|
||||
{
|
||||
RootPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
Directory.CreateDirectory(RootPath);
|
||||
DirectoryInfo = new DirectoryInfo(RootPath);
|
||||
}
|
||||
|
||||
public string RootPath { get; }
|
||||
|
||||
public DirectoryInfo DirectoryInfo { get; }
|
||||
|
||||
public DisposableFileSystem CreateFolder(string path)
|
||||
{
|
||||
Directory.CreateDirectory(Path.Combine(RootPath, path));
|
||||
return this;
|
||||
}
|
||||
|
||||
public DisposableFileSystem CreateFile(string path)
|
||||
{
|
||||
File.WriteAllText(Path.Combine(RootPath, path), "temp");
|
||||
return this;
|
||||
}
|
||||
|
||||
public DisposableFileSystem CreateFiles(params string[] fileRelativePaths)
|
||||
{
|
||||
foreach (var path in fileRelativePaths)
|
||||
{
|
||||
var fullPath = Path.Combine(RootPath, path);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
|
||||
|
||||
File.WriteAllText(
|
||||
fullPath,
|
||||
string.Format("Automatically generated for testing on {0:yyyy}/{0:MM}/{0:dd} {0:hh}:{0:mm}:{0:ss}", DateTime.UtcNow));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(RootPath, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Don't throw if this fails.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility
|
||||
{
|
||||
internal class FileSystemGlobbingTestContext
|
||||
{
|
||||
private readonly string _basePath;
|
||||
private readonly FileSystemOperationRecorder _recorder;
|
||||
private readonly Matcher _patternMatching;
|
||||
|
||||
private MockDirectoryInfo _directoryInfo;
|
||||
|
||||
public PatternMatchingResult Result { get; private set; }
|
||||
|
||||
public FileSystemGlobbingTestContext(string basePath, Matcher matcher)
|
||||
{
|
||||
_basePath = basePath;
|
||||
_recorder = new FileSystemOperationRecorder();
|
||||
_patternMatching = matcher;
|
||||
|
||||
_directoryInfo = new MockDirectoryInfo(
|
||||
recorder: _recorder,
|
||||
parentDirectory: null,
|
||||
fullName: _basePath,
|
||||
name: ".",
|
||||
paths: new string[0]);
|
||||
}
|
||||
|
||||
public FileSystemGlobbingTestContext Include(params string[] patterns)
|
||||
{
|
||||
foreach (var pattern in patterns)
|
||||
{
|
||||
_patternMatching.AddInclude(pattern);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileSystemGlobbingTestContext Exclude(params string[] patterns)
|
||||
{
|
||||
foreach (var pattern in patterns)
|
||||
{
|
||||
_patternMatching.AddExclude(pattern);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileSystemGlobbingTestContext Files(params string[] files)
|
||||
{
|
||||
_directoryInfo = new MockDirectoryInfo(
|
||||
_directoryInfo.Recorder,
|
||||
_directoryInfo.ParentDirectory,
|
||||
_directoryInfo.FullName,
|
||||
_directoryInfo.Name,
|
||||
_directoryInfo.Paths.Concat(files.Select(file => _basePath + file)).ToArray());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileSystemGlobbingTestContext Execute()
|
||||
{
|
||||
Result = _patternMatching.Execute(_directoryInfo);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileSystemGlobbingTestContext AssertExact(params string[] files)
|
||||
{
|
||||
Assert.Equal(files.OrderBy(file => file), Result.Files.OrderBy(file => file.Path).Select(file => file.Path));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileSystemGlobbingTestContext SubDirectory(string name)
|
||||
{
|
||||
_directoryInfo = (MockDirectoryInfo)_directoryInfo.GetDirectory(name);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility
|
||||
{
|
||||
internal class FileSystemOperationRecorder
|
||||
{
|
||||
public IList<IDictionary<string, object>> Records = new List<IDictionary<string, object>>();
|
||||
|
||||
public void Add(string action, object values)
|
||||
{
|
||||
var record = new Dictionary<string, object>
|
||||
{
|
||||
{"action", action }
|
||||
};
|
||||
|
||||
foreach (var p in values.GetType().GetTypeInfo().DeclaredProperties)
|
||||
{
|
||||
record[p.Name] = p.GetValue(values);
|
||||
}
|
||||
|
||||
Records.Add(record);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Abstractions;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility
|
||||
{
|
||||
internal class MockDirectoryInfo : DirectoryInfoBase
|
||||
{
|
||||
public MockDirectoryInfo(
|
||||
FileSystemOperationRecorder recorder,
|
||||
DirectoryInfoBase parentDirectory,
|
||||
string fullName,
|
||||
string name,
|
||||
string[] paths)
|
||||
{
|
||||
ParentDirectory = parentDirectory;
|
||||
Recorder = recorder;
|
||||
FullName = fullName;
|
||||
Name = name;
|
||||
Paths = paths;
|
||||
}
|
||||
|
||||
public FileSystemOperationRecorder Recorder { get; }
|
||||
|
||||
public override string FullName { get; }
|
||||
|
||||
public override string Name { get; }
|
||||
|
||||
public override DirectoryInfoBase ParentDirectory { get; }
|
||||
|
||||
public string[] Paths { get; }
|
||||
|
||||
public override IEnumerable<FileSystemInfoBase> EnumerateFileSystemInfos()
|
||||
{
|
||||
Recorder.Add("EnumerateFileSystemInfos", new { FullName, Name });
|
||||
|
||||
var names = new HashSet<string>();
|
||||
|
||||
foreach (var path in Paths)
|
||||
{
|
||||
if (!path.Replace('\\', '/').StartsWith(FullName.Replace('\\', '/')))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var beginPath = FullName.Length;
|
||||
var endPath = path.Length;
|
||||
|
||||
var beginSegment = beginPath;
|
||||
var endSegment = NextIndex(path, new[] { '/', '\\' }, beginSegment, path.Length);
|
||||
|
||||
if (endPath == endSegment)
|
||||
{
|
||||
yield return new MockFileInfo(
|
||||
recorder: Recorder,
|
||||
parentDirectory: this,
|
||||
fullName: path,
|
||||
name: path.Substring(beginSegment, endSegment - beginSegment));
|
||||
}
|
||||
else
|
||||
{
|
||||
var name = path.Substring(beginSegment, endSegment - beginSegment);
|
||||
if (!names.Contains(name))
|
||||
{
|
||||
names.Add(name);
|
||||
yield return new MockDirectoryInfo(
|
||||
recorder: Recorder,
|
||||
parentDirectory: this,
|
||||
fullName: path.Substring(0, endSegment + 1),
|
||||
name: name,
|
||||
paths: Paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int NextIndex(string pattern, char[] anyOf, int startIndex, int endIndex)
|
||||
{
|
||||
var index = pattern.IndexOfAny(anyOf, startIndex, endIndex - startIndex);
|
||||
return index == -1 ? endIndex : index;
|
||||
}
|
||||
|
||||
public override DirectoryInfoBase GetDirectory(string name)
|
||||
{
|
||||
if (string.Equals(name, "..", StringComparison.Ordinal))
|
||||
{
|
||||
var indexOfPenultimateSlash = FullName.LastIndexOf('\\', FullName.Length - 2);
|
||||
var fullName = FullName.Substring(0, indexOfPenultimateSlash + 1);
|
||||
return new MockDirectoryInfo(
|
||||
recorder: Recorder,
|
||||
parentDirectory: this,
|
||||
fullName: FullName.Substring(0, indexOfPenultimateSlash + 1),
|
||||
name: name,
|
||||
paths: Paths);
|
||||
}
|
||||
return new MockDirectoryInfo(
|
||||
recorder: Recorder,
|
||||
parentDirectory: this,
|
||||
fullName: FullName + name + "\\",
|
||||
name: name,
|
||||
paths: Paths);
|
||||
}
|
||||
|
||||
public override FileInfoBase GetFile(string name)
|
||||
{
|
||||
return new MockFileInfo(
|
||||
recorder: Recorder,
|
||||
parentDirectory: this,
|
||||
fullName: FullName + name,
|
||||
name: name);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Abstractions;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility
|
||||
{
|
||||
internal class MockFileInfo : FileInfoBase
|
||||
{
|
||||
public MockFileInfo(
|
||||
FileSystemOperationRecorder recorder,
|
||||
DirectoryInfoBase parentDirectory,
|
||||
string fullName,
|
||||
string name)
|
||||
{
|
||||
Recorder = recorder;
|
||||
FullName = fullName;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public FileSystemOperationRecorder Recorder { get; }
|
||||
|
||||
public override DirectoryInfoBase ParentDirectory { get; }
|
||||
|
||||
public override string FullName { get; }
|
||||
|
||||
public override string Name { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternContexts
|
||||
{
|
||||
internal class MockLinearPatternBuilder
|
||||
{
|
||||
private List<IPathSegment> _segments;
|
||||
|
||||
public static MockLinearPatternBuilder New()
|
||||
{
|
||||
return new MockLinearPatternBuilder();
|
||||
}
|
||||
|
||||
private MockLinearPatternBuilder()
|
||||
{
|
||||
_segments = new List<IPathSegment>();
|
||||
}
|
||||
|
||||
public MockLinearPatternBuilder Add(string value)
|
||||
{
|
||||
_segments.Add(new MockNonRecursivePathSegment(value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockLinearPatternBuilder Add(string[] values)
|
||||
{
|
||||
_segments.AddRange(values.Select(v => new MockNonRecursivePathSegment(v)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ILinearPattern Build()
|
||||
{
|
||||
return new MockLinearPattern(_segments);
|
||||
}
|
||||
|
||||
class MockLinearPattern : ILinearPattern
|
||||
{
|
||||
public MockLinearPattern(List<IPathSegment> segments)
|
||||
{
|
||||
Segments = segments;
|
||||
}
|
||||
|
||||
public IList<IPathSegment> Segments { get; }
|
||||
|
||||
public IPatternContext CreatePatternContextForExclude()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IPatternContext CreatePatternContextForInclude()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternContexts
|
||||
{
|
||||
internal class MockNonRecursivePathSegment : IPathSegment
|
||||
{
|
||||
private readonly StringComparison _comparisonType;
|
||||
|
||||
public MockNonRecursivePathSegment(StringComparison comparisonType)
|
||||
{
|
||||
_comparisonType = comparisonType;
|
||||
}
|
||||
|
||||
public MockNonRecursivePathSegment(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public bool CanProduceStem { get { return false; } }
|
||||
|
||||
public string Value { get; }
|
||||
|
||||
public bool Match(string value)
|
||||
{
|
||||
return string.Compare(Value, value, _comparisonType) == 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternContexts
|
||||
{
|
||||
internal class MockRaggedPatternBuilder
|
||||
{
|
||||
private MockRaggedPattern _result;
|
||||
|
||||
public static MockRaggedPatternBuilder New()
|
||||
{
|
||||
return new MockRaggedPatternBuilder();
|
||||
}
|
||||
|
||||
private MockRaggedPatternBuilder()
|
||||
{
|
||||
_result = new MockRaggedPattern();
|
||||
}
|
||||
|
||||
public MockRaggedPatternBuilder AddStart(params string[] values)
|
||||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
var segment = new MockNonRecursivePathSegment(value);
|
||||
_result.StartsWith.Add(segment);
|
||||
_result.Segments.Add(segment);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockRaggedPatternBuilder AddContainsGroup(params string[] values)
|
||||
{
|
||||
var last = _result.Segments.Last();
|
||||
|
||||
if (!(last is MockRecursivePathSegment))
|
||||
{
|
||||
AddRecursive();
|
||||
}
|
||||
|
||||
var containSegment = new List<IPathSegment>();
|
||||
foreach (var value in values)
|
||||
{
|
||||
var segment = new MockNonRecursivePathSegment(value);
|
||||
containSegment.Add(segment);
|
||||
_result.Segments.Add(segment);
|
||||
}
|
||||
|
||||
_result.Contains.Add(containSegment);
|
||||
|
||||
AddRecursive();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockRaggedPatternBuilder AddEnd(params string[] values)
|
||||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
_result.EndsWith.Add(new MockNonRecursivePathSegment(value));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockRaggedPatternBuilder AddRecursive()
|
||||
{
|
||||
_result.Segments.Add(new MockRecursivePathSegment());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public IRaggedPattern Build()
|
||||
{
|
||||
return _result;
|
||||
}
|
||||
|
||||
class MockRaggedPattern : IRaggedPattern
|
||||
{
|
||||
public IList<IPathSegment> Segments { get; } = new List<IPathSegment>();
|
||||
|
||||
public IList<IPathSegment> StartsWith { get; } = new List<IPathSegment>();
|
||||
|
||||
public IList<IList<IPathSegment>> Contains { get; } = new List<IList<IPathSegment>>();
|
||||
|
||||
public IList<IPathSegment> EndsWith { get; } = new List<IPathSegment>();
|
||||
|
||||
public IPatternContext CreatePatternContextForExclude()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IPatternContext CreatePatternContextForInclude()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.PatternContexts
|
||||
{
|
||||
internal class MockRecursivePathSegment : IPathSegment
|
||||
{
|
||||
public bool CanProduceStem { get { return false; } }
|
||||
|
||||
public bool Match(string value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Internal;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.FileSystemGlobbing.Tests.TestUtility
|
||||
{
|
||||
internal static class PatternContextHelper
|
||||
{
|
||||
public static void PushDirectory(IPatternContext context, params string[] directoryNames)
|
||||
{
|
||||
foreach (var each in directoryNames)
|
||||
{
|
||||
var directory = new MockDirectoryInfo(null, null, string.Empty, each, null);
|
||||
context.PushDirectory(directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue