dotnet-installer/test/Microsoft.DotNet.ProjectModel.Tests/FileSystemGlobbing/FunctionalTests.cs

469 lines
24 KiB
C#

// 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);
}
}
}