Skip to content

Commit 18e22df

Browse files
committed
Add test to OnlyOneMethodCanBeBaselinePerCategory rule verifying that it works correctly with invalid string values
1 parent f6b41a9 commit 18e22df

File tree

2 files changed

+106
-10
lines changed

2 files changed

+106
-10
lines changed

src/BenchmarkDotNet.Analyzers/General/BenchmarkClassAnalyzer.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,8 +458,7 @@ private static void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context)
458458
{
459459
foreach (var benchmarkCategory in benchmarkCategoriesArray.Values)
460460
{
461-
// TODO: Check if this is necessary
462-
if (benchmarkCategory.Kind != TypedConstantKind.Error)
461+
if (benchmarkCategory.Kind == TypedConstantKind.Primitive)
463462
{
464463
if (benchmarkCategory.Value == null)
465464
{

tests/BenchmarkDotNet.Analyzers.Tests/AnalyzerTests/General/BenchmarkClassAnalyzerTests.cs

Lines changed: 105 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
using System.Linq;
1212
using System.Threading.Tasks;
1313

14-
// TODO: Verify which diagnostics rely on presence of [Benchmark] attribute on methods and test with 0, 2, or 3 attribute usages
15-
1614
public class BenchmarkClassAnalyzerTests
1715
{
1816
public class General : AnalyzerTestFixture<BenchmarkClassAnalyzer>
@@ -626,10 +624,6 @@ public class OnlyOneMethodCanBeBaseline : AnalyzerTestFixture<BenchmarkClassAnal
626624
{
627625
public OnlyOneMethodCanBeBaseline() : base(BenchmarkClassAnalyzer.OnlyOneMethodCanBeBaselineRule) { }
628626

629-
// TODO: Test with duplicate [Benchmark] attribute usage on same method (should not trigger diagnostic)
630-
// Category can contain multiple values separated by comma
631-
// Test with all types of array containers (see Parameter attribute tests)
632-
633627
[Theory, CombinatorialData]
634628
public async Task Class_with_only_one_benchmark_method_marked_as_baseline_should_not_trigger_diagnostic([CombinatorialMemberData(nameof(ClassAbstractModifiersEnumerableLocal))] string abstractModifier,
635629
bool useConstantsFromOtherClass,
@@ -1561,6 +1555,111 @@ public void BaselineBenchmarkMethod3()
15611555
await RunAsync();
15621556
}
15631557

1558+
[Theory, CombinatorialData]
1559+
public async Task Class_with_more_than_one_benchmark_method_marked_as_baseline_per_unique_category_with_unknown_values_should_not_trigger_diagnostic([CombinatorialMemberData(nameof(ClassAbstractModifiersEnumerableLocal))] string abstractModifier,
1560+
bool useConstantsFromOtherClass,
1561+
bool useLocalConstants,
1562+
[CombinatorialMemberData(nameof(BenchmarkCategoryAttributeValuesContainerEnumerableLocal), true)] string valuesContainer,
1563+
[CombinatorialValues("dummy_literal", "1", "true")] string invalidCategoryStringValue,
1564+
bool useDuplicateInSameClass)
1565+
{
1566+
var baselineBenchmarkAttributeUsage = $"[Benchmark(Baseline = {(useLocalConstants ? "_xTrue" : useConstantsFromOtherClass ? "Constants.Value1" : "true")})]";
1567+
var nonBaselineBenchmarkAttributeUsage = $"[Benchmark(Baseline = {(useLocalConstants ? "_xFalse" : useConstantsFromOtherClass ? "Constants.Value2" : "false")})]";
1568+
1569+
var testCode = /* lang=c#-test */ $$"""
1570+
using BenchmarkDotNet.Attributes;
1571+
1572+
public class BenchmarkClass : BenchmarkClassAncestor1
1573+
{
1574+
{{(useLocalConstants ? $"""
1575+
private const bool _xTrue = {(useConstantsFromOtherClass ? "Constants.Value1" : "true")};
1576+
private const bool _xFalse = {(useConstantsFromOtherClass ? "Constants.Value2" : "false")};
1577+
""" : "")}}
1578+
1579+
[BenchmarkCategory({{string.Format(valuesContainer, $"""
1580+
null, {invalidCategoryStringValue}, null, "TEST", "test2"
1581+
""")}})]
1582+
{{baselineBenchmarkAttributeUsage}}
1583+
public void BaselineBenchmarkMethod1()
1584+
{
1585+
1586+
}
1587+
1588+
[BenchmarkCategory({{string.Format(valuesContainer, "null, null")}})]
1589+
[BenchmarkCategory({{string.Format(valuesContainer, """
1590+
"test", null
1591+
""")}})]
1592+
[BenchmarkCategory({{string.Format(valuesContainer, """
1593+
"test2"
1594+
""")}})]
1595+
{{(useDuplicateInSameClass ? baselineBenchmarkAttributeUsage : "")}}
1596+
public void BaselineBenchmarkMethod2()
1597+
{
1598+
1599+
}
1600+
1601+
[BenchmarkCategory("Category1")]
1602+
{{nonBaselineBenchmarkAttributeUsage}}
1603+
public void NonBaselineBenchmarkMethod1()
1604+
{
1605+
1606+
}
1607+
1608+
[BenchmarkCategory("Category1")]
1609+
public void DummyMethod()
1610+
{
1611+
1612+
}
1613+
1614+
[Benchmark]
1615+
public void NonBaselineBenchmarkMethod2()
1616+
{
1617+
1618+
}
1619+
1620+
{{nonBaselineBenchmarkAttributeUsage}}
1621+
public void NonBaselineBenchmarkMethod3()
1622+
{
1623+
1624+
}
1625+
}
1626+
""";
1627+
1628+
var benchmarkClassAncestor1Document = /* lang=c#-test */ $$"""
1629+
public {{abstractModifier}}class BenchmarkClassAncestor1 : BenchmarkClassAncestor2
1630+
{
1631+
}
1632+
""";
1633+
1634+
var benchmarkClassAncestor2Document = /* lang=c#-test */ $$"""
1635+
using BenchmarkDotNet.Attributes;
1636+
1637+
public {{abstractModifier}}class BenchmarkClassAncestor2
1638+
{
1639+
{{(useLocalConstants ? $"private const bool _xTrue = {(useConstantsFromOtherClass ? "Constants.Value1" : "true")};" : "")}}
1640+
1641+
[BenchmarkCategory({{string.Format(valuesContainer, "null, null")}})]
1642+
[BenchmarkCategory({{string.Format(valuesContainer, $"{invalidCategoryStringValue}, null")}})]
1643+
[BenchmarkCategory({{string.Format(valuesContainer, """
1644+
"test2"
1645+
""")}})]
1646+
{{baselineBenchmarkAttributeUsage}}
1647+
public void BaselineBenchmarkMethod3()
1648+
{
1649+
1650+
}
1651+
}
1652+
""";
1653+
1654+
TestCode = testCode;
1655+
ReferenceConstants(("bool", "true"), ("bool", "false"));
1656+
AddSource(benchmarkClassAncestor1Document);
1657+
AddSource(benchmarkClassAncestor2Document);
1658+
DisableCompilerDiagnostics();
1659+
1660+
await RunAsync();
1661+
}
1662+
15641663
[Theory, CombinatorialData]
15651664
public async Task Class_with_more_than_one_benchmark_method_marked_as_baseline_per_unique_category_should_trigger_diagnostic([CombinatorialMemberData(nameof(ClassAbstractModifiersEnumerableLocal))] string abstractModifier,
15661665
bool useConstantsFromOtherClass,
@@ -1591,7 +1690,6 @@ public void BaselineBenchmarkMethod1()
15911690
15921691
}
15931692
1594-
15951693
[BenchmarkCategory({{string.Format(valuesContainer, "null, null")}})]
15961694
[BenchmarkCategory({{string.Format(valuesContainer, """
15971695
"test", null
@@ -1696,7 +1794,6 @@ public void BaselineBenchmarkMethod3()
16961794

16971795
public static IEnumerable<string> BenchmarkAttributeUsagesEnumerable => [ "", "[Benchmark] " ];
16981796

1699-
//TODO: Move to a common helper class
17001797
public static IEnumerable<string> EmptyBenchmarkCategoryAttributeArgumentEnumerable()
17011798
{
17021799
yield return "";

0 commit comments

Comments
 (0)