Skip to content

Commit 819c488

Browse files
committed
Add tests for DiagnosticVerifier
1 parent ba0e2bc commit 819c488

3 files changed

Lines changed: 381 additions & 0 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/Helpers/DiagnosticResult.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ public bool HasLocation
9393
}
9494
}
9595

96+
public DiagnosticResult WithSeverity(DiagnosticSeverity severity)
97+
{
98+
DiagnosticResult result = this;
99+
result.Severity = severity;
100+
return result;
101+
}
102+
96103
public DiagnosticResult WithArguments(params object[] arguments)
97104
{
98105
DiagnosticResult result = this;

StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@
412412
<Compile Include="SpecialRules\SA0002UnitTests.cs" />
413413
<Compile Include="Verifiers\CodeFixVerifier.cs" />
414414
<Compile Include="Verifiers\DiagnosticVerifier.cs" />
415+
<Compile Include="Verifiers\DiagnosticVerifierTests.cs" />
415416
</ItemGroup>
416417
<ItemGroup>
417418
<None Include="..\..\build\keys\TestingKey.snk">
Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
4+
namespace StyleCop.Analyzers.Test.Verifiers
5+
{
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Threading;
9+
using System.Threading.Tasks;
10+
using Microsoft.CodeAnalysis;
11+
using Microsoft.CodeAnalysis.CSharp;
12+
using Microsoft.CodeAnalysis.Diagnostics;
13+
using StyleCop.Analyzers.SpacingRules;
14+
using TestHelper;
15+
using Xunit;
16+
using Xunit.Sdk;
17+
18+
/// <summary>
19+
/// This class verifies that <see cref="DiagnosticVerifier"/> will correctly report failing tests.
20+
/// </summary>
21+
public class DiagnosticVerifierTests : DiagnosticVerifier
22+
{
23+
private bool throwException;
24+
25+
[Fact]
26+
public async Task TestExpectedDiagnosticMissingAsync()
27+
{
28+
string testCode = @"
29+
class ClassName
30+
{
31+
void MethodName()
32+
{
33+
;
34+
}
35+
}
36+
";
37+
38+
var expected = this.CSharpDiagnostic();
39+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
40+
async () =>
41+
{
42+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
43+
}).ConfigureAwait(false);
44+
Assert.StartsWith("Mismatch between number of diagnostics returned, expected \"1\" actual \"0\"", ex.Message);
45+
}
46+
47+
[Fact]
48+
public async Task TestValidBehaviorAsync()
49+
{
50+
string testCode = @"
51+
class ClassName
52+
{
53+
int property;
54+
int PropertyName
55+
{
56+
get{return this.property;}
57+
}
58+
}
59+
";
60+
61+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "followed").WithLocation(7, 33);
62+
63+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
64+
}
65+
66+
[Fact]
67+
public async Task TestValidBehaviorUncheckedLineAsync()
68+
{
69+
string testCode = @"
70+
class ClassName
71+
{
72+
int property;
73+
int PropertyName
74+
{
75+
get{return this.property;}
76+
}
77+
}
78+
";
79+
80+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "followed").WithLocation(0, 33);
81+
82+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
83+
}
84+
85+
[Fact]
86+
public async Task TestValidBehaviorUncheckedColumnAsync()
87+
{
88+
string testCode = @"
89+
class ClassName
90+
{
91+
int property;
92+
int PropertyName
93+
{
94+
get{return this.property;}
95+
}
96+
}
97+
";
98+
99+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "followed").WithLocation(7, 0);
100+
101+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
102+
}
103+
104+
[Fact]
105+
public async Task TestUnexpectedMessageAsync()
106+
{
107+
string testCode = @"
108+
class ClassName
109+
{
110+
int property;
111+
int PropertyName
112+
{
113+
get{return this.property;}
114+
}
115+
}
116+
";
117+
118+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
119+
async () =>
120+
{
121+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
122+
}).ConfigureAwait(false);
123+
Assert.StartsWith("Mismatch between number of diagnostics returned, expected \"0\" actual \"1\"", ex.Message);
124+
Assert.Contains("warning SA1002", ex.Message);
125+
}
126+
127+
[Fact]
128+
public async Task TestUnexpectedAnalyzerErrorAsync()
129+
{
130+
string testCode = @"
131+
class ClassName
132+
{
133+
void MethodName()
134+
{
135+
;
136+
}
137+
}
138+
";
139+
140+
this.throwException = true;
141+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
142+
async () =>
143+
{
144+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
145+
}).ConfigureAwait(false);
146+
Assert.StartsWith("Mismatch between number of diagnostics returned, expected \"0\" actual \"2\"", ex.Message);
147+
Assert.Contains("error AD0001", ex.Message);
148+
}
149+
150+
[Fact]
151+
public async Task TestUnexpectedCompilerErrorAsync()
152+
{
153+
string testCode = @"
154+
class ClassName
155+
{
156+
int property;
157+
Int32 PropertyName
158+
{
159+
get{return this.property;}
160+
}
161+
}
162+
";
163+
164+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "followed").WithLocation(7, 33);
165+
166+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
167+
async () =>
168+
{
169+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
170+
}).ConfigureAwait(false);
171+
Assert.StartsWith("Mismatch between number of diagnostics returned, expected \"1\" actual \"2\"", ex.Message);
172+
Assert.Contains("error CS0246", ex.Message);
173+
}
174+
175+
[Fact]
176+
public async Task TestUnexpectedCompilerWarningAsync()
177+
{
178+
string testCode = @"
179+
class ClassName
180+
{
181+
int property;
182+
Int32 PropertyName
183+
{
184+
///
185+
get{return this.property;}
186+
}
187+
}
188+
";
189+
190+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "followed").WithLocation(8, 33);
191+
192+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
193+
async () =>
194+
{
195+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
196+
}).ConfigureAwait(false);
197+
Assert.StartsWith("Mismatch between number of diagnostics returned, expected \"1\" actual \"2\"", ex.Message);
198+
Assert.Contains("error CS0246", ex.Message);
199+
}
200+
201+
[Fact]
202+
public async Task TestInvalidSeverityAsync()
203+
{
204+
string testCode = @"
205+
class ClassName
206+
{
207+
int property;
208+
int PropertyName
209+
{
210+
get{return this.property;}
211+
}
212+
}
213+
";
214+
215+
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(7, 33).WithSeverity(DiagnosticSeverity.Error);
216+
217+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
218+
async () =>
219+
{
220+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
221+
}).ConfigureAwait(false);
222+
Assert.StartsWith("Expected diagnostic severity to be \"Error\" was \"Warning\"", ex.Message);
223+
}
224+
225+
[Fact]
226+
public async Task TestIncorrectLocationLineAsync()
227+
{
228+
string testCode = @"
229+
class ClassName
230+
{
231+
int property;
232+
int PropertyName
233+
{
234+
get{return this.property;}
235+
}
236+
}
237+
";
238+
239+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "followed").WithLocation(8, 33);
240+
241+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
242+
async () =>
243+
{
244+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
245+
}).ConfigureAwait(false);
246+
Assert.StartsWith("Expected diagnostic to start on line \"8\" was actually on line \"7\"", ex.Message);
247+
}
248+
249+
[Fact]
250+
public async Task TestIncorrectLocationColumnAsync()
251+
{
252+
string testCode = @"
253+
class ClassName
254+
{
255+
int property;
256+
int PropertyName
257+
{
258+
get{return this.property;}
259+
}
260+
}
261+
";
262+
263+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "followed").WithLocation(7, 34);
264+
265+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
266+
async () =>
267+
{
268+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
269+
}).ConfigureAwait(false);
270+
Assert.StartsWith("Expected diagnostic to start at column \"34\" was actually at column \"33\"", ex.Message);
271+
}
272+
273+
[Fact]
274+
public async Task TestIncorrectLocationEndColumnAsync()
275+
{
276+
string testCode = @"
277+
class ClassName
278+
{
279+
int property;
280+
int PropertyName
281+
{
282+
get{return this.property;}
283+
}
284+
}
285+
";
286+
287+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "followed").WithSpan(7, 33, 7, 35);
288+
289+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
290+
async () =>
291+
{
292+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
293+
}).ConfigureAwait(false);
294+
Assert.StartsWith("Expected diagnostic to end at column \"35\" was actually at column \"34\"", ex.Message);
295+
}
296+
297+
[Fact]
298+
public async Task TestIncorrectMessageAsync()
299+
{
300+
string testCode = @"
301+
class ClassName
302+
{
303+
int property;
304+
int PropertyName
305+
{
306+
get{return this.property;}
307+
}
308+
}
309+
";
310+
311+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "bogus argument").WithLocation(7, 33);
312+
313+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
314+
async () =>
315+
{
316+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
317+
}).ConfigureAwait(false);
318+
Assert.StartsWith("Expected diagnostic message to be ", ex.Message);
319+
}
320+
321+
[Fact]
322+
public async Task TestIncorrectAdditionalLocationAsync()
323+
{
324+
string testCode = @"
325+
class ClassName
326+
{
327+
int property;
328+
int PropertyName
329+
{
330+
get{return this.property;}
331+
}
332+
}
333+
";
334+
335+
DiagnosticResult expected = this.CSharpDiagnostic().WithArguments(string.Empty, "bogus argument").WithLocation(7, 33).WithLocation(8, 34);
336+
337+
var ex = await Assert.ThrowsAnyAsync<XunitException>(
338+
async () =>
339+
{
340+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
341+
}).ConfigureAwait(false);
342+
Assert.StartsWith("Expected 1 additional locations but got 0 for Diagnostic", ex.Message);
343+
}
344+
345+
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
346+
{
347+
if (this.throwException)
348+
{
349+
yield return new ErrorThrowingAnalyzer();
350+
}
351+
else
352+
{
353+
yield return new SA1002SemicolonsMustBeSpacedCorrectly();
354+
}
355+
}
356+
357+
private class ErrorThrowingAnalyzer : SA1002SemicolonsMustBeSpacedCorrectly
358+
{
359+
private static readonly Action<SyntaxNodeAnalysisContext> BlockAction = HandleBlock;
360+
361+
/// <inheritdoc/>
362+
public override void Initialize(AnalysisContext context)
363+
{
364+
context.RegisterSyntaxNodeAction(BlockAction, SyntaxKind.Block);
365+
}
366+
367+
private static void HandleBlock(SyntaxNodeAnalysisContext context)
368+
{
369+
throw new NotImplementedException();
370+
}
371+
}
372+
}
373+
}

0 commit comments

Comments
 (0)