Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 206 additions & 0 deletions TUnit.Analyzers.Tests/TimeoutCancellationTokenAnalyzerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
using Verifier = TUnit.Analyzers.Tests.Verifiers.CSharpAnalyzerVerifier<TUnit.Analyzers.TimeoutCancellationTokenAnalyzer>;

namespace TUnit.Analyzers.Tests;

public class TimeoutCancellationTokenAnalyzerTests
{
[Test]
public async Task Test_Method_Without_CancellationToken_Shows_Error()
{
await Verifier.VerifyAnalyzerAsync(
"""
using TUnit.Core;
using System.Threading.Tasks;

public class TestClass
{
[Test]
[Timeout(30_000)]
public async Task {|#0:TestMethod|}()
{
await Task.Delay(100);
}
}
""",
Verifier.Diagnostic(Rules.MissingTimeoutCancellationTokenAttributes)
.WithLocation(0)
);
}

[Test]
public async Task Test_Method_With_CancellationToken_Shows_No_Error()
{
await Verifier.VerifyAnalyzerAsync(
"""
using TUnit.Core;
using System.Threading;
using System.Threading.Tasks;

public class TestClass
{
[Test]
[Timeout(30_000)]
public async Task TestMethod(CancellationToken cancellationToken)
{
await Task.Delay(100, cancellationToken);
}
}
"""
);
}

[Test]
public async Task Test_Method_With_Class_Level_Timeout_Without_CancellationToken_Shows_Error()
{
await Verifier.VerifyAnalyzerAsync(
"""
using TUnit.Core;
using System.Threading.Tasks;

[Timeout(30_000)]
public class TestClass
{
[Test]
public async Task {|#0:TestMethod|}()
{
await Task.Delay(100);
}
}
""",
Verifier.Diagnostic(Rules.MissingTimeoutCancellationTokenAttributes)
.WithLocation(0)
);
}

[Test]
public async Task Test_Method_With_Class_Level_Timeout_With_CancellationToken_Shows_No_Error()
{
await Verifier.VerifyAnalyzerAsync(
"""
using TUnit.Core;
using System.Threading;
using System.Threading.Tasks;

[Timeout(30_000)]
public class TestClass
{
[Test]
public async Task TestMethod(CancellationToken cancellationToken)
{
await Task.Delay(100, cancellationToken);
}
}
"""
);
}

[Test]
public async Task Non_Test_Method_With_Class_Level_Timeout_Shows_No_Error()
{
await Verifier.VerifyAnalyzerAsync(
"""
using System.Net.Http;
using TUnit.Core;
using System.Threading;
using System.Threading.Tasks;

[Timeout(30_000)]
public class TestClass
{
private static HttpClient GetHttpClient() => new HttpClient();

[Test]
public async Task TestMethod(CancellationToken cancellationToken)
{
var client = GetHttpClient();
await client.GetStringAsync("https://google.com/", cancellationToken);
}
}
"""
);
}

[Test]
public async Task Non_Test_Method_Internal_With_Class_Level_Timeout_Shows_No_Error()
{
await Verifier.VerifyAnalyzerAsync(
"""
using TUnit.Core;
using System.Threading;
using System.Threading.Tasks;

[Timeout(30_000)]
public class TestClass
{
internal void HelperMethod()
{
// Some helper logic
}

[Test]
public async Task TestMethod(CancellationToken cancellationToken)
{
HelperMethod();
await Task.Delay(100, cancellationToken);
}
}
"""
);
}

[Test]
public async Task Non_Test_Method_Private_With_Class_Level_Timeout_Shows_No_Error()
{
await Verifier.VerifyAnalyzerAsync(
"""
using TUnit.Core;
using System.Threading;
using System.Threading.Tasks;

[Timeout(30_000)]
public class TestClass
{
private async Task DoSomethingAsync()
{
await Task.Delay(100);
}

[Test]
public async Task TestMethod(CancellationToken cancellationToken)
{
await DoSomethingAsync();
await Task.Delay(100, cancellationToken);
}
}
"""
);
}

[Test]
public async Task Non_Test_Non_Hook_Method_With_Method_Level_Timeout_Shows_No_Error()
{
await Verifier.VerifyAnalyzerAsync(
"""
using TUnit.Core;
using System.Threading.Tasks;

public class TestClass
{
// This shouldn't happen in practice as Timeout should only be on test/hook methods,
// but the analyzer should not crash or report errors for non-test methods
[Timeout(30_000)]
private async Task HelperMethodWithTimeout()
{
await Task.Delay(100);
}

[Test]
public async Task TestMethod()
{
await HelperMethodWithTimeout();
}
}
"""
);
}
}
6 changes: 6 additions & 0 deletions TUnit.Analyzers/TimeoutCancellationTokenAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ private void AnalyzeSymbol(SymbolAnalysisContext context)
return;
}

if (!methodSymbol.IsTestMethod(context.Compilation) &&
!methodSymbol.IsHookMethod(context.Compilation, out _, out _, out _))
{
return;
}

var attributes = methodSymbol.GetAttributes()
.Concat(methodSymbol.ContainingType.GetAttributes());

Expand Down
Loading