diff --git a/TUnit.Analyzers.Tests/BeforeHookAsyncLocalAnalyzerTests.cs b/TUnit.Analyzers.Tests/BeforeHookAsyncLocalAnalyzerTests.cs index 3c91916b41..1727730ee1 100644 --- a/TUnit.Analyzers.Tests/BeforeHookAsyncLocalAnalyzerTests.cs +++ b/TUnit.Analyzers.Tests/BeforeHookAsyncLocalAnalyzerTests.cs @@ -20,49 +20,21 @@ public class MyClass { private static readonly AsyncLocal _asyncLocal = new(); - [Before(Test)] - public void {|#0:MyTest|}() + {|#0:[Before(Class)] + public void MyTest() { _asyncLocal.Value = 1; - } - } - """ - ); - } - - [Test] - public async Task Async_Raises_Error_Setting_AsyncLocal() - { - await Verifier - .VerifyAnalyzerAsync( - """ - using System.Threading; - using System.Threading.Tasks; - using TUnit.Core; - using static TUnit.Core.HookType; - - public class MyClass - { - private static readonly AsyncLocal _asyncLocal = new(); - - {|#1:[Before(Test)] - public async Task MyTest() - { - {|#0:_asyncLocal.Value = 1|}; - await Task.Yield(); }|} } """, - Verifier - .Diagnostic(Rules.AsyncLocalVoidMethod) + .Diagnostic(Rules.AsyncLocalCallFlowValues) .WithLocation(0) - .WithLocation(1) ); } [Test] - public async Task Async_Raises_Error_Setting_AsyncLocal_Nested_Method() + public async Task AddAsyncLocalValues_No_Error() { await Verifier .VerifyAnalyzerAsync( @@ -76,24 +48,13 @@ public class MyClass { private static readonly AsyncLocal _asyncLocal = new(); - {|#1:[Before(Test)] - public async Task MyTest() + {|#0:[Before(Class)] + public void MyTest(ClassHookContext context) { - SetAsyncLocal(); - await Task.Yield(); + _asyncLocal.Value = 1; + context.AddAsyncLocalValues(); }|} - - private void SetAsyncLocal() - { - {|#0:_asyncLocal.Value = 1|}; - } } - """, - - Verifier - .Diagnostic(Rules.AsyncLocalVoidMethod) - .WithLocation(0) - .WithLocation(1) - ); + """); } } \ No newline at end of file diff --git a/TUnit.Analyzers/BeforeHookAsyncLocalAnalyzer.cs b/TUnit.Analyzers/BeforeHookAsyncLocalAnalyzer.cs index 31b70efc3f..d0543cbbde 100644 --- a/TUnit.Analyzers/BeforeHookAsyncLocalAnalyzer.cs +++ b/TUnit.Analyzers/BeforeHookAsyncLocalAnalyzer.cs @@ -11,7 +11,7 @@ namespace TUnit.Analyzers; public class BeforeHookAsyncLocalAnalyzer : ConcurrentDiagnosticAnalyzer { public override ImmutableArray SupportedDiagnostics { get; } = - ImmutableArray.Create(Rules.AsyncLocalVoidMethod); + ImmutableArray.Create(Rules.AsyncLocalCallFlowValues); protected override void InitializeInternal(AnalysisContext context) { @@ -39,16 +39,31 @@ private void AnalyzeOperation(OperationAnalysisContext context) return; } - var parent = assignmentOperation.Parent; - while (parent != null) + var methodBodyOperation = GetParentMethod(assignmentOperation.Parent); + + if (methodBodyOperation is null) + { + return; + } + + CheckMethod(context, methodBodyOperation); + } + + private IMethodBodyOperation? GetParentMethod(IOperation? assignmentOperationParent) + { + var parent = assignmentOperationParent; + + while (parent is not null) { if (parent is IMethodBodyOperation methodBodyOperation) { - CheckMethod(context, methodBodyOperation); + return methodBodyOperation; } parent = parent.Parent; } + + return null; } private void CheckMethod(OperationAnalysisContext context, IMethodBodyOperation methodBodyOperation) @@ -59,19 +74,20 @@ private void CheckMethod(OperationAnalysisContext context, IMethodBodyOperation return; } - if (methodSymbol.IsHookMethod(context.Compilation, out _, out _, out var type) - && type is HookType.Before - && !methodSymbol.ReturnsVoid) + if (!methodSymbol.IsHookMethod(context.Compilation, out _, out _, out var type) + || type is not HookType.Before) { - context.ReportDiagnostic(Diagnostic.Create(Rules.AsyncLocalVoidMethod, - context.Operation.Syntax.GetLocation(), - [methodBodyOperation.Syntax.GetLocation()])); return; } - var invocations = methodBodyOperation.SemanticModel - .SyntaxTree - .GetRoot() + var syntax = methodSymbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(); + + if (syntax is null) + { + return; + } + + var invocations = syntax .DescendantNodes() .OfType(); @@ -84,36 +100,13 @@ private void CheckMethod(OperationAnalysisContext context, IMethodBodyOperation continue; } - if (!SymbolEqualityComparer.Default.Equals(invocationOperation.TargetMethod, methodSymbol)) + if (invocationOperation.TargetMethod.Name == "AddAsyncLocalValues") { - continue; + return; } - - var parentMethodBody = GetParentMethodBody(invocationOperation); - - if (parentMethodBody == null) - { - continue; - } - - CheckMethod(context, parentMethodBody); - } - } - - private IMethodBodyOperation? GetParentMethodBody(IInvocationOperation invocationOperation) - { - var parent = invocationOperation.Parent; - - while (parent != null) - { - if (parent is IMethodBodyOperation methodBodyOperation) - { - return methodBodyOperation; - } - - parent = parent.Parent; } - return null; + context.ReportDiagnostic(Diagnostic.Create(Rules.AsyncLocalCallFlowValues, + methodBodyOperation.Syntax.GetLocation())); } } \ No newline at end of file diff --git a/TUnit.Analyzers/Resources.Designer.cs b/TUnit.Analyzers/Resources.Designer.cs index de9a78effd..204a803be3 100644 --- a/TUnit.Analyzers/Resources.Designer.cs +++ b/TUnit.Analyzers/Resources.Designer.cs @@ -1302,7 +1302,7 @@ internal static string TUnit0046Title { } /// - /// Looks up a localized string similar to Before hooks setting AsyncLocal values should be non-async void returning methods.. + /// Looks up a localized string similar to For AsyncLocal values set in before hooks, you must call `context.AddAsyncLocalValues` to access them within tests.. /// internal static string TUnit0047Description { get { @@ -1311,7 +1311,7 @@ internal static string TUnit0047Description { } /// - /// Looks up a localized string similar to Before hooks setting AsyncLocal values should be non-async void returning methods.. + /// Looks up a localized string similar to For AsyncLocal values set in before hooks, you must call `context.AddAsyncLocalValues` to access them within tests.. /// internal static string TUnit0047MessageFormat { get { @@ -1320,7 +1320,7 @@ internal static string TUnit0047MessageFormat { } /// - /// Looks up a localized string similar to Before hooks setting AsyncLocal values should be non-async void returning methods. + /// Looks up a localized string similar to Call `context.AddAsyncLocalValues`. /// internal static string TUnit0047Title { get { diff --git a/TUnit.Analyzers/Resources.resx b/TUnit.Analyzers/Resources.resx index 87b419cf55..c3f3ebb771 100644 --- a/TUnit.Analyzers/Resources.resx +++ b/TUnit.Analyzers/Resources.resx @@ -433,13 +433,13 @@ Return a `Func<T>` rather than a `<T>` - Before hooks setting AsyncLocal values should be non-async void returning methods. + For AsyncLocal values set in before hooks, you must call `context.FlowAsyncLocalValues` to access them within tests. - Before hooks setting AsyncLocal values should be non-async void returning methods. + For AsyncLocal values set in before hooks, you must call `context.FlowAsyncLocalValues` to access them within tests. - Before hooks setting AsyncLocal values should be non-async void returning methods + Call `context.FlowAsyncLocalValues` Test methods must not be static. diff --git a/TUnit.Analyzers/Rules.cs b/TUnit.Analyzers/Rules.cs index f4057a8b03..a86cdcf730 100644 --- a/TUnit.Analyzers/Rules.cs +++ b/TUnit.Analyzers/Rules.cs @@ -108,7 +108,7 @@ public static class Rules public static readonly DiagnosticDescriptor ReturnFunc = CreateDescriptor("TUnit0046", UsageCategory, DiagnosticSeverity.Warning); - public static readonly DiagnosticDescriptor AsyncLocalVoidMethod = + public static readonly DiagnosticDescriptor AsyncLocalCallFlowValues = CreateDescriptor("TUnit0047", UsageCategory, DiagnosticSeverity.Warning); public static DiagnosticDescriptor InstanceTestMethod = diff --git a/TUnit.Core.SourceGenerator.Tests/AfterAllTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/AfterAllTests.Test.verified.txt index 0414fcb0fb..8351d7aea7 100644 --- a/TUnit.Core.SourceGenerator.Tests/AfterAllTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/AfterAllTests.Test.verified.txt @@ -70,7 +70,7 @@ file partial class Hooks_Base1 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base1.AfterAll1()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base1.AfterAll1()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -159,7 +159,7 @@ file partial class Hooks_Base1 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base1)classInstance).AfterEach1()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base1)classInstance).AfterEach1()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -246,7 +246,7 @@ file partial class Hooks_Base2 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base2.AfterAll2()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base2.AfterAll2()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -335,7 +335,7 @@ file partial class Hooks_Base2 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base2)classInstance).AfterEach2()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base2)classInstance).AfterEach2()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -422,7 +422,7 @@ file partial class Hooks_Base3 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base3.AfterAll3()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base3.AfterAll3()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -511,7 +511,7 @@ file partial class Hooks_Base3 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base3)classInstance).AfterEach3()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base3)classInstance).AfterEach3()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -598,7 +598,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUp()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUp()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -693,7 +693,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUpWithContext(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -788,7 +788,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUp(cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUp(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -888,7 +888,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUpWithContext(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -977,7 +977,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).Cleanup()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).Cleanup()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1073,7 +1073,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).Cleanup(cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).Cleanup(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1169,7 +1169,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).CleanupWithContext(context)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).CleanupWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1270,7 +1270,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).CleanupWithContext(context, cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).CleanupWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator.Tests/AfterTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/AfterTests.Test.verified.txt index 9a5e4fc3bf..0032008899 100644 --- a/TUnit.Core.SourceGenerator.Tests/AfterTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/AfterTests.Test.verified.txt @@ -70,7 +70,7 @@ file partial class Hooks_Base1 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base1.AfterAll1()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base1.AfterAll1()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -159,7 +159,7 @@ file partial class Hooks_Base1 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base1)classInstance).AfterEach1()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base1)classInstance).AfterEach1()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -246,7 +246,7 @@ file partial class Hooks_Base2 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base2.AfterAll2()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base2.AfterAll2()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -335,7 +335,7 @@ file partial class Hooks_Base2 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base2)classInstance).AfterEach2()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base2)classInstance).AfterEach2()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -422,7 +422,7 @@ file partial class Hooks_Base3 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base3.AfterAll3()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.Base3.AfterAll3()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -511,7 +511,7 @@ file partial class Hooks_Base3 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base3)classInstance).AfterEach3()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.Base3)classInstance).AfterEach3()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -598,7 +598,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUp()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUp()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -693,7 +693,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUpWithContext(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -788,7 +788,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUp(cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUp(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -888,7 +888,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUpWithContext(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.CleanupTests.AfterAllCleanUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -977,7 +977,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).Cleanup()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).Cleanup()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1073,7 +1073,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).Cleanup(cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).Cleanup(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1169,7 +1169,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).CleanupWithContext(context)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).CleanupWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1270,7 +1270,7 @@ file partial class Hooks_CleanupTests : global::TUnit.Core.Interfaces.SourceGene Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).CleanupWithContext(context, cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.CleanupTests)classInstance).CleanupWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator.Tests/AssemblyAfterTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/AssemblyAfterTests.Test.verified.txt index 7a1f5deb36..37d9d42e18 100644 --- a/TUnit.Core.SourceGenerator.Tests/AssemblyAfterTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/AssemblyAfterTests.Test.verified.txt @@ -70,7 +70,7 @@ file partial class Hooks_AssemblyBase1 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyBase1.AfterAll1()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyBase1.AfterAll1()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -159,7 +159,7 @@ file partial class Hooks_AssemblyBase1 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyBase1)classInstance).AfterEach1()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyBase1)classInstance).AfterEach1()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -246,7 +246,7 @@ file partial class Hooks_AssemblyBase2 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyBase2.AfterAll2()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyBase2.AfterAll2()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -335,7 +335,7 @@ file partial class Hooks_AssemblyBase2 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyBase2)classInstance).AfterEach2()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyBase2)classInstance).AfterEach2()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -422,7 +422,7 @@ file partial class Hooks_AssemblyBase3 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyBase3.AfterAll3()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyBase3.AfterAll3()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -511,7 +511,7 @@ file partial class Hooks_AssemblyBase3 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyBase3)classInstance).AfterEach3()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyBase3)classInstance).AfterEach3()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -598,7 +598,7 @@ file partial class Hooks_AssemblyCleanupTests : global::TUnit.Core.Interfaces.So Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyCleanupTests.AfterAllCleanUp()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyCleanupTests.AfterAllCleanUp()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -693,7 +693,7 @@ file partial class Hooks_AssemblyCleanupTests : global::TUnit.Core.Interfaces.So Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyCleanupTests.AfterAllCleanUpWithContext(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyCleanupTests.AfterAllCleanUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -788,7 +788,7 @@ file partial class Hooks_AssemblyCleanupTests : global::TUnit.Core.Interfaces.So Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyCleanupTests.AfterAllCleanUp(cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyCleanupTests.AfterAllCleanUp(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -888,7 +888,7 @@ file partial class Hooks_AssemblyCleanupTests : global::TUnit.Core.Interfaces.So Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyCleanupTests.AfterAllCleanUpWithContext(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.AssemblyCleanupTests.AfterAllCleanUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -977,7 +977,7 @@ file partial class Hooks_AssemblyCleanupTests : global::TUnit.Core.Interfaces.So Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyCleanupTests)classInstance).Cleanup()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyCleanupTests)classInstance).Cleanup()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1073,7 +1073,7 @@ file partial class Hooks_AssemblyCleanupTests : global::TUnit.Core.Interfaces.So Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyCleanupTests)classInstance).Cleanup(cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyCleanupTests)classInstance).Cleanup(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1169,7 +1169,7 @@ file partial class Hooks_AssemblyCleanupTests : global::TUnit.Core.Interfaces.So Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyCleanupTests)classInstance).CleanupWithContext(context)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyCleanupTests)classInstance).CleanupWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1270,7 +1270,7 @@ file partial class Hooks_AssemblyCleanupTests : global::TUnit.Core.Interfaces.So Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyCleanupTests)classInstance).CleanupWithContext(context, cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.AssemblyCleanupTests)classInstance).CleanupWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator.Tests/AssemblyBeforeTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/AssemblyBeforeTests.Test.verified.txt index 6b7103a383..887411ba45 100644 --- a/TUnit.Core.SourceGenerator.Tests/AssemblyBeforeTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/AssemblyBeforeTests.Test.verified.txt @@ -64,7 +64,7 @@ file partial class Hooks_AssemblyBase1 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblyBase1.BeforeAll1()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblyBase1.BeforeAll1()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -153,7 +153,7 @@ file partial class Hooks_AssemblyBase1 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblyBase1)classInstance).BeforeEach1()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblyBase1)classInstance).BeforeEach1()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -240,7 +240,7 @@ file partial class Hooks_AssemblyBase2 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblyBase2.BeforeAll2()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblyBase2.BeforeAll2()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -329,7 +329,7 @@ file partial class Hooks_AssemblyBase2 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblyBase2)classInstance).BeforeEach2()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblyBase2)classInstance).BeforeEach2()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -416,7 +416,7 @@ file partial class Hooks_AssemblyBase3 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblyBase3.BeforeAll3()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblyBase3.BeforeAll3()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -505,7 +505,7 @@ file partial class Hooks_AssemblyBase3 : global::TUnit.Core.Interfaces.SourceGen Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblyBase3)classInstance).BeforeEach3()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblyBase3)classInstance).BeforeEach3()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -592,7 +592,7 @@ file partial class Hooks_AssemblySetupTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblySetupTests.BeforeAllSetUp()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblySetupTests.BeforeAllSetUp()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -687,7 +687,7 @@ file partial class Hooks_AssemblySetupTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblySetupTests.BeforeAllSetUpWithContext(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblySetupTests.BeforeAllSetUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -782,7 +782,7 @@ file partial class Hooks_AssemblySetupTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblySetupTests.BeforeAllSetUp(cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblySetupTests.BeforeAllSetUp(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -882,7 +882,7 @@ file partial class Hooks_AssemblySetupTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblySetupTests.BeforeAllSetUpWithContext(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.AssemblySetupTests.BeforeAllSetUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -971,7 +971,7 @@ file partial class Hooks_AssemblySetupTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblySetupTests)classInstance).Setup()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblySetupTests)classInstance).Setup()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1067,7 +1067,7 @@ file partial class Hooks_AssemblySetupTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblySetupTests)classInstance).Setup(cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblySetupTests)classInstance).Setup(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1163,7 +1163,7 @@ file partial class Hooks_AssemblySetupTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblySetupTests)classInstance).SetupWithContext(context)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblySetupTests)classInstance).SetupWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1264,7 +1264,7 @@ file partial class Hooks_AssemblySetupTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblySetupTests)classInstance).SetupWithContext(context, cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.AssemblySetupTests)classInstance).SetupWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator.Tests/BeforeAllTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/BeforeAllTests.Test.verified.txt index 37f1354d96..9ed959ec3d 100644 --- a/TUnit.Core.SourceGenerator.Tests/BeforeAllTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/BeforeAllTests.Test.verified.txt @@ -64,7 +64,7 @@ file partial class Hooks_Base1 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base1.BeforeAll1()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base1.BeforeAll1()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -153,7 +153,7 @@ file partial class Hooks_Base1 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base1)classInstance).BeforeEach1()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base1)classInstance).BeforeEach1()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -240,7 +240,7 @@ file partial class Hooks_Base2 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base2.BeforeAll2()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base2.BeforeAll2()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -329,7 +329,7 @@ file partial class Hooks_Base2 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base2)classInstance).BeforeEach2()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base2)classInstance).BeforeEach2()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -416,7 +416,7 @@ file partial class Hooks_Base3 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base3.BeforeAll3()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base3.BeforeAll3()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -505,7 +505,7 @@ file partial class Hooks_Base3 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base3)classInstance).BeforeEach3()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base3)classInstance).BeforeEach3()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -592,7 +592,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUp()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUp()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -687,7 +687,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUpWithContext(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -782,7 +782,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUp(cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUp(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -882,7 +882,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUpWithContext(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -971,7 +971,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).Setup()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).Setup()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1067,7 +1067,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).Setup(cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).Setup(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1163,7 +1163,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).SetupWithContext(context)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).SetupWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1264,7 +1264,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).SetupWithContext(context, cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).SetupWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator.Tests/BeforeTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/BeforeTests.Test.verified.txt index fdb373ab96..d41c7f96bb 100644 --- a/TUnit.Core.SourceGenerator.Tests/BeforeTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/BeforeTests.Test.verified.txt @@ -64,7 +64,7 @@ file partial class Hooks_Base1 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base1.BeforeAll1()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base1.BeforeAll1()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -153,7 +153,7 @@ file partial class Hooks_Base1 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base1)classInstance).BeforeEach1()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base1)classInstance).BeforeEach1()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -240,7 +240,7 @@ file partial class Hooks_Base2 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base2.BeforeAll2()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base2.BeforeAll2()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -329,7 +329,7 @@ file partial class Hooks_Base2 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base2)classInstance).BeforeEach2()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base2)classInstance).BeforeEach2()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -416,7 +416,7 @@ file partial class Hooks_Base3 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base3.BeforeAll3()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.Base3.BeforeAll3()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -505,7 +505,7 @@ file partial class Hooks_Base3 : global::TUnit.Core.Interfaces.SourceGenerator.I Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base3)classInstance).BeforeEach3()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.Base3)classInstance).BeforeEach3()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -592,7 +592,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUp()), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUp()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -687,7 +687,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUpWithContext(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -782,7 +782,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUp(cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUp(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -882,7 +882,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUpWithContext(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.SetupTests.BeforeAllSetUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -971,7 +971,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).Setup()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).Setup()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1067,7 +1067,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).Setup(cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).Setup(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1163,7 +1163,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).SetupWithContext(context)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).SetupWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -1264,7 +1264,7 @@ file partial class Hooks_SetupTests : global::TUnit.Core.Interfaces.SourceGenera Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).SetupWithContext(context, cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.SetupTests)classInstance).SetupWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator.Tests/GlobalStaticAfterEachTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/GlobalStaticAfterEachTests.Test.verified.txt index b87a146911..b7881d8ca1 100644 --- a/TUnit.Core.SourceGenerator.Tests/GlobalStaticAfterEachTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/GlobalStaticAfterEachTests.Test.verified.txt @@ -71,7 +71,7 @@ file partial class Hooks_GlobalBase1 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalBase1)classInstance).AfterEach1()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalBase1)classInstance).AfterEach1()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -159,7 +159,7 @@ file partial class Hooks_GlobalBase2 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalBase2)classInstance).AfterEach2()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalBase2)classInstance).AfterEach2()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -247,7 +247,7 @@ file partial class Hooks_GlobalBase3 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalBase3)classInstance).AfterEach3()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalBase3)classInstance).AfterEach3()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -335,7 +335,7 @@ file partial class Hooks_GlobalCleanUpTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalCleanUpTests)classInstance).CleanUp()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalCleanUpTests)classInstance).CleanUp()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -431,7 +431,7 @@ file partial class Hooks_GlobalCleanUpTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalCleanUpTests)classInstance).CleanUp(cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalCleanUpTests)classInstance).CleanUp(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -527,7 +527,7 @@ file partial class Hooks_GlobalCleanUpTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalCleanUpTests)classInstance).CleanUpWithContext(context)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalCleanUpTests)classInstance).CleanUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -628,7 +628,7 @@ file partial class Hooks_GlobalCleanUpTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalCleanUpTests)classInstance).CleanUpWithContext(context, cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.AfterTests.GlobalCleanUpTests)classInstance).CleanUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -711,7 +711,7 @@ file partial class Hooks_GlobalBase1 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalBase1.AfterAll1(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalBase1.AfterAll1(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -806,7 +806,7 @@ file partial class Hooks_GlobalBase2 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalBase2.AfterAll2(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalBase2.AfterAll2(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -901,7 +901,7 @@ file partial class Hooks_GlobalBase3 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalBase3.AfterAll3(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalBase3.AfterAll3(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -996,7 +996,7 @@ file partial class Hooks_GlobalCleanUpTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalCleanUpTests.AfterAllCleanUp(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalCleanUpTests.AfterAllCleanUp(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -1096,7 +1096,7 @@ file partial class Hooks_GlobalCleanUpTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalCleanUpTests.AfterAllCleanUp(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalCleanUpTests.AfterAllCleanUp(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -1191,7 +1191,7 @@ file partial class Hooks_GlobalCleanUpTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalCleanUpTests.AfterAllCleanUpWithContext(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalCleanUpTests.AfterAllCleanUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -1291,7 +1291,7 @@ file partial class Hooks_GlobalCleanUpTests : global::TUnit.Core.Interfaces.Sour Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalCleanUpTests.AfterAllCleanUpWithContext(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.AfterTests.GlobalCleanUpTests.AfterAllCleanUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", diff --git a/TUnit.Core.SourceGenerator.Tests/GlobalStaticBeforeEachTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/GlobalStaticBeforeEachTests.Test.verified.txt index 6a6264eae4..1b0e4f40bb 100644 --- a/TUnit.Core.SourceGenerator.Tests/GlobalStaticBeforeEachTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/GlobalStaticBeforeEachTests.Test.verified.txt @@ -65,7 +65,7 @@ file partial class Hooks_GlobalBase1 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalBase1)classInstance).BeforeEach1()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalBase1)classInstance).BeforeEach1()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -153,7 +153,7 @@ file partial class Hooks_GlobalBase2 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalBase2)classInstance).BeforeEach2()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalBase2)classInstance).BeforeEach2()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -241,7 +241,7 @@ file partial class Hooks_GlobalBase3 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalBase3)classInstance).BeforeEach3()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalBase3)classInstance).BeforeEach3()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -329,7 +329,7 @@ file partial class Hooks_GlobalSetUpTests : global::TUnit.Core.Interfaces.Source Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalSetUpTests)classInstance).SetUp()), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalSetUpTests)classInstance).SetUp()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -425,7 +425,7 @@ file partial class Hooks_GlobalSetUpTests : global::TUnit.Core.Interfaces.Source Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalSetUpTests)classInstance).SetUp(cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalSetUpTests)classInstance).SetUp(cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -521,7 +521,7 @@ file partial class Hooks_GlobalSetUpTests : global::TUnit.Core.Interfaces.Source Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalSetUpTests)classInstance).SetUpWithContext(context)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalSetUpTests)classInstance).SetUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -622,7 +622,7 @@ file partial class Hooks_GlobalSetUpTests : global::TUnit.Core.Interfaces.Source Properties = [], }), }, - AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalSetUpTests)classInstance).SetUpWithContext(context, cancellationToken)), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.BeforeTests.GlobalSetUpTests)classInstance).SetUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -705,7 +705,7 @@ file partial class Hooks_GlobalBase1 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalBase1.BeforeAll1(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalBase1.BeforeAll1(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -800,7 +800,7 @@ file partial class Hooks_GlobalBase2 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalBase2.BeforeAll2(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalBase2.BeforeAll2(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -895,7 +895,7 @@ file partial class Hooks_GlobalBase3 : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalBase3.BeforeAll3(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalBase3.BeforeAll3(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -990,7 +990,7 @@ file partial class Hooks_GlobalSetUpTests : global::TUnit.Core.Interfaces.Source Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalSetUpTests.BeforeAllSetUp(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalSetUpTests.BeforeAllSetUp(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -1090,7 +1090,7 @@ file partial class Hooks_GlobalSetUpTests : global::TUnit.Core.Interfaces.Source Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalSetUpTests.BeforeAllSetUp(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalSetUpTests.BeforeAllSetUp(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -1185,7 +1185,7 @@ file partial class Hooks_GlobalSetUpTests : global::TUnit.Core.Interfaces.Source Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalSetUpTests.BeforeAllSetUpWithContext(context)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalSetUpTests.BeforeAllSetUpWithContext(context)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", @@ -1285,7 +1285,7 @@ file partial class Hooks_GlobalSetUpTests : global::TUnit.Core.Interfaces.Source Properties = [], }), }, - AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalSetUpTests.BeforeAllSetUpWithContext(context, cancellationToken)), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.BeforeTests.GlobalSetUpTests.BeforeAllSetUpWithContext(context, cancellationToken)), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", diff --git a/TUnit.Core.SourceGenerator.Tests/Hooks1589.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Hooks1589.Test.verified.txt index 9e0884f0dc..b53199f5cb 100644 --- a/TUnit.Core.SourceGenerator.Tests/Hooks1589.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Hooks1589.Test.verified.txt @@ -65,7 +65,7 @@ file partial class Hooks_BaseTests : global::TUnit.Core.Interfaces.SourceGenerat Properties = [], }), }, - Body = (classInstance, context, cancellationToken) => classInstance.GetType().GetMethod("Setup", []).Invoke(classInstance, []), + Body = (classInstance, context, cancellationToken) => AsyncConvert.ConvertObject(() => classInstance.GetType().GetMethod("Setup", []).Invoke(classInstance, [])), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -128,7 +128,7 @@ new global::TUnit.Core.SourceGeneratedPropertyInformation ], }), }, - Body = (classInstance, context, cancellationToken) => ((global::TUnit.TestProject.Bugs._1589.BaseTests)classInstance).Setup(), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.Bugs._1589.BaseTests)classInstance).Setup()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator.Tests/Hooks1594.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Hooks1594.Test.verified.txt index ee81d3dfaa..7914bbc091 100644 --- a/TUnit.Core.SourceGenerator.Tests/Hooks1594.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Hooks1594.Test.verified.txt @@ -72,7 +72,7 @@ file partial class Hooks_MyTests : global::TUnit.Core.Interfaces.SourceGenerator Properties = [], }), }, - Body = (classInstance, context, cancellationToken) => ((global::TUnit.TestProject.Bugs._1594.MyTests)classInstance).SetupMyTests(), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.Bugs._1594.MyTests)classInstance).SetupMyTests()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -160,7 +160,7 @@ file partial class Hooks_ParentTests : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - Body = (classInstance, context, cancellationToken) => classInstance.GetType().GetMethod("SetupParentTests", []).Invoke(classInstance, []), + Body = (classInstance, context, cancellationToken) => AsyncConvert.ConvertObject(() => classInstance.GetType().GetMethod("SetupParentTests", []).Invoke(classInstance, [])), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -207,7 +207,7 @@ file partial class Hooks_ParentTests : global::TUnit.Core.Interfaces.SourceGener Properties = [], }), }, - Body = (classInstance, context, cancellationToken) => ((global::TUnit.TestProject.Bugs._1594.ParentTests)classInstance).SetupParentTests(), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.Bugs._1594.ParentTests)classInstance).SetupParentTests()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -295,7 +295,7 @@ file partial class Hooks_GrandParentTests : global::TUnit.Core.Interfaces.Source Properties = [], }), }, - Body = (classInstance, context, cancellationToken) => classInstance.GetType().GetMethod("SetupBase", []).Invoke(classInstance, []), + Body = (classInstance, context, cancellationToken) => AsyncConvert.ConvertObject(() => classInstance.GetType().GetMethod("SetupBase", []).Invoke(classInstance, [])), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = @@ -351,7 +351,7 @@ new global::TUnit.Core.SourceGeneratedPropertyInformation ], }), }, - Body = (classInstance, context, cancellationToken) => ((global::TUnit.TestProject.Bugs._1594.GrandParentTests)classInstance).SetupBase(), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.Bugs._1594.GrandParentTests)classInstance).SetupBase()), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator.Tests/STAThreadHooksTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/STAThreadHooksTests.Test.verified.txt index 8f8bafd2f5..c96a22fef2 100644 --- a/TUnit.Core.SourceGenerator.Tests/STAThreadHooksTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/STAThreadHooksTests.Test.verified.txt @@ -69,7 +69,7 @@ file partial class Hooks_STAThreadTests : global::TUnit.Core.Interfaces.SourceGe Properties = [], }), }, - Body = (classInstance, context, cancellationToken) => ((global::TUnit.TestProject.STAThreadTests)classInstance).BeforeTest(), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.STAThreadTests)classInstance).BeforeTest()), HookExecutor = new global::TUnit.Core.STAThreadExecutor(), Order = 0, MethodAttributes = @@ -171,7 +171,7 @@ file partial class Hooks_STAThreadTests : global::TUnit.Core.Interfaces.SourceGe Properties = [], }), }, - Body = (classInstance, context, cancellationToken) => ((global::TUnit.TestProject.STAThreadTests)classInstance).AfterTest(), + Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => ((global::TUnit.TestProject.STAThreadTests)classInstance).AfterTest()), HookExecutor = new global::TUnit.Core.STAThreadExecutor(), Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator.Tests/TestDiscoveryHookTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/TestDiscoveryHookTests.Test.verified.txt index d113791923..4c6030ee4b 100644 --- a/TUnit.Core.SourceGenerator.Tests/TestDiscoveryHookTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/TestDiscoveryHookTests.Test.verified.txt @@ -55,7 +55,7 @@ file partial class Hooks_TestDiscoveryHookTests : global::TUnit.Core.Interfaces. Properties = [], }), }, - Body = (context, cancellationToken) => global::TUnit.TestProject.TestDiscoveryHookTests.BeforeDiscovery(), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.TestDiscoveryHookTests.BeforeDiscovery()), HookExecutor = DefaultExecutor.Instance, Order = 5, FilePath = @"", @@ -140,7 +140,7 @@ file partial class Hooks_TestDiscoveryHookTests : global::TUnit.Core.Interfaces. Properties = [], }), }, - Body = (context, cancellationToken) => global::TUnit.TestProject.TestDiscoveryHookTests.AfterDiscovery(), + Body = (context, cancellationToken) => AsyncConvert.Convert(() => global::TUnit.TestProject.TestDiscoveryHookTests.AfterDiscovery()), HookExecutor = DefaultExecutor.Instance, Order = 0, FilePath = @"", diff --git a/TUnit.Core.SourceGenerator.Tests/Tests1899.BaseClass.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests1899.BaseClass.verified.txt index b3e91767f3..206f6bcb49 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests1899.BaseClass.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests1899.BaseClass.verified.txt @@ -65,7 +65,7 @@ file partial class Hooks_BaseClass : global::TUnit.Core.Interfaces.SourceGenerat Properties = [], }), }, - Body = (classInstance, context, cancellationToken) => classInstance.GetType().GetMethod("Setup", []).Invoke(classInstance, []), + Body = (classInstance, context, cancellationToken) => AsyncConvert.ConvertObject(() => classInstance.GetType().GetMethod("Setup", []).Invoke(classInstance, [])), HookExecutor = DefaultExecutor.Instance, Order = 0, MethodAttributes = diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/AssemblyHooksWriter.cs b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/AssemblyHooksWriter.cs index 35f534b6d4..7d3406e760 100644 --- a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/AssemblyHooksWriter.cs +++ b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/AssemblyHooksWriter.cs @@ -27,15 +27,8 @@ public static void Execute(SourceCodeWriter sourceBuilder, HooksDataModel? model sourceBuilder.WriteTabs(); sourceBuilder.Write("MethodInfo = "); SourceInformationWriter.GenerateMethodInformation(sourceBuilder, model.Context, model.ClassType, model.Method, null, ','); - - if (model.IsVoid) - { - sourceBuilder.WriteLine($"Body = (context, cancellationToken) => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model)}),"); - } - else - { - sourceBuilder.WriteLine($"AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model)})),"); - } + + sourceBuilder.WriteLine($"Body = (context, cancellationToken) => AsyncConvert.Convert(() => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model)})),"); sourceBuilder.WriteLine($"HookExecutor = {HookExecutorHelper.GetHookExecutor(model.HookExecutor)},"); sourceBuilder.WriteLine($"Order = {model.Order},"); diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/ClassHooksWriter.cs b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/ClassHooksWriter.cs index 84fb9fe47f..5eb741dcaf 100644 --- a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/ClassHooksWriter.cs +++ b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/ClassHooksWriter.cs @@ -22,15 +22,8 @@ public static void Execute(SourceCodeWriter sourceBuilder, HooksDataModel model) sourceBuilder.WriteTabs(); sourceBuilder.Write("MethodInfo = "); SourceInformationWriter.GenerateMethodInformation(sourceBuilder, model.Context, model.ClassType, model.Method, null, ','); - - if (model.IsVoid) - { - sourceBuilder.WriteLine($"Body = (context, cancellationToken) => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model)}),"); - } - else - { - sourceBuilder.WriteLine($"AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model)})),"); - } + + sourceBuilder.WriteLine($"Body = (context, cancellationToken) => AsyncConvert.Convert(() => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model)})),"); sourceBuilder.WriteLine($"HookExecutor = {HookExecutorHelper.GetHookExecutor(model.HookExecutor)},"); sourceBuilder.WriteLine($"Order = {model.Order},"); diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/GlobalTestHooksWriter.cs b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/GlobalTestHooksWriter.cs index 452e72789d..0369073fbd 100644 --- a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/GlobalTestHooksWriter.cs +++ b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/GlobalTestHooksWriter.cs @@ -15,17 +15,8 @@ public static void Execute(SourceCodeWriter sourceBuilder, HooksDataModel model) sourceBuilder.WriteTabs(); sourceBuilder.Write("MethodInfo = "); SourceInformationWriter.GenerateMethodInformation(sourceBuilder, model.Context, model.ClassType, model.Method, null, ','); - - if (model.IsVoid) - { - sourceBuilder.WriteLine( - $"Body = (context, cancellationToken) => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model, model.HookLocationType)}),"); - } - else - { - sourceBuilder.WriteLine( - $"AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model, model.HookLocationType)})),"); - } + + sourceBuilder.WriteLine($"Body = (context, cancellationToken) => AsyncConvert.Convert(() => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model, model.HookLocationType)})),"); sourceBuilder.WriteLine($"HookExecutor = {HookExecutorHelper.GetHookExecutor(model.HookExecutor)},"); sourceBuilder.WriteLine($"Order = {model.Order},"); diff --git a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/TestHooksWriter.cs b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/TestHooksWriter.cs index b593adff45..9a79780408 100644 --- a/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/TestHooksWriter.cs +++ b/TUnit.Core.SourceGenerator/CodeGenerators/Writers/Hooks/TestHooksWriter.cs @@ -25,14 +25,7 @@ public static void Execute(SourceCodeWriter sourceBuilder, HooksDataModel model) sourceBuilder.Write("MethodInfo = "); SourceInformationWriter.GenerateMethodInformation(sourceBuilder, model.Context, model.ClassType, model.Method, null, ','); - if (model.IsVoid) - { - sourceBuilder.WriteLine($"Body = (context, cancellationToken) => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model)}),"); - } - else - { - sourceBuilder.WriteLine($"AsyncBody = (context, cancellationToken) => AsyncConvert.Convert(() => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model)})),"); - } + sourceBuilder.WriteLine($"Body = (context, cancellationToken) => AsyncConvert.Convert(() => {model.FullyQualifiedTypeName}.{model.MethodName}({GetArgs(model)})),"); sourceBuilder.WriteLine($"HookExecutor = {HookExecutorHelper.GetHookExecutor(model.HookExecutor)},"); sourceBuilder.WriteLine($"Order = {model.Order},"); @@ -63,28 +56,16 @@ public static void Execute(SourceCodeWriter sourceBuilder, HooksDataModel model) sourceBuilder.WriteTabs(); sourceBuilder.Write("MethodInfo = "); SourceInformationWriter.GenerateMethodInformation(sourceBuilder, model.Context, model.ClassType, model.Method, null, ','); - - if (model.IsVoid) + + + if (model.ClassType.IsGenericDefinition()) { - if (model.ClassType.IsGenericDefinition()) - { - sourceBuilder.WriteLine($"Body = (classInstance, context, cancellationToken) => classInstance.GetType().GetMethod(\"{model.MethodName}\", [{string.Join(", ", model.ParameterTypes.Select(x => $"typeof({x})"))}]).Invoke(classInstance, {GetArgsOrEmptyArray(model)}),"); - } - else - { - sourceBuilder.WriteLine($"Body = (classInstance, context, cancellationToken) => (({model.FullyQualifiedTypeName})classInstance).{model.MethodName}({GetArgs(model)}),"); - } + sourceBuilder.WriteLine( + $"Body = (classInstance, context, cancellationToken) => AsyncConvert.ConvertObject(() => classInstance.GetType().GetMethod(\"{model.MethodName}\", [{string.Join(", ", model.ParameterTypes.Select(x => $"typeof({x})"))}]).Invoke(classInstance, {GetArgsOrEmptyArray(model)})),"); } else { - if (model.ClassType.IsGenericDefinition()) - { - sourceBuilder.WriteLine($"AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => classInstance.GetType().GetMethod(\"{model.MethodName}\", [{string.Join(", ", model.ParameterTypes.Select(x => $"typeof({x})"))}]).Invoke(classInstance, {GetArgsOrEmptyArray(model)})),"); - } - else - { - sourceBuilder.WriteLine($"AsyncBody = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => (({model.FullyQualifiedTypeName})classInstance).{model.MethodName}({GetArgs(model)})),"); - } + sourceBuilder.WriteLine($"Body = (classInstance, context, cancellationToken) => AsyncConvert.Convert(() => (({model.FullyQualifiedTypeName})classInstance).{model.MethodName}({GetArgs(model)})),"); } sourceBuilder.WriteLine($"HookExecutor = {HookExecutorHelper.GetHookExecutor(model.HookExecutor)},"); diff --git a/TUnit.Core/AsyncConvert.cs b/TUnit.Core/AsyncConvert.cs index dfa242f6a5..a6da3282fc 100644 --- a/TUnit.Core/AsyncConvert.cs +++ b/TUnit.Core/AsyncConvert.cs @@ -21,8 +21,23 @@ public static async Task Convert(Func action) await action(); } - public static async ValueTask Convert(object? invoke) + public static async Task ConvertObject(object? invoke) { + if (invoke is Func syncFunc) + { + syncFunc(); + } + + if (invoke is Func asyncFunc) + { + await asyncFunc(); + } + + if (invoke is Func asyncValueFunc) + { + await asyncValueFunc(); + } + if (invoke is Task task) { await task; diff --git a/TUnit.Core/Context.cs b/TUnit.Core/Context.cs index 16ae7734d0..063a23832c 100644 --- a/TUnit.Core/Context.cs +++ b/TUnit.Core/Context.cs @@ -1,11 +1,12 @@ -using System.Diagnostics.CodeAnalysis; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Text; using TUnit.Core.Interfaces; using TUnit.Core.Logging; namespace TUnit.Core; -public abstract class Context : IContext +public abstract class Context : IContext, IDisposable { public static Context Current => TestContext.Current as Context @@ -28,6 +29,13 @@ TestContext.Current as Context internal Context() { } + + internal ExecutionContext? ExecutionContext { get; set; } + + public void AddAsyncLocalValues() + { + ExecutionContext = ExecutionContext.Capture(); + } public string GetStandardOutput() { @@ -43,4 +51,9 @@ public TUnitLogger GetDefaultLogger() { return new DefaultLogger(); } + + public void Dispose() + { + ExecutionContext?.Dispose(); + } } \ No newline at end of file diff --git a/TUnit.Core/Extensions/TestContextExtensions.cs b/TUnit.Core/Extensions/TestContextExtensions.cs index c457d37f54..6683c154e8 100644 --- a/TUnit.Core/Extensions/TestContextExtensions.cs +++ b/TUnit.Core/Extensions/TestContextExtensions.cs @@ -80,9 +80,22 @@ internal static IEnumerable GetTestRetryEventObjects(th internal static IEnumerable GetTestEndEventObjects(this TestContext context) => GetPossibleEventObjects(context).OfType(); - internal static IEnumerable GetOnDisposeObjects(this TestContext context) => - Enumerable.Reverse(GetEventObjects(context)).Where(x => x is IDisposable or IAsyncDisposable).OfType(); - + internal static IEnumerable GetOnDisposeObjects(this TestContext context) + { + IEnumerable disposableObjects = + [ + ..context.TestDetails.Attributes, + context.InternalDiscoveredTest.ClassConstructor, + context.TestDetails.ClassInstance, + context.Events, + context + ]; + + return disposableObjects + .Where(x => x is IDisposable or IAsyncDisposable) + .OfType(); + } + internal static IEnumerable GetTestSkippedEventObjects(this TestContext context) => GetPossibleEventObjects(context).OfType(); diff --git a/TUnit.Core/Hooks/AfterAssemblyHookMethod.cs b/TUnit.Core/Hooks/AfterAssemblyHookMethod.cs index 957ecf2889..c05e505cad 100644 --- a/TUnit.Core/Hooks/AfterAssemblyHookMethod.cs +++ b/TUnit.Core/Hooks/AfterAssemblyHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(AssemblyHookContext context, CancellationToken canc public override Task ExecuteAsync(AssemblyHookContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousAfterAssemblyHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/AfterClassHookMethod.cs b/TUnit.Core/Hooks/AfterClassHookMethod.cs index 1290a59c29..15f44ebecc 100644 --- a/TUnit.Core/Hooks/AfterClassHookMethod.cs +++ b/TUnit.Core/Hooks/AfterClassHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(ClassHookContext context, CancellationToken cancell public override Task ExecuteAsync(ClassHookContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousAfterClassHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/AfterTestDiscoveryHookMethod.cs b/TUnit.Core/Hooks/AfterTestDiscoveryHookMethod.cs index be9d5564b2..e022d3ef47 100644 --- a/TUnit.Core/Hooks/AfterTestDiscoveryHookMethod.cs +++ b/TUnit.Core/Hooks/AfterTestDiscoveryHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(TestDiscoveryContext context, CancellationToken can public override Task ExecuteAsync(TestDiscoveryContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousAfterTestDiscoveryHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/AfterTestHookMethod.cs b/TUnit.Core/Hooks/AfterTestHookMethod.cs index b73d8102b9..080e6a35c6 100644 --- a/TUnit.Core/Hooks/AfterTestHookMethod.cs +++ b/TUnit.Core/Hooks/AfterTestHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(TestContext context, CancellationToken cancellation public override Task ExecuteAsync(TestContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousAfterTestHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/AfterTestSessionHookMethod.cs b/TUnit.Core/Hooks/AfterTestSessionHookMethod.cs index a6c9d0b2a6..258656d83f 100644 --- a/TUnit.Core/Hooks/AfterTestSessionHookMethod.cs +++ b/TUnit.Core/Hooks/AfterTestSessionHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(TestSessionContext context, CancellationToken cance public override Task ExecuteAsync(TestSessionContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousAfterTestSessionHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/BeforeAssemblyHookMethod.cs b/TUnit.Core/Hooks/BeforeAssemblyHookMethod.cs index a85c95b4cf..24d6f5ef72 100644 --- a/TUnit.Core/Hooks/BeforeAssemblyHookMethod.cs +++ b/TUnit.Core/Hooks/BeforeAssemblyHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(AssemblyHookContext context, CancellationToken canc public override Task ExecuteAsync(AssemblyHookContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousBeforeAssemblyHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/BeforeClassHookMethod.cs b/TUnit.Core/Hooks/BeforeClassHookMethod.cs index 4180b92ce4..6f1a952985 100644 --- a/TUnit.Core/Hooks/BeforeClassHookMethod.cs +++ b/TUnit.Core/Hooks/BeforeClassHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(ClassHookContext context, CancellationToken cancell public override Task ExecuteAsync(ClassHookContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousBeforeClassHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/BeforeTestDiscoveryHookMethod.cs b/TUnit.Core/Hooks/BeforeTestDiscoveryHookMethod.cs index e2e3b7196d..aa4ed1c694 100644 --- a/TUnit.Core/Hooks/BeforeTestDiscoveryHookMethod.cs +++ b/TUnit.Core/Hooks/BeforeTestDiscoveryHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(BeforeTestDiscoveryContext context, CancellationTok public override Task ExecuteAsync(BeforeTestDiscoveryContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousBeforeTestDiscoveryHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/BeforeTestHookMethod.cs b/TUnit.Core/Hooks/BeforeTestHookMethod.cs index 343540415b..d18c776653 100644 --- a/TUnit.Core/Hooks/BeforeTestHookMethod.cs +++ b/TUnit.Core/Hooks/BeforeTestHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(TestContext context, CancellationToken cancellation public override Task ExecuteAsync(TestContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousBeforeTestHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/BeforeTestSessionHookMethod.cs b/TUnit.Core/Hooks/BeforeTestSessionHookMethod.cs index 853c4f96a0..cd3db893a5 100644 --- a/TUnit.Core/Hooks/BeforeTestSessionHookMethod.cs +++ b/TUnit.Core/Hooks/BeforeTestSessionHookMethod.cs @@ -18,7 +18,7 @@ public override bool Execute(TestSessionContext context, CancellationToken cance public override Task ExecuteAsync(TestSessionContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousBeforeTestSessionHook(MethodInfo, context, - () => AsyncBody!.Invoke(context, cancellationToken) + () => Body!.Invoke(context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/IExecutableHook.cs b/TUnit.Core/Hooks/IExecutableHook.cs index ebc0e38751..c82783a203 100644 --- a/TUnit.Core/Hooks/IExecutableHook.cs +++ b/TUnit.Core/Hooks/IExecutableHook.cs @@ -1,13 +1,9 @@ -using System.Reflection; - -namespace TUnit.Core.Hooks; +namespace TUnit.Core.Hooks; public interface IExecutableHook { string Name { get; } SourceGeneratedMethodInformation MethodInfo { get; } int Order { get; } - bool Execute(T context, CancellationToken cancellationToken); Task ExecuteAsync(T context, CancellationToken cancellationToken); - bool IsSynchronous { get; } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/InstanceHookMethod.cs b/TUnit.Core/Hooks/InstanceHookMethod.cs index fa6a7a8feb..dbf0eafe54 100644 --- a/TUnit.Core/Hooks/InstanceHookMethod.cs +++ b/TUnit.Core/Hooks/InstanceHookMethod.cs @@ -33,28 +33,12 @@ public record InstanceHookMethod : IExecutableHook public required int Order { get; init; } - public Func? AsyncBody { get; init; } - public Action? Body { get; init; } - - public bool IsSynchronous => Body != null; - - public bool Execute(TestContext context, CancellationToken cancellationToken) - { - if (Body != null) - { - HookExecutor.ExecuteSynchronousBeforeTestHook(MethodInfo, context, - () => Body.Invoke(context.TestDetails.ClassInstance, context, cancellationToken) - ); - return true; - } - - return false; - } + public Func? Body { get; init; } public Task ExecuteAsync(TestContext context, CancellationToken cancellationToken) { return HookExecutor.ExecuteAsynchronousBeforeTestHook(MethodInfo, context, - () => AsyncBody!.Invoke(context.TestDetails.ClassInstance, context, cancellationToken) + () => Body!.Invoke(context.TestDetails.ClassInstance, context, cancellationToken) ); } } \ No newline at end of file diff --git a/TUnit.Core/Hooks/StaticHookMethod.cs b/TUnit.Core/Hooks/StaticHookMethod.cs index 63fa7a1d86..4f570db77c 100644 --- a/TUnit.Core/Hooks/StaticHookMethod.cs +++ b/TUnit.Core/Hooks/StaticHookMethod.cs @@ -9,12 +9,9 @@ namespace TUnit.Core.Hooks; #endif public abstract record StaticHookMethod : StaticHookMethod, IExecutableHook { - public Func? AsyncBody { get; init; } - public Action? Body { get; init; } - + public Func? Body { get; init; } public abstract bool Execute(T context, CancellationToken cancellationToken); public abstract Task ExecuteAsync(T context, CancellationToken cancellationToken); - public bool IsSynchronous => Body != null; } #if !DEBUG diff --git a/TUnit.Engine/Extensions/TestContextExtensions.cs b/TUnit.Engine/Extensions/TestContextExtensions.cs index 3d55b996b0..ca59d7cd52 100644 --- a/TUnit.Engine/Extensions/TestContextExtensions.cs +++ b/TUnit.Engine/Extensions/TestContextExtensions.cs @@ -41,7 +41,7 @@ public static async Task ReregisterTestWithArguments( try { - await AsyncConvert.Convert(testMetadata.TestMethod.ReflectionInformation.Invoke(@class, args)); + await AsyncConvert.ConvertObject(testMetadata.TestMethod.ReflectionInformation.Invoke(@class, args)); } catch (TargetInvocationException e) { diff --git a/TUnit.Engine/Framework/TUnitServiceProvider.cs b/TUnit.Engine/Framework/TUnitServiceProvider.cs index bdbe89ee31..436e8ae8c1 100644 --- a/TUnit.Engine/Framework/TUnitServiceProvider.cs +++ b/TUnit.Engine/Framework/TUnitServiceProvider.cs @@ -25,6 +25,7 @@ internal class TUnitServiceProvider : IServiceProvider, IAsyncDisposable public TUnitFrameworkLogger Logger { get; } public TUnitMessageBus TUnitMessageBus { get; } + public HooksCollector HooksCollector { get; set; } public TUnitInitializer Initializer { get; } public StandardOutConsoleInterceptor StandardOutConsoleInterceptor { get; } public StandardErrorConsoleInterceptor StandardErrorConsoleInterceptor { get; } @@ -70,7 +71,7 @@ public TUnitServiceProvider(IExtension extension, var instanceTracker = Register(new InstanceTracker()); - var hooksCollector = Register(new HooksCollector(context.Request.Session.SessionUid.Value)); + HooksCollector = Register(new HooksCollector(context.Request.Session.SessionUid.Value)); var dependencyCollector = new DependencyCollector(); @@ -80,17 +81,17 @@ public TUnitServiceProvider(IExtension extension, TestGrouper = Register(new TestGrouper()); - AssemblyHookOrchestrator = Register(new AssemblyHookOrchestrator(instanceTracker, hooksCollector)); + AssemblyHookOrchestrator = Register(new AssemblyHookOrchestrator(instanceTracker, HooksCollector, Logger)); - TestDiscoveryHookOrchestrator = Register(new TestDiscoveryHookOrchestrator(hooksCollector, stringFilter)); - TestSessionHookOrchestrator = Register(new TestSessionHookOrchestrator(hooksCollector, AssemblyHookOrchestrator, stringFilter)); + TestDiscoveryHookOrchestrator = Register(new TestDiscoveryHookOrchestrator(HooksCollector, Logger, stringFilter)); + TestSessionHookOrchestrator = Register(new TestSessionHookOrchestrator(HooksCollector, AssemblyHookOrchestrator, Logger, stringFilter)); - var classHookOrchestrator = Register(new ClassHookOrchestrator(instanceTracker, hooksCollector)); + var classHookOrchestrator = Register(new ClassHookOrchestrator(instanceTracker, HooksCollector, Logger)); - var testHookOrchestrator = Register(new TestHookOrchestrator(hooksCollector)); + var testHookOrchestrator = Register(new TestHookOrchestrator(HooksCollector, Logger)); var testRegistrar = Register(new TestRegistrar(instanceTracker, AssemblyHookOrchestrator, classHookOrchestrator)); - TestDiscoverer = Register(new TUnitTestDiscoverer(hooksCollector, testsConstructor, testFilterService, TestGrouper, testRegistrar, TestDiscoveryHookOrchestrator, TUnitMessageBus, Logger, extension)); + TestDiscoverer = Register(new TUnitTestDiscoverer(testsConstructor, testFilterService, TestGrouper, testRegistrar, TUnitMessageBus, Logger, extension)); TestFinder = Register(new TestsFinder(TestDiscoverer)); Register(TestFinder); @@ -105,11 +106,11 @@ public TUnitServiceProvider(IExtension extension, var singleTestExecutor = Register(new SingleTestExecutor(extension, instanceTracker, testInvoker, parallelLimitProvider, AssemblyHookOrchestrator, classHookOrchestrator, TUnitMessageBus, Logger, EngineCancellationToken, testRegistrar)); - TestsExecutor = Register(new TestsExecutor(singleTestExecutor, Logger, CommandLineOptions, EngineCancellationToken)); + TestsExecutor = Register(new TestsExecutor(singleTestExecutor, Logger, CommandLineOptions, EngineCancellationToken, AssemblyHookOrchestrator, classHookOrchestrator)); OnEndExecutor = Register(new OnEndExecutor(CommandLineOptions, Logger)); } - + public Disposer Disposer { get; } public async ValueTask DisposeAsync() diff --git a/TUnit.Engine/Framework/TUnitTestFramework.cs b/TUnit.Engine/Framework/TUnitTestFramework.cs index a396542372..fc0196175f 100644 --- a/TUnit.Engine/Framework/TUnitTestFramework.cs +++ b/TUnit.Engine/Framework/TUnitTestFramework.cs @@ -7,6 +7,7 @@ using Microsoft.Testing.Platform.Services; using TUnit.Core; using TUnit.Core.Logging; +using TUnit.Engine.Helpers; namespace TUnit.Engine.Framework; @@ -81,8 +82,22 @@ public async Task ExecuteRequestAsync(ExecuteRequestContext context) { serviceProvider.EngineCancellationToken.Initialise(context.CancellationToken); + ExecutionContextHelper.RestoreContext(await serviceProvider.TestDiscoveryHookOrchestrator.RunBeforeTestDiscovery()); + + var allDiscoveredTests = serviceProvider.TestDiscoverer.GetTests(serviceProvider.EngineCancellationToken.Token); + + var afterDiscoveryHooks = serviceProvider.TestDiscoveryHookOrchestrator.CollectAfterHooks(); + var afterContext = serviceProvider.TestDiscoveryHookOrchestrator.GetAfterContext(allDiscoveredTests); + + foreach (var afterDiscoveryHook in afterDiscoveryHooks) + { + await logger.LogDebugAsync("Executing [After(TestDiscovery)] hook"); + + await afterDiscoveryHook.ExecuteAsync(afterContext, CancellationToken.None); + } + var filteredTests = await serviceProvider.TestDiscoverer - .FilterTests(context, stringFilter, serviceProvider.EngineCancellationToken.Token); + .FilterTests(context, serviceProvider.EngineCancellationToken.Token); switch (context.Request) { @@ -101,24 +116,8 @@ public async Task ExecuteRequestAsync(ExecuteRequestContext context) TestFilter = stringFilter }; - var beforeSessionHooks = serviceProvider.TestSessionHookOrchestrator.CollectBeforeHooks(); + ExecutionContextHelper.RestoreContext(await serviceProvider.TestSessionHookOrchestrator.RunBeforeTestSession(context.CancellationToken)); - foreach (var beforeSessionHook in beforeSessionHooks) - { - if (beforeSessionHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing synchronous [Before(TestSession)] hook"); - - beforeSessionHook.Execute(testSessionContext, context.CancellationToken); - } - else - { - await logger.LogDebugAsync("Executing asynchronous [Before(TestSession)] hook"); - - await beforeSessionHook.ExecuteAsync(testSessionContext, context.CancellationToken); - } - } - await serviceProvider.TestsExecutor.ExecuteAsync(filteredTests, runTestExecutionRequest.Filter, context); @@ -129,18 +128,9 @@ await serviceProvider.TestsExecutor.ExecuteAsync(filteredTests, runTestExecution foreach (var afterSessionHook in afterSessionHooks) { - if (afterSessionHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing synchronous [After(TestSession)] hook"); - - afterSessionHook.Execute(testSessionContext, context.CancellationToken); - } - else - { - await logger.LogDebugAsync("Executing asynchronous [After(TestSession)] hook"); + await logger.LogDebugAsync("Executing [After(TestSession)] hook"); - await afterSessionHook.ExecuteAsync(testSessionContext, context.CancellationToken); - } + await afterSessionHook.ExecuteAsync(testSessionContext, context.CancellationToken); } foreach (var artifact in testSessionContext.Artifacts) diff --git a/TUnit.Engine/Helpers/ExecutionContextHelper.cs b/TUnit.Engine/Helpers/ExecutionContextHelper.cs new file mode 100644 index 0000000000..acd20f4173 --- /dev/null +++ b/TUnit.Engine/Helpers/ExecutionContextHelper.cs @@ -0,0 +1,21 @@ +using System.Runtime.CompilerServices; +using TUnit.Core; + +namespace TUnit.Engine.Helpers; + +internal static class ExecutionContextHelper +{ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void RestoreContext(Context context) => RestoreContext(context.ExecutionContext); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void RestoreContext(ExecutionContext? executionContext) + { +#if NET + if (executionContext != null) + { + ExecutionContext.Restore(executionContext); + } +#endif + } +} \ No newline at end of file diff --git a/TUnit.Engine/Hooks/AssemblyHookOrchestrator.cs b/TUnit.Engine/Hooks/AssemblyHookOrchestrator.cs index 075691d407..34bd7c3b4f 100644 --- a/TUnit.Engine/Hooks/AssemblyHookOrchestrator.cs +++ b/TUnit.Engine/Hooks/AssemblyHookOrchestrator.cs @@ -4,11 +4,14 @@ using TUnit.Core.Data; using TUnit.Core.Extensions; using TUnit.Core.Hooks; +using TUnit.Core.Logging; +using TUnit.Engine.Helpers; +using TUnit.Engine.Logging; using TUnit.Engine.Services; namespace TUnit.Engine.Hooks; -internal class AssemblyHookOrchestrator(InstanceTracker instanceTracker, HooksCollector hooksCollector) +internal class AssemblyHookOrchestrator(InstanceTracker instanceTracker, HooksCollector hooksCollector, TUnitFrameworkLogger logger) { private readonly ConcurrentDictionary _assemblyHookContexts = new(); @@ -16,6 +19,47 @@ internal class AssemblyHookOrchestrator(InstanceTracker instanceTracker, HooksCo internal GetOnlyDictionary> PreviouslyRunBeforeHooks { get; } = new(); + public async Task ExecuteBeforeAssemblyHooks(TestContext testContext) + { + var assemblyHookContext = GetContext(testContext.TestDetails.TestClass.Type.Assembly); + + var assemblyHooksTaskCompletionSource = PreviouslyRunBeforeHooks.GetOrAdd( + testContext.TestDetails.TestClass.Type.Assembly, _ => new TaskCompletionSource(), + out var assemblyHooksTaskPreviouslyExisted); + + if (assemblyHooksTaskPreviouslyExisted) + { + await assemblyHooksTaskCompletionSource.Task; + return assemblyHookContext.ExecutionContext; + } + + try + { + var beforeAssemblyHooks = CollectBeforeHooks(testContext.TestDetails.TestClass.Type.Assembly); + + AssemblyHookContext.Current = assemblyHookContext; + + foreach (var beforeHook in beforeAssemblyHooks) + { + await logger.LogDebugAsync("Executing [Before(Assembly)] hook"); + + await beforeHook.ExecuteAsync(assemblyHookContext, CancellationToken.None); + + ExecutionContextHelper.RestoreContext(assemblyHookContext.ExecutionContext); + } + + AssemblyHookContext.Current = null; + assemblyHooksTaskCompletionSource.SetResult(false); + } + catch (Exception e) + { + assemblyHooksTaskCompletionSource.SetException(e); + throw; + } + + return assemblyHookContext.ExecutionContext; + } + public IEnumerable> CollectBeforeHooks(Assembly assembly) { _beforeHooksReached.GetOrAdd(assembly, true); diff --git a/TUnit.Engine/Hooks/ClassHookOrchestrator.cs b/TUnit.Engine/Hooks/ClassHookOrchestrator.cs index 604e722048..4ff7528f12 100644 --- a/TUnit.Engine/Hooks/ClassHookOrchestrator.cs +++ b/TUnit.Engine/Hooks/ClassHookOrchestrator.cs @@ -3,11 +3,14 @@ using TUnit.Core.Data; using TUnit.Core.Extensions; using TUnit.Core.Hooks; +using TUnit.Core.Logging; +using TUnit.Engine.Helpers; +using TUnit.Engine.Logging; using TUnit.Engine.Services; namespace TUnit.Engine.Hooks; -internal class ClassHookOrchestrator(InstanceTracker instanceTracker, HooksCollector hooksCollector) +internal class ClassHookOrchestrator(InstanceTracker instanceTracker, HooksCollector hooksCollector, TUnitFrameworkLogger logger) { private readonly ConcurrentDictionary _classHookContexts = new(); @@ -39,6 +42,49 @@ public IEnumerable> CollectBeforeHooks(Type t } } } + + public async Task ExecuteBeforeClassHooks(TestContext testContext) + { + var classHookContext = GetContext(testContext.TestDetails.TestClass.Type); + + var classHooksTaskCompletionSource = PreviouslyRunBeforeHooks.GetOrAdd( + testContext.TestDetails.TestClass.Type, _ => new TaskCompletionSource(), + out var classHooksTaskPreviouslyExisted); + + if (classHooksTaskPreviouslyExisted) + { + await classHooksTaskCompletionSource.Task; + return classHookContext.ExecutionContext; + } + + try + { + var beforeClassHooks = CollectBeforeHooks(testContext.TestDetails.TestClass.Type); + + ClassHookContext.Current = classHookContext; + + foreach (var beforeHook in beforeClassHooks) + { + { + await logger.LogDebugAsync("Executing [Before(Class)] hook"); + + await beforeHook.ExecuteAsync(classHookContext, CancellationToken.None); + + ExecutionContextHelper.RestoreContext(classHookContext.ExecutionContext); + } + } + + ClassHookContext.Current = null; + classHooksTaskCompletionSource.SetResult(false); + } + catch (Exception e) + { + classHooksTaskCompletionSource.SetException(e); + throw; + } + + return classHookContext.ExecutionContext; + } public IEnumerable> CollectAfterHooks( TestContext testContext, diff --git a/TUnit.Engine/Hooks/TestDiscoveryHookOrchestrator.cs b/TUnit.Engine/Hooks/TestDiscoveryHookOrchestrator.cs index 61c577b2d7..cae54180c1 100644 --- a/TUnit.Engine/Hooks/TestDiscoveryHookOrchestrator.cs +++ b/TUnit.Engine/Hooks/TestDiscoveryHookOrchestrator.cs @@ -1,14 +1,38 @@ using TUnit.Core; using TUnit.Core.Hooks; +using TUnit.Core.Logging; +using TUnit.Engine.Helpers; +using TUnit.Engine.Logging; using TUnit.Engine.Services; namespace TUnit.Engine.Hooks; -internal class TestDiscoveryHookOrchestrator(HooksCollector hooksCollector, string? stringFilter) +internal class TestDiscoveryHookOrchestrator(HooksCollector hooksCollector, TUnitFrameworkLogger logger, string? stringFilter) { private BeforeTestDiscoveryContext? _beforeContext; private TestDiscoveryContext? _afterContext; + + + + public async Task RunBeforeTestDiscovery() + { + hooksCollector.CollectDiscoveryHooks(); + + var beforeDiscoveryHooks = CollectBeforeHooks(); + var beforeContext = GetBeforeContext(); + + foreach (var beforeDiscoveryHook in beforeDiscoveryHooks) + { + await logger.LogDebugAsync("Executing [Before(TestDiscovery)] hook"); + + await beforeDiscoveryHook.ExecuteAsync(beforeContext, CancellationToken.None); + + ExecutionContextHelper.RestoreContext(beforeContext.ExecutionContext); + } + return beforeContext.ExecutionContext; + } + public IEnumerable> CollectBeforeHooks() { return hooksCollector.BeforeTestDiscoveryHooks diff --git a/TUnit.Engine/Hooks/TestHookOrchestrator.cs b/TUnit.Engine/Hooks/TestHookOrchestrator.cs index 8eb057407f..c4613ce276 100644 --- a/TUnit.Engine/Hooks/TestHookOrchestrator.cs +++ b/TUnit.Engine/Hooks/TestHookOrchestrator.cs @@ -1,5 +1,8 @@ using TUnit.Core; using TUnit.Core.Hooks; +using TUnit.Core.Logging; +using TUnit.Engine.Helpers; +using TUnit.Engine.Logging; using TUnit.Engine.Services; namespace TUnit.Engine.Hooks; @@ -7,8 +10,28 @@ namespace TUnit.Engine.Hooks; #if !DEBUG [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] #endif -internal class TestHookOrchestrator(HooksCollector hooksCollector) +internal class TestHookOrchestrator(HooksCollector hooksCollector, TUnitFrameworkLogger logger) { + public async Task ExecuteBeforeHooks(DiscoveredTest discoveredTest, CancellationToken cancellationToken) + { + var beforeHooks = CollectBeforeHooks( + discoveredTest.TestContext.TestDetails.ClassInstance, + discoveredTest); + + foreach (var executableHook in beforeHooks) + { + await logger.LogDebugAsync("Executing [Before(Test)] hook"); + + await Timings.Record($"Before(Test): {executableHook.Name}", discoveredTest.TestContext, () => + executableHook.ExecuteAsync(discoveredTest.TestContext, cancellationToken) + ); + + ExecutionContextHelper.RestoreContext(discoveredTest.TestContext.ExecutionContext); + } + + return discoveredTest.TestContext.ExecutionContext; + } + internal IEnumerable> CollectBeforeHooks(object classInstance, DiscoveredTest discoveredTest) { var testClassType = classInstance.GetType(); diff --git a/TUnit.Engine/Hooks/TestSessionHookOrchestrator.cs b/TUnit.Engine/Hooks/TestSessionHookOrchestrator.cs index 42509e7b93..a244b5b7e5 100644 --- a/TUnit.Engine/Hooks/TestSessionHookOrchestrator.cs +++ b/TUnit.Engine/Hooks/TestSessionHookOrchestrator.cs @@ -1,13 +1,39 @@ using TUnit.Core; using TUnit.Core.Hooks; +using TUnit.Core.Logging; +using TUnit.Engine.Helpers; +using TUnit.Engine.Logging; using TUnit.Engine.Services; namespace TUnit.Engine.Hooks; -internal class TestSessionHookOrchestrator(HooksCollector hooksCollector, AssemblyHookOrchestrator assemblyHookOrchestrator, string? stringFilter) +internal class TestSessionHookOrchestrator(HooksCollector hooksCollector, AssemblyHookOrchestrator assemblyHookOrchestrator, TUnitFrameworkLogger logger, string? stringFilter) { private TestSessionContext? _context; + public async Task RunBeforeTestSession(CancellationToken cancellationToken) + { + hooksCollector.CollectionTestSessionHooks(); + + var testSessionContext = GetContext(); + var beforeSessionHooks = CollectBeforeHooks(); + + foreach (var beforeSessionHook in beforeSessionHooks) + { + await logger.LogDebugAsync("Executing [Before(TestSession)] hook"); + + await beforeSessionHook.ExecuteAsync(testSessionContext, cancellationToken); + + ExecutionContextHelper.RestoreContext(testSessionContext.ExecutionContext); + } + + // After Discovery and Before test session hooks are run, more chance of references assemblies + // being loaded into the AppDomain, so now we collect the test hooks which should pick up loaded libraries too + hooksCollector.CollectHooks(); + + return testSessionContext.ExecutionContext; + } + public IEnumerable> CollectBeforeHooks() { return hooksCollector.BeforeTestSessionHooks diff --git a/TUnit.Engine/Services/HooksCollector.cs b/TUnit.Engine/Services/HooksCollector.cs index 04f99eb2b2..73bda44c32 100644 --- a/TUnit.Engine/Services/HooksCollector.cs +++ b/TUnit.Engine/Services/HooksCollector.cs @@ -43,6 +43,22 @@ public void CollectDiscoveryHooks() } } + public void CollectionTestSessionHooks() + { + foreach (var hookSource in Sources.TestSessionHookSources) + { + foreach (var beforeHook in hookSource.CollectBeforeTestSessionHooks(sessionId)) + { + BeforeTestSessionHooks.Add(beforeHook); + } + + foreach (var afterHook in hookSource.CollectAfterTestSessionHooks(sessionId)) + { + AfterTestSessionHooks.Add(afterHook); + } + } + } + public void CollectHooks() { foreach (var hookSource in Sources.TestHookSources) @@ -117,18 +133,5 @@ public void CollectHooks() AfterEveryAssemblyHooks.Add(afterHook); } } - - foreach (var hookSource in Sources.TestSessionHookSources) - { - foreach (var beforeHook in hookSource.CollectBeforeTestSessionHooks(sessionId)) - { - BeforeTestSessionHooks.Add(beforeHook); - } - - foreach (var afterHook in hookSource.CollectAfterTestSessionHooks(sessionId)) - { - AfterTestSessionHooks.Add(afterHook); - } - } } } \ No newline at end of file diff --git a/TUnit.Engine/Services/SingleTestExecutor.cs b/TUnit.Engine/Services/SingleTestExecutor.cs index d6e0e5a0fb..8d0cb83102 100644 --- a/TUnit.Engine/Services/SingleTestExecutor.cs +++ b/TUnit.Engine/Services/SingleTestExecutor.cs @@ -41,7 +41,8 @@ public Task ExecuteTestAsync(DiscoveredTest test, ITestExecutionFilter? filter, } } - private async Task ExecuteTestInternalAsync(DiscoveredTest test, ITestExecutionFilter? filter, ExecuteRequestContext context, bool isStartedAsDependencyForAnotherTest) + private async Task ExecuteTestInternalAsync(DiscoveredTest test, ITestExecutionFilter? filter, + ExecuteRequestContext context, bool isStartedAsDependencyForAnotherTest) { var semaphore = WaitForParallelLimiter(test, isStartedAsDependencyForAnotherTest); @@ -91,97 +92,15 @@ private async Task ExecuteTestInternalAsync(DiscoveredTest test, ITestExecutionF throw new SkipTestException("The test session has been cancelled..."); } - // Ideally all these 'Set up' hooks would be refactored into inner/classes and/or methods, - // But users may want to set AsyncLocal values, and so the method must be a parent/ancestor of the method that starts the test! - // So actually refactoring these into other methods would mean they wouldn't be a parent/ancestor and would break async local! - var assemblyHooksTaskCompletionSource = assemblyHookOrchestrator.PreviouslyRunBeforeHooks.GetOrAdd(testContext.TestDetails.TestClass.Type.Assembly, - _ => new TaskCompletionSource(), out var assemblyHooksTaskPreviouslyExisted); - - if (assemblyHooksTaskPreviouslyExisted) - { - await assemblyHooksTaskCompletionSource.Task; - } - else - { - try - { - var beforeAssemblyHooks = - assemblyHookOrchestrator.CollectBeforeHooks(test.TestContext.TestDetails.TestClass.Type.Assembly); - var assemblyHookContext = - assemblyHookOrchestrator.GetContext(test.TestContext.TestDetails.TestClass.Type.Assembly); - - AssemblyHookContext.Current = assemblyHookContext; - - foreach (var beforeHook in beforeAssemblyHooks) - { - if (beforeHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing synchronous [Before(Assembly)] hook"); - - beforeHook.Execute(assemblyHookContext, CancellationToken.None); - } - else - { - await logger.LogDebugAsync("Executing asynchronous [Before(Assembly)] hook"); - - await beforeHook.ExecuteAsync(assemblyHookContext, CancellationToken.None); - } - } - - AssemblyHookContext.Current = null; - assemblyHooksTaskCompletionSource.SetResult(false); - } - catch (Exception e) - { - assemblyHooksTaskCompletionSource.SetException(e); - throw; - } - } + TestContext.Current = testContext; - var classHooksTaskCompletionSource = classHookOrchestrator.PreviouslyRunBeforeHooks.GetOrAdd(testContext.TestDetails.TestClass.Type, - _ => new TaskCompletionSource(), out var classHooksTaskPreviouslyExisted); - - if (classHooksTaskPreviouslyExisted) - { - await classHooksTaskCompletionSource.Task; - } - else + foreach (var testStartEventsObject in testContext.GetTestStartEventObjects()) { - try - { - var beforeClassHooks = - classHookOrchestrator.CollectBeforeHooks(test.TestContext.TestDetails.TestClass.Type); - var classHookContext = classHookOrchestrator.GetContext(test.TestContext.TestDetails.TestClass.Type); - - ClassHookContext.Current = classHookContext; - - foreach (var beforeHook in beforeClassHooks) - { - if (beforeHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing synchronous [Before(Class)] hook"); - - beforeHook.Execute(classHookContext, CancellationToken.None); - } - else - { - await logger.LogDebugAsync("Executing asynchronous [Before(Class)] hook"); - - await beforeHook.ExecuteAsync(classHookContext, CancellationToken.None); - } - } - - ClassHookContext.Current = null; - classHooksTaskCompletionSource.SetResult(false); - } - catch (Exception e) - { - classHooksTaskCompletionSource.SetException(e); - throw; - } - } + await logger.LogDebugAsync("Executing ITestStartEventReceivers"); - TestContext.Current = testContext; + await testStartEventsObject.OnTestStart(new BeforeTestContext(testContext.InternalDiscoveredTest)); + testStartEventsObject.OnTestStartSynchronous(new BeforeTestContext(testContext.InternalDiscoveredTest)); + } await ExecuteWithRetries(test, cleanUpExceptions); @@ -227,14 +146,15 @@ private ValueTask RegisterIfNotAlready(TestContext testContext) { lock (Lock) { - // Could not be registered if it's triggered from a [DependsOn] + // Could not be registered if wasn't in the original filter and it's triggered from a [DependsOn] if (!testContext.IsRegistered) { - return testRegistrar.RegisterInstance(testContext.InternalDiscoveredTest, _ => default); + return testRegistrar.RegisterInstance(testContext.InternalDiscoveredTest, + _ => default); } + + return default; } - - return default; } private async Task RunCleanUps(DiscoveredTest test, TestContext testContext, @@ -281,18 +201,9 @@ private async Task ExecuteStaticAfterHooks(DiscoveredTest test, TestContext test foreach (var afterHook in afterClassHooks) { - if (afterHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing synchronous [After(Class)] hook"); - - RunHelpers.RunSafely(() => afterHook.Execute(classHookContext, CancellationToken.None), cleanUpExceptions); - } - else - { - await logger.LogDebugAsync("Executing asynchronous [After(Class)] hook"); + await logger.LogDebugAsync("Executing [After(Class)] hook"); - await RunHelpers.RunSafelyAsync(() => afterHook.ExecuteAsync(classHookContext, CancellationToken.None), cleanUpExceptions); - } + await RunHelpers.RunSafelyAsync(() => afterHook.ExecuteAsync(classHookContext, CancellationToken.None), cleanUpExceptions); } ClassHookContext.Current = null; @@ -304,18 +215,9 @@ private async Task ExecuteStaticAfterHooks(DiscoveredTest test, TestContext test foreach (var afterHook in afterAssemblyHooks) { - if (afterHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing synchronous [After(Assembly)] hook"); - - RunHelpers.RunSafely(() => afterHook.Execute(assemblyHookContext, CancellationToken.None), cleanUpExceptions); - } - else - { - await logger.LogDebugAsync("Executing asynchronous [After(Assembly)] hook"); + await logger.LogDebugAsync("Executing [After(Assembly)] hook"); - await RunHelpers.RunSafelyAsync(() => afterHook.ExecuteAsync(assemblyHookContext, CancellationToken.None), cleanUpExceptions); - } + await RunHelpers.RunSafelyAsync(() => afterHook.ExecuteAsync(assemblyHookContext, CancellationToken.None), cleanUpExceptions); } AssemblyHookContext.Current = null; diff --git a/TUnit.Engine/Services/TUnitTestDiscoverer.cs b/TUnit.Engine/Services/TUnitTestDiscoverer.cs index c51a9aa353..1b57693db5 100644 --- a/TUnit.Engine/Services/TUnitTestDiscoverer.cs +++ b/TUnit.Engine/Services/TUnitTestDiscoverer.cs @@ -4,35 +4,32 @@ using Microsoft.Testing.Platform.Requests; using TUnit.Core; using TUnit.Core.Logging; -using TUnit.Engine.Hooks; using TUnit.Engine.Logging; using TUnit.Engine.Models; namespace TUnit.Engine.Services; internal class TUnitTestDiscoverer( - HooksCollector hooksCollector, TestsConstructor testsConstructor, TestFilterService testFilterService, TestGrouper testGrouper, TestRegistrar testRegistrar, - TestDiscoveryHookOrchestrator testDiscoveryHookOrchestrator, ITUnitMessageBus tUnitMessageBus, TUnitFrameworkLogger logger, IExtension extension) : IDataProducer { private IReadOnlyCollection? _cachedTests; - public IReadOnlyCollection GetCachedTests() + public IReadOnlyCollection GetTests(CancellationToken cancellationToken = default) { - return _cachedTests!; + return _cachedTests ??= testsConstructor.GetTests(cancellationToken); } - public async Task FilterTests(ExecuteRequestContext context, string? stringTestFilter, CancellationToken cancellationToken) + public async Task FilterTests(ExecuteRequestContext context, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - var allDiscoveredTests = _cachedTests ??= await DiscoverTests(cancellationToken); + var allDiscoveredTests = _cachedTests ??= GetTests(cancellationToken); var executionRequest = context.Request as TestExecutionRequest; @@ -60,54 +57,6 @@ await testRegistrar.RegisterInstance(discoveredTest: test, } } - private async Task> DiscoverTests(CancellationToken cancellationToken) - { - hooksCollector.CollectDiscoveryHooks(); - - var beforeDiscoveryHooks = testDiscoveryHookOrchestrator.CollectBeforeHooks(); - var beforeContext = testDiscoveryHookOrchestrator.GetBeforeContext(); - - foreach (var beforeDiscoveryHook in beforeDiscoveryHooks) - { - if (beforeDiscoveryHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing synchronous [Before(TestDiscovery)] hook"); - - beforeDiscoveryHook.Execute(beforeContext, CancellationToken.None); - } - else - { - await logger.LogDebugAsync("Executing asynchronous [Before(TestDiscovery)] hook"); - - await beforeDiscoveryHook.ExecuteAsync(beforeContext, CancellationToken.None); - } - } - - var allDiscoveredTests = testsConstructor.GetTests(cancellationToken); - - var afterDiscoveryHooks = testDiscoveryHookOrchestrator.CollectAfterHooks(); - var afterContext = testDiscoveryHookOrchestrator.GetAfterContext(allDiscoveredTests); - - foreach (var afterDiscoveryHook in afterDiscoveryHooks) - { - if (afterDiscoveryHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing asynchronous [After(TestDiscovery)] hook"); - - afterDiscoveryHook.Execute(afterContext, CancellationToken.None); - } - else - { - await logger.LogDebugAsync("Executing asynchronous [After(TestDiscovery)] hook"); - - await afterDiscoveryHook.ExecuteAsync(afterContext, CancellationToken.None); - } - } - hooksCollector.CollectHooks(); - - return allDiscoveredTests; - } - public Task IsEnabledAsync() { return extension.IsEnabledAsync(); diff --git a/TUnit.Engine/Services/TestInvoker.cs b/TUnit.Engine/Services/TestInvoker.cs index 86775c75b1..79e50b2eb9 100644 --- a/TUnit.Engine/Services/TestInvoker.cs +++ b/TUnit.Engine/Services/TestInvoker.cs @@ -25,33 +25,7 @@ public async Task Invoke(DiscoveredTest discoveredTest, CancellationToken cancel await onInitializeObject.InitializeAsync(); } - // In order to set async-local values properly in a before hook, the method doing so needs to have the parents execution context. - // This is achievable by: - // - Calling it here (and not in a child/sibling method to the actual test body) as this method calls the test body so is considered a parent - // - Running synchronous hooks synchronously, so they don't generate a new child execution context which happens in async methods - var beforeHooks = testHookOrchestrator.CollectBeforeHooks( - discoveredTest.TestContext.TestDetails.ClassInstance, - discoveredTest); - - foreach (var executableHook in beforeHooks) - { - if (executableHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing synchronous [Before(Test)] hook"); - - Timings.Record($"Before(Test): {executableHook.Name}", discoveredTest.TestContext, () => - executableHook.Execute(discoveredTest.TestContext, cancellationToken) - ); - } - else - { - await logger.LogDebugAsync("Executing asynchronous [Before(Test)] hook"); - - await Timings.Record($"Before(Test): {executableHook.Name}", discoveredTest.TestContext, () => - executableHook.ExecuteAsync(discoveredTest.TestContext, cancellationToken) - ); - } - } + ExecutionContextHelper.RestoreContext(await testHookOrchestrator.ExecuteBeforeHooks(discoveredTest, cancellationToken)); foreach (var testStartEventsObject in discoveredTest.TestContext.GetTestStartEventObjects()) { @@ -85,17 +59,8 @@ private async ValueTask DisposeTest(TestContext testContext, List cle foreach (var executableHook in afterHooks) { - if (executableHook.IsSynchronous) - { - await logger.LogDebugAsync("Executing synchronous [After(Test)] hook"); - - Timings.Record($"After(Test): {executableHook.Name}", testContext, () => - executableHook.Execute(testContext, CancellationToken.None) - ); - } - else { - await logger.LogDebugAsync("Executing asynchronous [After(Test)] hook"); + await logger.LogDebugAsync("Executing [After(Test)] hook"); await Timings.Record($"After(Test): {executableHook.Name}", testContext, () => executableHook.ExecuteAsync(testContext, CancellationToken.None) diff --git a/TUnit.Engine/Services/TestsExecutor.cs b/TUnit.Engine/Services/TestsExecutor.cs index 0af80b5749..21c76b6524 100644 --- a/TUnit.Engine/Services/TestsExecutor.cs +++ b/TUnit.Engine/Services/TestsExecutor.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using EnumerableAsyncProcessor.Extensions; using Microsoft.Testing.Platform.CommandLine; using Microsoft.Testing.Platform.Extensions.TestFramework; @@ -7,6 +8,8 @@ using TUnit.Core; using TUnit.Core.Helpers; using TUnit.Engine.CommandLineProviders; +using TUnit.Engine.Helpers; +using TUnit.Engine.Hooks; using TUnit.Engine.Logging; using TUnit.Engine.Models; @@ -15,10 +18,12 @@ namespace TUnit.Engine.Services; internal class TestsExecutor { private readonly SingleTestExecutor _singleTestExecutor; - private readonly TUnitFrameworkLogger _logger; private readonly ICommandLineOptions _commandLineOptions; private readonly EngineCancellationToken _engineCancellationToken; + private readonly AssemblyHookOrchestrator _assemblyHookOrchestrator; + private readonly ClassHookOrchestrator _classHookOrchestrator; + private readonly Counter _executionCounter = new(); private readonly TaskCompletionSource _onFinished = new(); @@ -27,12 +32,13 @@ internal class TestsExecutor public TestsExecutor(SingleTestExecutor singleTestExecutor, TUnitFrameworkLogger logger, ICommandLineOptions commandLineOptions, - EngineCancellationToken engineCancellationToken) + EngineCancellationToken engineCancellationToken, AssemblyHookOrchestrator assemblyHookOrchestrator, ClassHookOrchestrator classHookOrchestrator) { _singleTestExecutor = singleTestExecutor; - _logger = logger; _commandLineOptions = commandLineOptions; _engineCancellationToken = engineCancellationToken; + _assemblyHookOrchestrator = assemblyHookOrchestrator; + _classHookOrchestrator = classHookOrchestrator; _maximumParallelTests = GetParallelTestsLimit(); @@ -99,9 +105,16 @@ private async Task ProcessQueue(ITestExecutionFilter? filter, ExecuteRequestCont { await Task.Run(async delegate { - while (tests.TryDequeue(out var testInformation, out _)) + while (tests.TryDequeue(out var test, out _)) { - await ProcessTest(testInformation, filter, context, context.CancellationToken); + if (test.TestContext.SkipReason == null) + { + ExecutionContextHelper.RestoreContext(await _assemblyHookOrchestrator.ExecuteBeforeAssemblyHooks(test.TestContext)); + + ExecutionContextHelper.RestoreContext(await _classHookOrchestrator.ExecuteBeforeClassHooks(test.TestContext)); + } + + await ProcessTest(test, filter, context, context.CancellationToken); } }); } @@ -112,6 +125,7 @@ private async Task ProcessParallelTests(IEnumerable queue, ITest await ProcessCollection(queue, filter, context); } + [SuppressMessage("ReSharper", "AccessToDisposedClosure")] private async Task ProcessCollection(IEnumerable queue, ITestExecutionFilter? filter, ExecuteRequestContext context) @@ -121,10 +135,30 @@ private async Task ProcessCollection(IEnumerable queue, { MaxDegreeOfParallelism = _maximumParallelTests, CancellationToken = context.CancellationToken - }, (test, token) => ProcessTest(test, filter, context, token)); + }, async (test, token) => + { + if (test.TestContext.SkipReason == null) + { + ExecutionContextHelper.RestoreContext(await _assemblyHookOrchestrator.ExecuteBeforeAssemblyHooks(test.TestContext)); + + ExecutionContextHelper.RestoreContext(await _classHookOrchestrator.ExecuteBeforeClassHooks(test.TestContext)); + } + + await ProcessTest(test, filter, context, token); + }); #else await queue - .ForEachAsync(test => ProcessTest(test, filter, context, context.CancellationToken)) + .ForEachAsync(async test => + { + if (test.TestContext.SkipReason != null) + { + ExecutionContextHelper.RestoreContext(await _assemblyHookOrchestrator.ExecuteBeforeAssemblyHooks(test.TestContext)); + + ExecutionContextHelper.RestoreContext(await _classHookOrchestrator.ExecuteBeforeClassHooks(test.TestContext)); + } + + await ProcessTest(test, filter, context, context.CancellationToken); + }) .ProcessInParallel(_maximumParallelTests); #endif } diff --git a/TUnit.Engine/Services/TestsFinder.cs b/TUnit.Engine/Services/TestsFinder.cs index 054bdcfd9f..7b2e40f727 100644 --- a/TUnit.Engine/Services/TestsFinder.cs +++ b/TUnit.Engine/Services/TestsFinder.cs @@ -7,14 +7,14 @@ internal class TestsFinder(TUnitTestDiscoverer testDiscoverer) : ITestFinder { public IEnumerable GetTests(Type classType) { - return testDiscoverer.GetCachedTests() + return testDiscoverer.GetTests() .Where(x => x.TestDetails.TestClass.Type == classType) .Select(x => x.TestContext); } public TestContext[] GetTestsByNameAndParameters(string testName, IEnumerable methodParameterTypes, Type classType, IEnumerable classParameterTypes, IEnumerable classArguments) { - var testsWithoutMethodParameterTypesMatching = testDiscoverer.GetCachedTests().Where(x => + var testsWithoutMethodParameterTypesMatching = testDiscoverer.GetTests().Where(x => x.TestContext.TestDetails.TestName == testName && x.TestContext.TestDetails.TestClass.Type == classType && x.TestContext.TestDetails.TestClassParameterTypes.SequenceEqual(classParameterTypes) && diff --git a/TUnit.Engine/TUnitMessageBus.cs b/TUnit.Engine/TUnitMessageBus.cs index 1e3c1c3ad8..fc34678991 100644 --- a/TUnit.Engine/TUnitMessageBus.cs +++ b/TUnit.Engine/TUnitMessageBus.cs @@ -204,8 +204,8 @@ private void TidyStacktrace(Exception exception) var newStackTrace = FilterStackTrace(originalStacktrace); StackTrace(exception) = null; - RemoteStackTraceString(exception) = null; - StackTraceString(exception) = newStackTrace; + StackTraceString(exception) = null; + RemoteStackTraceString(exception) = newStackTrace; if (exception.InnerException != null) { diff --git a/TUnit.TestProject/AsyncLocalTest.cs b/TUnit.TestProject/AsyncLocalTest.cs index 8e8287beff..63224624d0 100644 --- a/TUnit.TestProject/AsyncLocalTest.cs +++ b/TUnit.TestProject/AsyncLocalTest.cs @@ -12,6 +12,7 @@ public class AsyncLocalTest public void Before(TestContext context) { _asyncLocalValue.Value = "123"; + context.AddAsyncLocalValues(); } [After(Test)] diff --git a/TUnit.TestProject/Bugs/1914/AsyncHookTests.cs b/TUnit.TestProject/Bugs/1914/AsyncHookTests.cs new file mode 100644 index 0000000000..aeb45cc9b5 --- /dev/null +++ b/TUnit.TestProject/Bugs/1914/AsyncHookTests.cs @@ -0,0 +1,129 @@ +using System.Diagnostics.CodeAnalysis; +using TUnit.Assertions; +using TUnit.Assertions.Extensions; + +namespace TUnit.TestProject.Bugs._1914; + +[SuppressMessage("Usage", "TUnit0042:Global hooks should not be mixed with test classes to avoid confusion. Place them in their own class.")] +public class AsyncHookTests +{ + private static readonly AsyncLocal _0BeforeTestDiscoveryLocal = new(); + private static readonly AsyncLocal _0BeforeTestDiscoveryLocal2 = new(); + + private static readonly AsyncLocal _1BeforeTestSessionLocal = new(); + private static readonly AsyncLocal _1BeforeTestSessionLocal2 = new(); + + private static readonly AsyncLocal _2BeforeAssemblyLocal = new(); + private static readonly AsyncLocal _2BeforeAssemblyLocal2 = new(); + + private static readonly AsyncLocal _3BeforeClassLocal = new(); + private static readonly AsyncLocal _3BeforeClassLocal2 = new(); + + private static readonly AsyncLocal _4BeforeTestLocal = new(); + private static readonly AsyncLocal _4BeforeTestLocal2 = new(); + + [Before(TestDiscovery)] + public static async Task BeforeTestDiscovery(BeforeTestDiscoveryContext context) + { + await Task.CompletedTask; + _0BeforeTestDiscoveryLocal.Value = "BeforeTestDiscovery"; + context.AddAsyncLocalValues(); + } + + [Before(TestDiscovery)] + public static async Task BeforeTestDiscovery2(BeforeTestDiscoveryContext context) + { + await Task.CompletedTask; + _0BeforeTestDiscoveryLocal2.Value = "BeforeTestDiscovery2"; + context.AddAsyncLocalValues(); + } + + [Before(TestSession)] + public static async Task BeforeTestSession(TestSessionContext context) + { + await Task.CompletedTask; + _1BeforeTestSessionLocal.Value = "BeforeTestSession"; + context.AddAsyncLocalValues(); + } + + [Before(TestSession)] + public static async Task BeforeTestSession2(TestSessionContext context) + { + await Task.CompletedTask; + _1BeforeTestSessionLocal2.Value = "BeforeTestSession2"; + context.AddAsyncLocalValues(); + } + + [Before(Assembly)] + public static async Task BeforeAssembly(AssemblyHookContext context) + { + await Task.CompletedTask; + _2BeforeAssemblyLocal.Value = "BeforeAssembly"; + context.AddAsyncLocalValues(); + } + + [Before(Assembly)] + public static async Task BeforeAssembly2(AssemblyHookContext context) + { + await Task.CompletedTask; + _2BeforeAssemblyLocal2.Value = "BeforeAssembly2"; + context.AddAsyncLocalValues(); + } + + [Before(Class)] + public static async Task BeforeClass(ClassHookContext context) + { + await Task.CompletedTask; + _3BeforeClassLocal.Value = "BeforeClass"; + context.AddAsyncLocalValues(); + } + + [Before(Class)] + public static async Task BeforeClass2(ClassHookContext context) + { + await Task.CompletedTask; + _3BeforeClassLocal2.Value = "BeforeClass2"; + context.AddAsyncLocalValues(); + } + + [Before(Test)] + public async Task BeforeTest(TestContext context) + { + await Task.CompletedTask; + _4BeforeTestLocal.Value = "BeforeTest"; + context.AddAsyncLocalValues(); + } + + [Before(Test)] + public async Task BeforeTest2(TestContext context) + { + await Task.CompletedTask; + _4BeforeTestLocal2.Value = "BeforeTest2"; + context.AddAsyncLocalValues(); + } + + + [Test] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + [Arguments(6)] + [Arguments(7)] + [Arguments(8)] + public async Task TestAsyncLocal(int i) + { + await Assert.That(_0BeforeTestDiscoveryLocal.Value).IsEqualTo("BeforeTestDiscovery"); + await Assert.That(_1BeforeTestSessionLocal.Value).IsEqualTo("BeforeTestSession"); + await Assert.That(_2BeforeAssemblyLocal.Value).IsEqualTo("BeforeAssembly"); + await Assert.That(_3BeforeClassLocal.Value).IsEqualTo("BeforeClass"); + await Assert.That(_4BeforeTestLocal.Value).IsEqualTo("BeforeTest"); + + await Assert.That(_0BeforeTestDiscoveryLocal2.Value).IsEqualTo("BeforeTestDiscovery2"); + await Assert.That(_1BeforeTestSessionLocal2.Value).IsEqualTo("BeforeTestSession2"); + await Assert.That(_2BeforeAssemblyLocal2.Value).IsEqualTo("BeforeAssembly2"); + await Assert.That(_3BeforeClassLocal2.Value).IsEqualTo("BeforeClass2"); + await Assert.That(_4BeforeTestLocal2.Value).IsEqualTo("BeforeTest2"); + } +} \ No newline at end of file diff --git a/TUnit.TestProject/Bugs/1914/SyncHookTests.cs b/TUnit.TestProject/Bugs/1914/SyncHookTests.cs new file mode 100644 index 0000000000..4c06d417ff --- /dev/null +++ b/TUnit.TestProject/Bugs/1914/SyncHookTests.cs @@ -0,0 +1,119 @@ +using System.Diagnostics.CodeAnalysis; +using TUnit.Assertions; +using TUnit.Assertions.Extensions; + +namespace TUnit.TestProject.Bugs._1914; + +[SuppressMessage("Usage", "TUnit0042:Global hooks should not be mixed with test classes to avoid confusion. Place them in their own class.")] +public class SyncHookTests +{ + private static readonly AsyncLocal _0BeforeTestDiscoveryLocal = new(); + private static readonly AsyncLocal _0BeforeTestDiscoveryLocal2 = new(); + + private static readonly AsyncLocal _1BeforeTestSessionLocal = new(); + private static readonly AsyncLocal _1BeforeTestSessionLocal2 = new(); + + private static readonly AsyncLocal _2BeforeAssemblyLocal = new(); + private static readonly AsyncLocal _2BeforeAssemblyLocal2 = new(); + + private static readonly AsyncLocal _3BeforeClassLocal = new(); + private static readonly AsyncLocal _3BeforeClassLocal2 = new(); + + private static readonly AsyncLocal _4BeforeTestLocal = new(); + private static readonly AsyncLocal _4BeforeTestLocal2 = new(); + + [Before(TestDiscovery)] + public static void BeforeTestDiscovery(BeforeTestDiscoveryContext context) + { + _0BeforeTestDiscoveryLocal.Value = "BeforeTestDiscovery"; + context.AddAsyncLocalValues(); + } + + [Before(TestDiscovery)] + public static void BeforeTestDiscovery2(BeforeTestDiscoveryContext context) + { + _0BeforeTestDiscoveryLocal2.Value = "BeforeTestDiscovery2"; + context.AddAsyncLocalValues(); + } + + [Before(TestSession)] + public static void BeforeTestSession(TestSessionContext context) + { + _1BeforeTestSessionLocal.Value = "BeforeTestSession"; + context.AddAsyncLocalValues(); + } + + [Before(TestSession)] + public static void BeforeTestSession2(TestSessionContext context) + { + _1BeforeTestSessionLocal2.Value = "BeforeTestSession2"; + context.AddAsyncLocalValues(); + } + + [Before(Assembly)] + public static void BeforeAssembly(AssemblyHookContext context) + { + _2BeforeAssemblyLocal.Value = "BeforeAssembly"; + context.AddAsyncLocalValues(); + } + + [Before(Assembly)] + public static void BeforeAssembly2(AssemblyHookContext context) + { + _2BeforeAssemblyLocal2.Value = "BeforeAssembly2"; + context.AddAsyncLocalValues(); + } + + [Before(Class)] + public static void BeforeClass(ClassHookContext context) + { + _3BeforeClassLocal.Value = "BeforeClass"; + context.AddAsyncLocalValues(); + } + + [Before(Class)] + public static void BeforeClass2(ClassHookContext context) + { + _3BeforeClassLocal2.Value = "BeforeClass2"; + context.AddAsyncLocalValues(); + } + + [Before(Test)] + public void BeforeTest(TestContext context) + { + _4BeforeTestLocal.Value = "BeforeTest"; + context.AddAsyncLocalValues(); + } + + [Before(Test)] + public void BeforeTest2(TestContext context) + { + _4BeforeTestLocal2.Value = "BeforeTest2"; + context.AddAsyncLocalValues(); + } + + + [Test] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + [Arguments(6)] + [Arguments(7)] + [Arguments(8)] + public async Task TestAsyncLocal(int i) + { + await Assert.That(_0BeforeTestDiscoveryLocal.Value).IsEqualTo("BeforeTestDiscovery"); + await Assert.That(_1BeforeTestSessionLocal.Value).IsEqualTo("BeforeTestSession"); + await Assert.That(_2BeforeAssemblyLocal.Value).IsEqualTo("BeforeAssembly"); + await Assert.That(_3BeforeClassLocal.Value).IsEqualTo("BeforeClass"); + await Assert.That(_4BeforeTestLocal.Value).IsEqualTo("BeforeTest"); + + await Assert.That(_0BeforeTestDiscoveryLocal2.Value).IsEqualTo("BeforeTestDiscovery2"); + await Assert.That(_1BeforeTestSessionLocal2.Value).IsEqualTo("BeforeTestSession2"); + await Assert.That(_2BeforeAssemblyLocal2.Value).IsEqualTo("BeforeAssembly2"); + await Assert.That(_3BeforeClassLocal2.Value).IsEqualTo("BeforeClass2"); + await Assert.That(_4BeforeTestLocal2.Value).IsEqualTo("BeforeTest2"); + } +} \ No newline at end of file diff --git a/docs/docs/tutorial-extras/setup.md b/docs/docs/tutorial-extras/setup.md index edab76b013..2012214f6f 100644 --- a/docs/docs/tutorial-extras/setup.md +++ b/docs/docs/tutorial-extras/setup.md @@ -82,3 +82,19 @@ public class MyTestClass } } ``` +## AsyncLocal + +If you are wanting to set AsyncLocal values within your `[Before(...)]` hooks, this is supported. + +But to propagate the values into the test framework, you must call `context.FlowAsyncLocalValues()` - Where `context` is the relevant context object injected into your hook method. + +E.g. + +```csharp + [BeforeEvery(Class)] + public static void BeforeClass(ClassHookContext context) + { + _myAsyncLocal.Value = "Some Value"; + context.FlowAsyncLocalValues(); + } +``` \ No newline at end of file