Skip to content

Commit 4a752f7

Browse files
committed
Add performance tests
1 parent 185b18f commit 4a752f7

File tree

2 files changed

+265
-0
lines changed

2 files changed

+265
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
2+
3+
#pragma warning disable VSTHRD200 // Use "Async" suffix for async methods
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Collections.Immutable;
8+
using System.Linq;
9+
using System.Threading;
10+
using System.Threading.Tasks;
11+
using BenchmarkDotNet.Attributes;
12+
using Microsoft.CodeAnalysis.Diagnostics;
13+
using Microsoft.NetCore.CSharp.Analyzers.Performance;
14+
using PerformanceTests.Utilities;
15+
using PerfUtilities;
16+
17+
namespace CSharpPerformanceTests.Enabled
18+
{
19+
public class CSharp_CA1856
20+
{
21+
[IterationSetup]
22+
public static void CreateEnvironmentCA1856()
23+
{
24+
var sources = new List<(string name, string content)>();
25+
string attributeSource = @"#nullable enable
26+
namespace System.Diagnostics.CodeAnalysis
27+
{
28+
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
29+
public sealed class ConstantExpectedAttribute : Attribute
30+
{
31+
public object? Min { get; set; }
32+
public object? Max { get; set; }
33+
}
34+
}";
35+
sources.Add(("attributeSource", attributeSource));
36+
37+
for (var i = 0; i < Constants.Number_Of_Code_Files; i++)
38+
{
39+
var name = "TypeName" + i;
40+
sources.Add((name, @$"
41+
using System;
42+
using System.Diagnostics.CodeAnalysis;
43+
44+
class {name}
45+
{{
46+
public void Test([ConstantExpected(Min = 30, Max = 15)] int val) // diagnostic x2
47+
{{
48+
}}
49+
50+
public void Test2([ConstantExpected(Min = 0, Max = 15)] string val) // diagnostic x2
51+
{{
52+
}}
53+
54+
public void Test3<T>([ConstantExpected(Min = 0, Max = 15)] T val) // diagnostic
55+
{{
56+
}}
57+
58+
public void Test4([ConstantExpected(Min = 0, Max = int.MaxValue)] byte val) // diagnostic
59+
{{
60+
}}
61+
62+
}}
63+
"));
64+
}
65+
66+
var compilation = CSharpCompilationHelper.CreateAsync(sources.ToArray()).GetAwaiter().GetResult();
67+
BaselineCompilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(new EmptyAnalyzer()));
68+
CompilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(new CSharpConstantExpectedAnalyzer()));
69+
}
70+
71+
private static CompilationWithAnalyzers BaselineCompilationWithAnalyzers;
72+
private static CompilationWithAnalyzers CompilationWithAnalyzers;
73+
74+
[Benchmark]
75+
public async Task CA1856_DiagnosticsProduced()
76+
{
77+
var analysisResult = await CompilationWithAnalyzers.GetAnalysisResultAsync(CancellationToken.None);
78+
var diagnostics = analysisResult.GetAllDiagnostics(analysisResult.Analyzers.First());
79+
if (analysisResult.Analyzers.Length != 1)
80+
{
81+
throw new InvalidOperationException($"Expected a single analyzer but found '{analysisResult.Analyzers.Length}'");
82+
}
83+
84+
if (analysisResult.CompilationDiagnostics.Count != 0)
85+
{
86+
throw new InvalidOperationException($"Expected no compilation diagnostics but found '{analysisResult.CompilationDiagnostics.Count}'");
87+
}
88+
89+
if (diagnostics.Length != 6 * Constants.Number_Of_Code_Files)
90+
{
91+
throw new InvalidOperationException($"Expected '{6 * Constants.Number_Of_Code_Files:N0}' analyzer diagnostics but found '{diagnostics.Length}'");
92+
}
93+
}
94+
95+
[Benchmark(Baseline = true)]
96+
public async Task CA1856_Baseline()
97+
{
98+
var analysisResult = await BaselineCompilationWithAnalyzers.GetAnalysisResultAsync(CancellationToken.None);
99+
var diagnostics = analysisResult.GetAllDiagnostics(analysisResult.Analyzers.First());
100+
if (analysisResult.Analyzers.Length != 1)
101+
{
102+
throw new InvalidOperationException($"Expected a single analyzer but found '{analysisResult.Analyzers.Length}'");
103+
}
104+
105+
if (analysisResult.CompilationDiagnostics.Count != 0)
106+
{
107+
throw new InvalidOperationException($"Expected no compilation diagnostics but found '{analysisResult.CompilationDiagnostics.Count}'");
108+
}
109+
110+
if (diagnostics.Length != 0)
111+
{
112+
throw new InvalidOperationException($"Expected no analyzer diagnostics but found '{diagnostics.Length}'");
113+
}
114+
}
115+
}
116+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
2+
3+
#pragma warning disable VSTHRD200 // Use "Async" suffix for async methods
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Collections.Immutable;
8+
using System.Linq;
9+
using System.Threading;
10+
using System.Threading.Tasks;
11+
using BenchmarkDotNet.Attributes;
12+
using Microsoft.CodeAnalysis.Diagnostics;
13+
using Microsoft.NetCore.CSharp.Analyzers.Performance;
14+
using PerformanceTests.Utilities;
15+
using PerfUtilities;
16+
17+
namespace CSharpPerformanceTests.Enabled
18+
{
19+
public class CSharp_CA1857
20+
{
21+
[IterationSetup]
22+
public static void CreateEnvironmentCA1856()
23+
{
24+
var sources = new List<(string name, string content)>();
25+
string attributeSource = @"#nullable enable
26+
namespace System.Diagnostics.CodeAnalysis
27+
{
28+
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
29+
public sealed class ConstantExpectedAttribute : Attribute
30+
{
31+
public object? Min { get; set; }
32+
public object? Max { get; set; }
33+
}
34+
}";
35+
sources.Add(("attributeSource", attributeSource));
36+
37+
string testClass = @"
38+
using System;
39+
using System.Diagnostics.CodeAnalysis;
40+
#nullable enable
41+
42+
namespace ConstantExpectedTest
43+
{
44+
public class Test
45+
{
46+
public void TestMethodString([ConstantExpected] string val) { }
47+
public void TestMethodInt32([ConstantExpected] int val) { }
48+
public void TestMethodInt32Ex([ConstantExpected(Min = 0, Max = 15)] int val) { }
49+
public void TestMethodByte([ConstantExpected] byte val) { }
50+
public void TestMethodByteEx([ConstantExpected(Min = 0, Max = 7)] byte val) { }
51+
}
52+
public interface ITestInterface
53+
{
54+
void TestMethodT<T>([ConstantExpected] T val) { }
55+
}
56+
public interface ITestInterface2<T>
57+
{
58+
void TestMethod([ConstantExpected] T val) { }
59+
}
60+
}
61+
";
62+
sources.Add(("testClass", testClass));
63+
for (var i = 0; i < Constants.Number_Of_Code_Files; i++)
64+
{
65+
var name = "TypeName" + i;
66+
sources.Add((name, @$"
67+
using System;
68+
using ConstantExpectedTest;
69+
70+
class {name}
71+
{{
72+
private readonly Test _test;
73+
74+
public {name}(Test test)
75+
{{
76+
_test = test;
77+
}}
78+
79+
public void Test(int a)
80+
{{
81+
_test.TestMethodString(""Ok"");
82+
_test.TestMethodInt32(10);
83+
_test.TestMethodInt32Ex(10);
84+
_test.TestMethodInt32Ex(20); // diagnostic
85+
_test.TestMethodByte(10);
86+
_test.TestMethodByteEx(10); // diagnostic
87+
_test.TestMethodInt32Ex(a); // diagnostic
88+
}}
89+
90+
private sealed class TestImpl : ITestInterface, ITestInterface2<int>
91+
{{
92+
public void TestMethodT<T>( T val) {{ }} // diagnostic
93+
public void TestMethod(int val) {{ }} // diagnostic
94+
}}
95+
}}
96+
"));
97+
}
98+
99+
var compilation = CSharpCompilationHelper.CreateAsync(sources.ToArray()).GetAwaiter().GetResult();
100+
BaselineCompilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(new EmptyAnalyzer()));
101+
CompilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(new CSharpConstantExpectedAnalyzer()));
102+
}
103+
104+
private static CompilationWithAnalyzers BaselineCompilationWithAnalyzers;
105+
private static CompilationWithAnalyzers CompilationWithAnalyzers;
106+
107+
[Benchmark]
108+
public async Task CA1857_DiagnosticsProduced()
109+
{
110+
var analysisResult = await CompilationWithAnalyzers.GetAnalysisResultAsync(CancellationToken.None);
111+
var diagnostics = analysisResult.GetAllDiagnostics(analysisResult.Analyzers.First());
112+
if (analysisResult.Analyzers.Length != 1)
113+
{
114+
throw new InvalidOperationException($"Expected a single analyzer but found '{analysisResult.Analyzers.Length}'");
115+
}
116+
117+
if (analysisResult.CompilationDiagnostics.Count != 0)
118+
{
119+
throw new InvalidOperationException($"Expected no compilation diagnostics but found '{analysisResult.CompilationDiagnostics.Count}'");
120+
}
121+
122+
if (diagnostics.Length != 5 * Constants.Number_Of_Code_Files)
123+
{
124+
throw new InvalidOperationException($"Expected '{5 * Constants.Number_Of_Code_Files:N0}' analyzer diagnostics but found '{diagnostics.Length}'");
125+
}
126+
}
127+
128+
[Benchmark(Baseline = true)]
129+
public async Task CA1857_Baseline()
130+
{
131+
var analysisResult = await BaselineCompilationWithAnalyzers.GetAnalysisResultAsync(CancellationToken.None);
132+
var diagnostics = analysisResult.GetAllDiagnostics(analysisResult.Analyzers.First());
133+
if (analysisResult.Analyzers.Length != 1)
134+
{
135+
throw new InvalidOperationException($"Expected a single analyzer but found '{analysisResult.Analyzers.Length}'");
136+
}
137+
138+
if (analysisResult.CompilationDiagnostics.Count != 0)
139+
{
140+
throw new InvalidOperationException($"Expected no compilation diagnostics but found '{analysisResult.CompilationDiagnostics.Count}'");
141+
}
142+
143+
if (diagnostics.Length != 0)
144+
{
145+
throw new InvalidOperationException($"Expected no analyzer diagnostics but found '{diagnostics.Length}'");
146+
}
147+
}
148+
}
149+
}

0 commit comments

Comments
 (0)