Skip to content

Commit

Permalink
Exclude filter issue (#1728)
Browse files Browse the repository at this point in the history
* first tests

* some more test + refactoring

* update new unit tests

* refactoring

* test
  • Loading branch information
daveMueller authored Jan 15, 2025
1 parent 8eecb42 commit e3717da
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 12 deletions.
42 changes: 30 additions & 12 deletions src/coverlet.core/Helpers/InstrumentationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -360,38 +360,56 @@ private string GetModuleKeysForIncludeFilters(IEnumerable<string> filters, char
{
string[] validFilters = GetValidFilters(filters);

return !validFilters.Any() ? moduleKeys : GetModuleKeysForValidFilters(escapeSymbol, moduleKeys, validFilters);
return !validFilters.Any() ? moduleKeys : GetIncludeModuleKeysForValidFilters(escapeSymbol, moduleKeys, validFilters);
}

private string GetModuleKeysForExcludeFilters(IEnumerable<string> filters, char escapeSymbol, string moduleKeys)
{
string[] validFilters = GetValidFilters(filters);

return !validFilters.Any() ? string.Empty : GetModuleKeysForValidFilters(escapeSymbol, moduleKeys, validFilters);
return !validFilters.Any() ? string.Empty : GetExcludeModuleKeysForValidFilters(escapeSymbol, moduleKeys, validFilters);
}

private static string GetModuleKeysForValidFilters(char escapeSymbol, string moduleKeys, string[] validFilters)
private string[] GetValidFilters(IEnumerable<string> filters)
{
return (filters ?? Array.Empty<string>())
.Where(IsValidFilterExpression)
.Where(x => x.EndsWith("*"))
.ToArray();
}

private static string GetExcludeModuleKeysForValidFilters(char escapeSymbol, string moduleKeys, string[] validFilters)
{
string pattern = CreateRegexPattern(validFilters, escapeSymbol);
string pattern = CreateRegexExcludePattern(validFilters, escapeSymbol);
IEnumerable<Match> matches = Regex.Matches(moduleKeys, pattern, RegexOptions.IgnoreCase).Cast<Match>();

return string.Join(
Environment.NewLine,
matches.Where(x => x.Success).Select(x => x.Groups[0].Value));
}

private string[] GetValidFilters(IEnumerable<string> filters)
private static string GetIncludeModuleKeysForValidFilters(char escapeSymbol, string moduleKeys, string[] validFilters)
{
return (filters ?? Array.Empty<string>())
.Where(IsValidFilterExpression)
.Where(x => x.EndsWith("*"))
.ToArray();
string pattern = CreateRegexIncludePattern(validFilters, escapeSymbol);
IEnumerable<Match> matches = Regex.Matches(moduleKeys, pattern, RegexOptions.IgnoreCase).Cast<Match>();

return string.Join(
Environment.NewLine,
matches.Where(x => x.Success).Select(x => x.Groups[0].Value));
}

private static string CreateRegexPattern(IEnumerable<string> filters, char escapeSymbol)
private static string CreateRegexExcludePattern(IEnumerable<string> filters, char escapeSymbol)
//only look for module filters here, types will be filtered out when instrumenting
=> CreateRegexPattern(filters, escapeSymbol, filter => filter.Substring(filter.IndexOf(']') + 1) == "*");

private static string CreateRegexIncludePattern(IEnumerable<string> filters, char escapeSymbol) =>
CreateRegexPattern(filters, escapeSymbol);

private static string CreateRegexPattern(IEnumerable<string> filters, char escapeSymbol, Func<string, bool> filterPredicate = null)
{
IEnumerable<string> regexPatterns = filters.Select(x =>
$"{escapeSymbol}{WildcardToRegex(x.Substring(1, x.IndexOf(']') - 1)).Trim('^', '$')}{escapeSymbol}");
IEnumerable<string> filteredFilters = filterPredicate != null ? filters.Where(filterPredicate) : filters;
IEnumerable<string> regexPatterns = filteredFilters.Select(x =>
$"{escapeSymbol}{WildcardToRegex(x.Substring(1, x.IndexOf(']') - 1)).Trim('^', '$')}{escapeSymbol}");
return string.Join("|", regexPatterns);
}

Expand Down
25 changes: 25 additions & 0 deletions test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,30 @@ public void TestIsModuleExcludedAndIncludedWithMatchingAndMismatchingFilter(stri
Assert.Empty(result);
}

[Fact]
public void TestSelectModulesWithTypeFiltersDoesNotExcludeAssemblyWithType()
{
string[] modules = new[] { "Module.dll", "Module.Tests.dll" };
string[] includeFilters = new[] { "[*]Module*" };
string[] excludeFilters = new[] { "[*]Module.Tests.*" };

IEnumerable<string> result = _instrumentationHelper.SelectModules(modules, includeFilters, excludeFilters);

Assert.Equal(modules, result);
}

[Fact]
public void TestSelectModulesWithModuleFilterExcludesExpectedModules()
{
string[] modules = new[] { "ModuleA.dll", "ModuleA.Tests.dll", "ModuleB.dll", "Module.B.Tests.dll" };
string[] includeFilters = new[] { "" };
string[] excludeFilters = new[] { "[ModuleA*]*" };

IEnumerable<string> result = _instrumentationHelper.SelectModules(modules, includeFilters, excludeFilters);

Assert.Equal(["ModuleB.dll", "Module.B.Tests.dll"], result);
}

[Fact]
public void TestIsTypeExcludedWithoutFilter()
{
Expand Down Expand Up @@ -326,6 +350,7 @@ public void InstrumentationHelper_IsLocalMethod_ReturnsExpectedResult(string met
new object[] { "[Mod*le*]*" },
new object[] { "[Module?]*" },
new object[] { "[ModuleX?]*" },
new object[] { "[*]*" }
};

public static IEnumerable<object[]> ValidModuleAndNamespaceFilterData =>
Expand Down

0 comments on commit e3717da

Please sign in to comment.