diff --git a/.github/workflows/speed-comparison.yml b/.github/workflows/speed-comparison.yml index a8bc3862fb..cc363b2a0f 100644 --- a/.github/workflows/speed-comparison.yml +++ b/.github/workflows/speed-comparison.yml @@ -28,28 +28,22 @@ jobs: with: dotnet-version: 9.0.x - - name: Build TUnit AOT .NET 8.0 - run: dotnet publish UnifiedTests.csproj -c Release -p:TestFramework=TUNIT --framework net8.0 --output aot-publish-net8 -p:PublishAot=true --runtime ${{ matrix.os == 'windows-latest' && 'win-x64' || matrix.os == 'ubuntu-latest' && 'linux-x64' || 'osx-arm64' }} - working-directory: "tools/speed-comparison/UnifiedTests" - - - name: Build TUnit AOT .NET 9.0 - run: dotnet publish UnifiedTests.csproj -c Release -p:TestFramework=TUNIT --framework net9.0 --output aot-publish-net9 -p:PublishAot=true --runtime ${{ matrix.os == 'windows-latest' && 'win-x64' || matrix.os == 'ubuntu-latest' && 'linux-x64' || 'osx-arm64' }} - working-directory: "tools/speed-comparison/UnifiedTests" - - - name: Build TUnit Single File .NET 8.0 - run: dotnet publish UnifiedTests.csproj -c Release -p:TestFramework=TUNIT --framework net8.0 --output singlefile-publish-net8 -p:PublishSingleFile=true -p:SelfContained=true --runtime ${{ matrix.os == 'windows-latest' && 'win-x64' || matrix.os == 'ubuntu-latest' && 'linux-x64' || 'osx-arm64' }} - working-directory: "tools/speed-comparison/UnifiedTests" - - - name: Build TUnit Single File .NET 9.0 - run: dotnet publish UnifiedTests.csproj -c Release -p:TestFramework=TUNIT --framework net9.0 --output singlefile-publish-net9 -p:PublishSingleFile=true -p:SelfContained=true --runtime ${{ matrix.os == 'windows-latest' && 'win-x64' || matrix.os == 'ubuntu-latest' && 'linux-x64' || 'osx-arm64' }} + - name: Build All Frameworks + run: | + dotnet build -c Release -p:TestFramework=TUNIT --framework net8.0 --output bin/Release-TUNIT/net8.0 + dotnet build -c Release -p:TestFramework=TUNIT --framework net9.0 --output bin/Release-TUNIT/net9.0 + dotnet build -c Release -p:TestFramework=XUNIT --framework net8.0 --output bin/Release-XUNIT/net8.0 + dotnet build -c Release -p:TestFramework=XUNIT --framework net9.0 --output bin/Release-XUNIT/net9.0 + dotnet build -c Release -p:TestFramework=NUNIT --framework net8.0 --output bin/Release-NUNIT/net8.0 + dotnet build -c Release -p:TestFramework=NUNIT --framework net9.0 --output bin/Release-NUNIT/net9.0 + dotnet build -c Release -p:TestFramework=MSTEST --framework net8.0 --output bin/Release-MSTEST/net8.0 + dotnet build -c Release -p:TestFramework=MSTEST --framework net9.0 --output bin/Release-MSTEST/net9.0 working-directory: "tools/speed-comparison/UnifiedTests" - - name: Build All Frameworks + - name: Publish TUnit AOT run: | - dotnet build -c Release -p:TestFramework=TUNIT - dotnet build -c Release -p:TestFramework=XUNIT - dotnet build -c Release -p:TestFramework=NUNIT - dotnet build -c Release -p:TestFramework=MSTEST + dotnet publish -c Release -p:TestFramework=TUNIT -p:Aot=true --framework net8.0 --runtime ${{ matrix.os == 'windows-latest' && 'win-x64' || matrix.os == 'ubuntu-latest' && 'linux-x64' || 'osx-arm64' }} --output bin/Release-TUNIT-AOT/net8.0 + dotnet publish -c Release -p:TestFramework=TUNIT -p:Aot=true --framework net9.0 --runtime ${{ matrix.os == 'windows-latest' && 'win-x64' || matrix.os == 'ubuntu-latest' && 'linux-x64' || 'osx-arm64' }} --output bin/Release-TUNIT-AOT/net9.0 working-directory: "tools/speed-comparison/UnifiedTests" - name: Run Benchmark diff --git a/.gitignore b/.gitignore index 2d7856147c..3dae757b14 100644 --- a/.gitignore +++ b/.gitignore @@ -397,6 +397,7 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml +.idea/ # Generated Code *.g.cs diff --git a/.idea/.idea.TUnit/.idea/workspace.xml b/.idea/.idea.TUnit/.idea/workspace.xml deleted file mode 100644 index 80e9f39bf6..0000000000 --- a/.idea/.idea.TUnit/.idea/workspace.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - TUnit.Analyzers.Tests/TUnit.Analyzers.Tests.csproj - TUnit.Analyzers/TUnit.Analyzers.csproj - TUnit.Assertions.Analyzers.CodeFixers.Tests/TUnit.Assertions.Analyzers.CodeFixers.Tests.csproj - TUnit.Assertions.Analyzers.Tests/TUnit.Assertions.Analyzers.Tests.csproj - TUnit.Assertions.Analyzers/TUnit.Assertions.Analyzers.csproj - TUnit.Assertions.SourceGenerator.Tests/TUnit.Assertions.SourceGenerator.Tests.csproj - TUnit.Assertions.Tests/TUnit.Assertions.Tests.csproj - TUnit.Core.SourceGenerator.Tests/TUnit.Core.SourceGenerator.Tests.csproj - TUnit.Core.SourceGenerator/TUnit.Core.SourceGenerator.csproj - TUnit.Engine.SourceGenerator/TUnit.Engine.SourceGenerator.csproj - TUnit.Engine.Tests/TUnit.Engine.Tests.csproj - TUnit.Example.Asp.Net.TestProject/TUnit.Example.Asp.Net.TestProject.csproj - TUnit.Example.Asp.Net/TUnit.Example.Asp.Net.csproj - TUnit.Example.Asp.Net/TUnit.Example.Asp.Net.csproj - TUnit.Pipeline/TUnit.Pipeline.csproj - TUnit.PublicAPI/TUnit.PublicAPI.csproj - TUnit.RpcTests/TUnit.RpcTests.csproj - TUnit.Templates.Tests/TUnit.Templates.Tests.csproj - TUnit.Templates/content/TUnit.AspNet.FSharp/TestProject/TestProject.fsproj - TUnit.Templates/content/TUnit.AspNet.FSharp/WebApp/WebApp.fsproj - TUnit.Templates/content/TUnit.AspNet.FSharp/WebApp/WebApp.fsproj - TUnit.Templates/content/TUnit.AspNet/TestProject/TestProject.csproj - TUnit.Templates/content/TUnit.AspNet/WebApp/WebApp.csproj - TUnit.Templates/content/TUnit.AspNet/WebApp/WebApp.csproj - TUnit.Templates/content/TUnit.AspNet/WebApp/WebApp.csproj - TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.ApiService/ExampleNamespace.ApiService.csproj - TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.ApiService/ExampleNamespace.ApiService.csproj - TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj - TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj - TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.TestProject/ExampleNamespace.TestProject.csproj - TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj - TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj - TUnit.Templates/content/TUnit.Aspire.Test/ExampleNamespace.csproj - TUnit.Templates/content/TUnit.FSharp/TestProject.fsproj - TUnit.Templates/content/TUnit.Playwright/TestProject.csproj - TUnit.Templates/content/TUnit.VB/TestProject.vbproj - TUnit.Templates/content/TUnit/TestProject.csproj - TUnit.TestProject.FSharp/TUnit.TestProject.FSharp.fsproj - TUnit.TestProject.VB.NET/TUnit.TestProject.VB.NET.vbproj - TUnit.TestProject/TUnit.TestProject.csproj - TUnit.UnitTests/TUnit.UnitTests.csproj - - - - - - - - - - - - - - - - - - { - "keyToString": { - "node.js.selected.package.tslint": "(autodetect)" - } -} - - - - - - \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index dc9380f8f8..57b1feafef 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -58,10 +58,7 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + @@ -73,7 +70,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + @@ -82,12 +79,12 @@ - - - - - - + + + + + + diff --git a/Library.props b/Library.props index 36bd76fc63..c3e8636f73 100644 --- a/Library.props +++ b/Library.props @@ -8,10 +8,7 @@ true - - true - + true $(MSBuildThisFileDirectory)strongname.snk 0024000004800000940000000602000000240000525341310004000001000100698a70398fa0b2230c5a72e3bd9d56b48f809f6173e49a19fbb942d621be93ad48c5566b47b28faabc359b9ad3ff4e00bbdea88f5bdfa250f391fedd28182b2e37b55d429c0151a42a98ea7a5821818cd15a79fef9903e8607a88304cf3e0317bf86ec96e32e1381535a6582251e5a6eed40b5a3ed82bc444598b1269cce57a7 diff --git a/README.md b/README.md index f8c41764bc..c7c67a676d 100644 --- a/README.md +++ b/README.md @@ -440,10 +440,10 @@ Runtime=.NET 9.0 ``` | Method | Version | Mean | Error | StdDev | Median | |------------- |-------- |--------:|---------:|---------:|--------:| -| Build_TUnit | 0.61.58 | 1.740 s | 0.1459 s | 0.4302 s | 1.716 s | -| Build_NUnit | 4.4.0 | 1.982 s | 0.1231 s | 0.3609 s | 2.003 s | -| Build_xUnit | 2.9.3 | 1.573 s | 0.1605 s | 0.4732 s | 1.491 s | -| Build_MSTest | 3.11.0 | 1.425 s | 0.0672 s | 0.1895 s | 1.402 s | +| Build_TUnit | 0.63.3 | 1.462 s | 0.1537 s | 0.4532 s | 1.310 s | +| Build_NUnit | 4.4.0 | 1.744 s | 0.1092 s | 0.3168 s | 1.679 s | +| Build_xUnit | 2.9.3 | 1.641 s | 0.1261 s | 0.3698 s | 1.592 s | +| Build_MSTest | 3.11.0 | 1.636 s | 0.1609 s | 0.4668 s | 1.595 s | @@ -462,10 +462,10 @@ Runtime=.NET 9.0 ``` | Method | Version | Mean | Error | StdDev | Median | |------------- |-------- |--------:|---------:|---------:|--------:| -| Build_TUnit | 0.61.58 | 1.703 s | 0.0329 s | 0.0379 s | 1.695 s | -| Build_NUnit | 4.4.0 | 1.510 s | 0.0214 s | 0.0189 s | 1.510 s | -| Build_xUnit | 2.9.3 | 1.547 s | 0.0158 s | 0.0148 s | 1.548 s | -| Build_MSTest | 3.11.0 | 1.554 s | 0.0233 s | 0.0218 s | 1.558 s | +| Build_TUnit | 0.63.3 | 1.677 s | 0.0312 s | 0.0320 s | 1.674 s | +| Build_NUnit | 4.4.0 | 1.494 s | 0.0223 s | 0.0198 s | 1.490 s | +| Build_xUnit | 2.9.3 | 1.516 s | 0.0204 s | 0.0190 s | 1.515 s | +| Build_MSTest | 3.11.0 | 1.563 s | 0.0274 s | 0.0243 s | 1.551 s | @@ -484,10 +484,10 @@ Runtime=.NET 9.0 ``` | Method | Version | Mean | Error | StdDev | Median | |------------- |-------- |--------:|---------:|---------:|--------:| -| Build_TUnit | 0.61.58 | 1.898 s | 0.0378 s | 0.0478 s | 1.889 s | -| Build_NUnit | 4.4.0 | 1.690 s | 0.0321 s | 0.0330 s | 1.696 s | -| Build_xUnit | 2.9.3 | 1.666 s | 0.0175 s | 0.0163 s | 1.664 s | -| Build_MSTest | 3.11.0 | 1.731 s | 0.0331 s | 0.0310 s | 1.734 s | +| Build_TUnit | 0.63.3 | 1.816 s | 0.0320 s | 0.0300 s | 1.813 s | +| Build_NUnit | 4.4.0 | 1.740 s | 0.0344 s | 0.0756 s | 1.741 s | +| Build_xUnit | 2.9.3 | 1.746 s | 0.0308 s | 0.0240 s | 1.745 s | +| Build_MSTest | 3.11.0 | 1.949 s | 0.0594 s | 0.1723 s | 1.945 s | ### Scenario: Tests focused on assertion performance and validation @@ -505,20 +505,17 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|---------:|---------:|----------:| +| TUnit | 0.63.3 | 479.46 ms | 26.36 ms | 77.31 ms | 468.46 ms | +| NUnit | 4.4.0 | NA | NA | NA | NA | +| xUnit | 2.9.3 | NA | NA | NA | NA | +| MSTest | 3.11.0 | 772.99 ms | 27.36 ms | 79.82 ms | 767.38 ms | +| TUnit_AOT | 0.63.3 | 78.72 ms | 10.19 ms | 29.88 ms | 72.16 ms | Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) @@ -535,20 +532,13 @@ AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|----------:|----------:|----------:| +| TUnit | 0.63.3 | 476.11 ms | 3.318 ms | 2.941 ms | 475.39 ms | +| NUnit | 4.4.0 | 906.72 ms | 16.690 ms | 15.611 ms | 909.59 ms | +| xUnit | 2.9.3 | 981.64 ms | 17.772 ms | 16.624 ms | 984.23 ms | +| MSTest | 3.11.0 | 837.91 ms | 16.192 ms | 15.146 ms | 845.11 ms | +| TUnit_AOT | 0.63.3 | 25.04 ms | 0.435 ms | 0.407 ms | 24.90 ms | @@ -557,28 +547,21 @@ Benchmarks with issues: ``` BenchmarkDotNet v0.15.4, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley) (Hyper-V) -Intel Xeon Platinum 8370C CPU 2.80GHz (Max: 2.79GHz), 1 CPU, 4 logical and 2 physical cores +AMD EPYC 7763 2.44GHz, 1 CPU, 4 logical and 2 physical cores .NET SDK 9.0.305 - [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v4 - Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v4 + [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 + Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|------------:| +| TUnit | 0.63.3 | 579.08 ms | 11.140 ms | 11.439 ms | 579.59 ms | +| NUnit | 4.4.0 | 1,028.66 ms | 15.662 ms | 18.645 ms | 1,026.26 ms | +| xUnit | 2.9.3 | 1,100.01 ms | 15.464 ms | 14.465 ms | 1,098.76 ms | +| MSTest | 3.11.0 | 965.98 ms | 16.841 ms | 15.753 ms | 969.80 ms | +| TUnit_AOT | 0.63.3 | 64.84 ms | 1.596 ms | 4.706 ms | 64.04 ms | ### Scenario: Tests running asynchronous operations and async/await patterns @@ -596,20 +579,18 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |---------:|---------:|---------:|---------:| +| TUnit | 0.63.3 | 367.9 ms | 23.31 ms | 67.62 ms | 363.7 ms | +| NUnit | 4.4.0 | NA | NA | NA | NA | +| xUnit | 2.9.3 | NA | NA | NA | NA | +| MSTest | 3.11.0 | NA | NA | NA | NA | +| TUnit_AOT | 0.63.3 | 123.0 ms | 10.80 ms | 30.98 ms | 121.5 ms | Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) @@ -618,28 +599,21 @@ Benchmarks with issues: ``` BenchmarkDotNet v0.15.4, Linux Ubuntu 24.04.3 LTS (Noble Numbat) -AMD EPYC 7763 2.74GHz, 1 CPU, 4 logical and 2 physical cores +Intel Xeon Platinum 8370C CPU 2.80GHz (Max: 3.41GHz), 1 CPU, 4 logical and 2 physical cores .NET SDK 9.0.305 - [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 - Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 + [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v4 + Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v4 Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|----------:| +| TUnit | 0.63.3 | 447.75 ms | 3.328 ms | 3.113 ms | 448.32 ms | +| NUnit | 4.4.0 | 936.85 ms | 15.843 ms | 14.820 ms | 932.42 ms | +| xUnit | 2.9.3 | 1,000.39 ms | 15.065 ms | 14.092 ms | 997.53 ms | +| MSTest | 3.11.0 | 875.87 ms | 17.316 ms | 17.783 ms | 881.92 ms | +| TUnit_AOT | 0.63.3 | 34.15 ms | 1.021 ms | 2.979 ms | 33.99 ms | @@ -656,20 +630,13 @@ AMD EPYC 7763 2.44GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|------------:| +| TUnit | 0.63.3 | 487.90 ms | 6.862 ms | 6.419 ms | 488.06 ms | +| NUnit | 4.4.0 | 996.81 ms | 16.090 ms | 15.051 ms | 1,001.60 ms | +| xUnit | 2.9.3 | 1,078.25 ms | 21.004 ms | 25.004 ms | 1,074.69 ms | +| MSTest | 3.11.0 | 960.32 ms | 18.866 ms | 33.042 ms | 957.71 ms | +| TUnit_AOT | 0.63.3 | 89.64 ms | 2.507 ms | 7.352 ms | 89.31 ms | ### Scenario: Simple tests with basic operations and assertions @@ -687,20 +654,18 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|---------:|---------:|----------:| +| TUnit | 0.63.3 | 284.11 ms | 5.665 ms | 14.11 ms | 284.77 ms | +| NUnit | 4.4.0 | NA | NA | NA | NA | +| xUnit | 2.9.3 | NA | NA | NA | NA | +| MSTest | 3.11.0 | NA | NA | NA | NA | +| TUnit_AOT | 0.63.3 | 46.96 ms | 3.820 ms | 11.02 ms | 44.62 ms | Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) @@ -709,7 +674,7 @@ Benchmarks with issues: ``` BenchmarkDotNet v0.15.4, Linux Ubuntu 24.04.3 LTS (Noble Numbat) -AMD EPYC 7763 2.63GHz, 1 CPU, 4 logical and 2 physical cores +AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores .NET SDK 9.0.305 [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 @@ -717,20 +682,13 @@ AMD EPYC 7763 2.63GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|----------:|----------:|----------:| +| TUnit | 0.63.3 | 453.60 ms | 3.055 ms | 2.708 ms | 454.25 ms | +| NUnit | 4.4.0 | 899.90 ms | 16.844 ms | 15.756 ms | 899.44 ms | +| xUnit | 2.9.3 | 975.65 ms | 16.601 ms | 15.529 ms | 975.10 ms | +| MSTest | 3.11.0 | 829.74 ms | 16.432 ms | 17.582 ms | 829.26 ms | +| TUnit_AOT | 0.63.3 | 24.26 ms | 0.153 ms | 0.136 ms | 24.29 ms | @@ -747,20 +705,13 @@ AMD EPYC 7763 2.44GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|------------:| +| TUnit | 0.63.3 | 514.15 ms | 3.565 ms | 3.160 ms | 515.34 ms | +| NUnit | 4.4.0 | 1,007.07 ms | 20.094 ms | 18.796 ms | 1,016.18 ms | +| xUnit | 2.9.3 | 1,072.94 ms | 17.351 ms | 15.381 ms | 1,071.46 ms | +| MSTest | 3.11.0 | 960.30 ms | 19.039 ms | 36.681 ms | 957.30 ms | +| TUnit_AOT | 0.63.3 | 65.31 ms | 1.702 ms | 4.910 ms | 64.62 ms | ### Scenario: Parameterized tests with multiple test cases using data attributes @@ -778,20 +729,18 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|----------:|---------:|----------:| +| TUnit | 0.63.3 | 508.28 ms | 28.742 ms | 83.39 ms | 503.10 ms | +| NUnit | 4.4.0 | NA | NA | NA | NA | +| xUnit | 2.9.3 | NA | NA | NA | NA | +| MSTest | 3.11.0 | NA | NA | NA | NA | +| TUnit_AOT | 0.63.3 | 50.26 ms | 5.691 ms | 15.96 ms | 43.02 ms | Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) @@ -800,7 +749,7 @@ Benchmarks with issues: ``` BenchmarkDotNet v0.15.4, Linux Ubuntu 24.04.3 LTS (Noble Numbat) -AMD EPYC 7763 2.61GHz, 1 CPU, 4 logical and 2 physical cores +AMD EPYC 7763 3.14GHz, 1 CPU, 4 logical and 2 physical cores .NET SDK 9.0.305 [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 @@ -808,20 +757,13 @@ AMD EPYC 7763 2.61GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|----------:|----------:|----------:| +| TUnit | 0.63.3 | 455.80 ms | 3.669 ms | 3.253 ms | 455.17 ms | +| NUnit | 4.4.0 | 914.06 ms | 17.555 ms | 17.242 ms | 914.95 ms | +| xUnit | 2.9.3 | 979.27 ms | 16.884 ms | 15.794 ms | 973.97 ms | +| MSTest | 3.11.0 | 838.10 ms | 16.382 ms | 16.824 ms | 838.29 ms | +| TUnit_AOT | 0.63.3 | 26.17 ms | 0.143 ms | 0.111 ms | 26.19 ms | @@ -838,20 +780,13 @@ AMD EPYC 7763 2.44GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|------------:| +| TUnit | 0.63.3 | 538.01 ms | 8.772 ms | 8.206 ms | 537.61 ms | +| NUnit | 4.4.0 | 1,073.69 ms | 19.276 ms | 18.031 ms | 1,073.06 ms | +| xUnit | 2.9.3 | 1,213.12 ms | 24.081 ms | 36.043 ms | 1,203.63 ms | +| MSTest | 3.11.0 | 944.38 ms | 18.063 ms | 36.898 ms | 940.78 ms | +| TUnit_AOT | 0.63.3 | 70.66 ms | 1.623 ms | 4.604 ms | 69.71 ms | ### Scenario: Tests utilizing class fixtures and shared test context @@ -869,20 +804,17 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|----------:|----------:|----------:| +| TUnit | 0.63.3 | 288.07 ms | 5.635 ms | 8.434 ms | 286.94 ms | +| NUnit | 4.4.0 | NA | NA | NA | NA | +| xUnit | 2.9.3 | NA | NA | NA | NA | +| MSTest | 3.11.0 | 538.04 ms | 10.750 ms | 27.939 ms | 537.81 ms | +| TUnit_AOT | 0.63.3 | 61.74 ms | 7.554 ms | 22.155 ms | 57.27 ms | Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) @@ -891,7 +823,7 @@ Benchmarks with issues: ``` BenchmarkDotNet v0.15.4, Linux Ubuntu 24.04.3 LTS (Noble Numbat) -AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores +AMD EPYC 7763 2.61GHz, 1 CPU, 4 logical and 2 physical cores .NET SDK 9.0.305 [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 @@ -899,20 +831,13 @@ AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|----------:|----------:|----------:| +| TUnit | 0.63.3 | 455.15 ms | 5.557 ms | 5.198 ms | 455.25 ms | +| NUnit | 4.4.0 | 915.64 ms | 17.609 ms | 18.083 ms | 911.62 ms | +| xUnit | 2.9.3 | 988.17 ms | 13.009 ms | 12.169 ms | 983.08 ms | +| MSTest | 3.11.0 | 844.43 ms | 16.200 ms | 16.636 ms | 840.44 ms | +| TUnit_AOT | 0.63.3 | 41.37 ms | 1.147 ms | 3.365 ms | 41.22 ms | @@ -921,28 +846,21 @@ Benchmarks with issues: ``` BenchmarkDotNet v0.15.4, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley) (Hyper-V) -AMD EPYC 7763 2.44GHz, 1 CPU, 4 logical and 2 physical cores +Intel Xeon Platinum 8370C CPU 2.80GHz (Max: 2.79GHz), 1 CPU, 4 logical and 2 physical cores .NET SDK 9.0.305 - [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 - Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 + [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v4 + Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v4 Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|------------:| +| TUnit | 0.63.3 | 462.52 ms | 2.747 ms | 2.435 ms | 462.57 ms | +| NUnit | 4.4.0 | 960.55 ms | 16.492 ms | 15.427 ms | 955.02 ms | +| xUnit | 2.9.3 | 1,023.13 ms | 14.747 ms | 13.795 ms | 1,020.79 ms | +| MSTest | 3.11.0 | 902.64 ms | 17.032 ms | 15.932 ms | 904.73 ms | +| TUnit_AOT | 0.63.3 | 75.34 ms | 1.815 ms | 5.352 ms | 75.61 ms | ### Scenario: Tests executing in parallel to test framework parallelization @@ -960,20 +878,17 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|----------:|----------:|----------:| +| TUnit | 0.63.3 | 363.11 ms | 21.655 ms | 63.17 ms | 355.38 ms | +| NUnit | 4.4.0 | 810.36 ms | 39.599 ms | 116.14 ms | 817.71 ms | +| xUnit | 2.9.3 | NA | NA | NA | NA | +| MSTest | 3.11.0 | NA | NA | NA | NA | +| TUnit_AOT | 0.63.3 | 52.73 ms | 7.951 ms | 23.32 ms | 47.71 ms | Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) @@ -982,7 +897,7 @@ Benchmarks with issues: ``` BenchmarkDotNet v0.15.4, Linux Ubuntu 24.04.3 LTS (Noble Numbat) -AMD EPYC 7763 3.04GHz, 1 CPU, 4 logical and 2 physical cores +AMD EPYC 7763 2.60GHz, 1 CPU, 4 logical and 2 physical cores .NET SDK 9.0.305 [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 @@ -990,20 +905,13 @@ AMD EPYC 7763 3.04GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|------------:| +| TUnit | 0.63.3 | 447.17 ms | 4.052 ms | 3.790 ms | 446.70 ms | +| NUnit | 4.4.0 | 923.05 ms | 15.178 ms | 14.197 ms | 923.63 ms | +| xUnit | 2.9.3 | 1,005.70 ms | 19.824 ms | 25.071 ms | 1,012.18 ms | +| MSTest | 3.11.0 | 846.51 ms | 16.324 ms | 18.145 ms | 847.05 ms | +| TUnit_AOT | 0.63.3 | 24.71 ms | 0.117 ms | 0.104 ms | 24.71 ms | @@ -1020,20 +928,13 @@ AMD EPYC 7763 2.44GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|------------:| +| TUnit | 0.63.3 | 483.76 ms | 3.091 ms | 2.892 ms | 482.96 ms | +| NUnit | 4.4.0 | 989.91 ms | 19.172 ms | 18.830 ms | 990.27 ms | +| xUnit | 2.9.3 | 1,050.50 ms | 15.138 ms | 14.160 ms | 1,052.16 ms | +| MSTest | 3.11.0 | 917.36 ms | 17.850 ms | 18.331 ms | 919.22 ms | +| TUnit_AOT | 0.63.3 | 61.39 ms | 1.670 ms | 4.899 ms | 60.37 ms | ### Scenario: A test that takes 50ms to execute, repeated 100 times @@ -1051,20 +952,18 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|----------:|---------:|----------:| +| TUnit | 0.63.3 | 354.33 ms | 18.244 ms | 51.76 ms | 342.33 ms | +| NUnit | 4.4.0 | NA | NA | NA | NA | +| xUnit | 2.9.3 | NA | NA | NA | NA | +| MSTest | 3.11.0 | NA | NA | NA | NA | +| TUnit_AOT | 0.63.3 | 71.02 ms | 8.697 ms | 24.39 ms | 68.41 ms | Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) @@ -1081,20 +980,13 @@ AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|------------:| +| TUnit | 0.63.3 | 487.20 ms | 5.421 ms | 4.805 ms | 486.93 ms | +| NUnit | 4.4.0 | 939.51 ms | 18.004 ms | 17.683 ms | 938.30 ms | +| xUnit | 2.9.3 | 1,091.21 ms | 21.753 ms | 20.348 ms | 1,094.17 ms | +| MSTest | 3.11.0 | 867.68 ms | 17.173 ms | 19.777 ms | 872.92 ms | +| TUnit_AOT | 0.63.3 | 40.28 ms | 0.781 ms | 0.767 ms | 40.06 ms | @@ -1111,20 +1003,13 @@ AMD EPYC 7763 2.44GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|-----------:|------------:| +| TUnit | 0.63.3 | 547.41 ms | 7.923 ms | 7.412 ms | 544.94 ms | +| NUnit | 4.4.0 | 1,042.01 ms | 20.683 ms | 20.314 ms | 1,044.61 ms | +| xUnit | 2.9.3 | 1,256.12 ms | 37.748 ms | 111.302 ms | 1,201.34 ms | +| MSTest | 3.11.0 | 990.59 ms | 19.476 ms | 36.100 ms | 983.32 ms | +| TUnit_AOT | 0.63.3 | 76.87 ms | 1.118 ms | 0.933 ms | 77.14 ms | ### Scenario: Tests with setup and teardown lifecycle methods @@ -1142,20 +1027,18 @@ Apple M1 (Virtual), 1 CPU, 3 logical and 3 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |----------:|----------:|----------:|----------:| +| TUnit | 0.63.3 | 306.88 ms | 12.220 ms | 34.863 ms | 297.15 ms | +| NUnit | 4.4.0 | NA | NA | NA | NA | +| xUnit | 2.9.3 | NA | NA | NA | NA | +| MSTest | 3.11.0 | NA | NA | NA | NA | +| TUnit_AOT | 0.63.3 | 38.42 ms | 3.037 ms | 8.811 ms | 37.08 ms | Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) @@ -1164,7 +1047,7 @@ Benchmarks with issues: ``` BenchmarkDotNet v0.15.4, Linux Ubuntu 24.04.3 LTS (Noble Numbat) -AMD EPYC 7763 3.22GHz, 1 CPU, 4 logical and 2 physical cores +AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores .NET SDK 9.0.305 [Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 Job-YNJDZW : .NET 9.0.9 (9.0.9, 9.0.925.41916), X64 RyuJIT x86-64-v3 @@ -1172,20 +1055,13 @@ AMD EPYC 7763 3.22GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|----------:| +| TUnit | 0.63.3 | 455.06 ms | 4.366 ms | 3.871 ms | 456.07 ms | +| NUnit | 4.4.0 | 921.14 ms | 16.321 ms | 15.267 ms | 920.60 ms | +| xUnit | 2.9.3 | 1,004.66 ms | 17.672 ms | 16.530 ms | 999.12 ms | +| MSTest | 3.11.0 | 853.92 ms | 16.796 ms | 15.711 ms | 845.49 ms | +| TUnit_AOT | 0.63.3 | 25.88 ms | 0.175 ms | 0.164 ms | 25.89 ms | @@ -1202,20 +1078,13 @@ AMD EPYC 7763 2.44GHz, 1 CPU, 4 logical and 2 physical cores Runtime=.NET 9.0 ``` -| Method | Version | Mean | Error | StdDev | Median | -|---------- |-------- |-----:|------:|-------:|-------:| -| TUnit | 0.61.58 | NA | NA | NA | NA | -| NUnit | 4.4.0 | NA | NA | NA | NA | -| xUnit | 2.9.3 | NA | NA | NA | NA | -| MSTest | 3.11.0 | NA | NA | NA | NA | -| TUnit_AOT | 0.61.58 | NA | NA | NA | NA | - -Benchmarks with issues: - RuntimeBenchmarks.TUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.NUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.xUnit: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.MSTest: Job-YNJDZW(Runtime=.NET 9.0) - RuntimeBenchmarks.TUnit_AOT: Job-YNJDZW(Runtime=.NET 9.0) +| Method | Version | Mean | Error | StdDev | Median | +|---------- |-------- |------------:|----------:|----------:|------------:| +| TUnit | 0.63.3 | 493.83 ms | 2.563 ms | 2.397 ms | 493.07 ms | +| NUnit | 4.4.0 | 999.26 ms | 19.901 ms | 25.168 ms | 996.23 ms | +| xUnit | 2.9.3 | 1,057.71 ms | 15.826 ms | 14.804 ms | 1,058.51 ms | +| MSTest | 3.11.0 | 934.66 ms | 17.020 ms | 17.478 ms | 934.94 ms | +| TUnit_AOT | 0.63.3 | 62.90 ms | 1.511 ms | 4.455 ms | 62.61 ms | diff --git a/TUnit.Analyzers.CodeFixers/InheritsTestsCodeFixProvider.cs b/TUnit.Analyzers.CodeFixers/InheritsTestsCodeFixProvider.cs index 37c49cc804..1437836a79 100644 --- a/TUnit.Analyzers.CodeFixers/InheritsTestsCodeFixProvider.cs +++ b/TUnit.Analyzers.CodeFixers/InheritsTestsCodeFixProvider.cs @@ -16,12 +16,12 @@ namespace TUnit.Analyzers.CodeFixers; [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(InheritsTestsCodeFixProvider)), Shared] public class InheritsTestsCodeFixProvider : CodeFixProvider { - public override sealed ImmutableArray FixableDiagnosticIds { get; } = + public sealed override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(Rules.DoesNotInheritTestsWarning.Id); public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context) + public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { foreach (var diagnostic in context.Diagnostics) { diff --git a/TUnit.Analyzers.CodeFixers/XUnitMigrationCodeFixProvider.cs b/TUnit.Analyzers.CodeFixers/XUnitMigrationCodeFixProvider.cs index e36af3b34d..c0f66c91c3 100644 --- a/TUnit.Analyzers.CodeFixers/XUnitMigrationCodeFixProvider.cs +++ b/TUnit.Analyzers.CodeFixers/XUnitMigrationCodeFixProvider.cs @@ -11,12 +11,12 @@ namespace TUnit.Analyzers.CodeFixers; [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(XUnitMigrationCodeFixProvider)), Shared] public class XUnitMigrationCodeFixProvider : CodeFixProvider { - public override sealed ImmutableArray FixableDiagnosticIds { get; } = + public sealed override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(Rules.XunitMigration.Id); public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - public override sealed Task RegisterCodeFixesAsync(CodeFixContext context) + public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { foreach (var diagnostic in context.Diagnostics) { diff --git a/TUnit.Analyzers.Tests/AnalyzerTestHelpers.cs b/TUnit.Analyzers.Tests/AnalyzerTestHelpers.cs index 84123c7846..cfc1a476b4 100644 --- a/TUnit.Analyzers.Tests/AnalyzerTestHelpers.cs +++ b/TUnit.Analyzers.Tests/AnalyzerTestHelpers.cs @@ -183,7 +183,7 @@ public static CSharpSuppressorTest CreateSuppresso } } -file static class DiagnosticSeverityExtensions +static file class DiagnosticSeverityExtensions { public static ReportDiagnostic ToReportDiagnostic(this DiagnosticSeverity severity) => severity switch diff --git a/TUnit.Analyzers/ConcurrentDiagnosticAnalyzer.cs b/TUnit.Analyzers/ConcurrentDiagnosticAnalyzer.cs index 40473f4c39..d0114b7601 100644 --- a/TUnit.Analyzers/ConcurrentDiagnosticAnalyzer.cs +++ b/TUnit.Analyzers/ConcurrentDiagnosticAnalyzer.cs @@ -4,7 +4,7 @@ namespace TUnit.Analyzers; public abstract class ConcurrentDiagnosticAnalyzer : DiagnosticAnalyzer { - public override sealed void Initialize(AnalysisContext context) + public sealed override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); diff --git a/TUnit.Assertions.Analyzers.CodeFixers/AwaitAssertionCodeFixProvider.cs b/TUnit.Assertions.Analyzers.CodeFixers/AwaitAssertionCodeFixProvider.cs index f76ce17c6a..0924421d73 100644 --- a/TUnit.Assertions.Analyzers.CodeFixers/AwaitAssertionCodeFixProvider.cs +++ b/TUnit.Assertions.Analyzers.CodeFixers/AwaitAssertionCodeFixProvider.cs @@ -13,12 +13,12 @@ namespace TUnit.Assertions.Analyzers.CodeFixers; [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AwaitAssertionCodeFixProvider)), Shared] public class AwaitAssertionCodeFixProvider : CodeFixProvider { - public override sealed ImmutableArray FixableDiagnosticIds { get; } = + public sealed override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(Rules.AwaitAssertion.Id); public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context) + public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { foreach (var diagnostic in context.Diagnostics) { diff --git a/TUnit.Assertions.Analyzers.CodeFixers/XUnitAssertionCodeFixProvider.cs b/TUnit.Assertions.Analyzers.CodeFixers/XUnitAssertionCodeFixProvider.cs index f5f3846a73..c4f6adaea6 100644 --- a/TUnit.Assertions.Analyzers.CodeFixers/XUnitAssertionCodeFixProvider.cs +++ b/TUnit.Assertions.Analyzers.CodeFixers/XUnitAssertionCodeFixProvider.cs @@ -12,12 +12,12 @@ namespace TUnit.Assertions.Analyzers.CodeFixers; [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(XUnitAssertionCodeFixProvider)), Shared] public class XUnitAssertionCodeFixProvider : CodeFixProvider { - public override sealed ImmutableArray FixableDiagnosticIds { get; } = + public sealed override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(Rules.XUnitAssertion.Id); public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context) + public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { foreach (var diagnostic in context.Diagnostics) { diff --git a/TUnit.Assertions.Analyzers/ConcurrentDiagnosticAnalyzer.cs b/TUnit.Assertions.Analyzers/ConcurrentDiagnosticAnalyzer.cs index f7280fad44..0c71821ab2 100644 --- a/TUnit.Assertions.Analyzers/ConcurrentDiagnosticAnalyzer.cs +++ b/TUnit.Assertions.Analyzers/ConcurrentDiagnosticAnalyzer.cs @@ -4,7 +4,7 @@ namespace TUnit.Assertions.Analyzers; public abstract class ConcurrentDiagnosticAnalyzer : DiagnosticAnalyzer { - public override sealed void Initialize(AnalysisContext context) + public sealed override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); diff --git a/TUnit.Assertions/AssertConditions/BaseAssertCondition.cs b/TUnit.Assertions/AssertConditions/BaseAssertCondition.cs index cd2323f564..14a1c20b82 100644 --- a/TUnit.Assertions/AssertConditions/BaseAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/BaseAssertCondition.cs @@ -30,7 +30,7 @@ public AssertionResult FailWithMessage(string message) /// public virtual TimeSpan? WaitFor { get; protected set; } - internal protected abstract string GetExpectation(); + protected internal abstract string GetExpectation(); internal virtual string GetExpectationWithReason() => $"{GetExpectation()}{GetBecauseReason()}"; diff --git a/TUnit.Assertions/AssertConditions/Connectors/AndAssertCondition.cs b/TUnit.Assertions/AssertConditions/Connectors/AndAssertCondition.cs index a0509d97a8..a329cb9b05 100644 --- a/TUnit.Assertions/AssertConditions/Connectors/AndAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/Connectors/AndAssertCondition.cs @@ -18,12 +18,12 @@ public AndAssertCondition(BaseAssertCondition condition1, BaseAssertCondition co // Not used, as GetExpectationWithReason is overridden - internal protected override string GetExpectation() => ""; + protected internal override string GetExpectation() => ""; internal override string GetExpectationWithReason() => $"{_condition1.GetExpectationWithReason()}{Environment.NewLine} and {_condition2.GetExpectationWithReason()}"; - internal override sealed async ValueTask GetAssertionResult(object? actualValue, Exception? exception, AssertionMetadata assertionMetadata, string? actualExpression) + internal sealed override async ValueTask GetAssertionResult(object? actualValue, Exception? exception, AssertionMetadata assertionMetadata, string? actualExpression) { return (await _condition1.GetAssertionResult(actualValue, exception, assertionMetadata, actualExpression)) .And(await _condition2.GetAssertionResult(actualValue, exception, assertionMetadata, actualExpression)); diff --git a/TUnit.Assertions/AssertConditions/Connectors/OrAssertCondition.cs b/TUnit.Assertions/AssertConditions/Connectors/OrAssertCondition.cs index a255b967b9..001da713ec 100644 --- a/TUnit.Assertions/AssertConditions/Connectors/OrAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/Connectors/OrAssertCondition.cs @@ -17,12 +17,12 @@ public OrAssertCondition(BaseAssertCondition condition1, BaseAssertCondition con } // Not used, as GetExpectationWithReason is overridden - internal protected override string GetExpectation() => ""; + protected internal override string GetExpectation() => ""; internal override string GetExpectationWithReason() => $"{_condition1.GetExpectationWithReason()}{Environment.NewLine} or {_condition2.GetExpectationWithReason()}"; - internal override sealed async ValueTask GetAssertionResult(object? actualValue, Exception? exception, AssertionMetadata assertionMetadata, string? actualExpression) + internal sealed override async ValueTask GetAssertionResult(object? actualValue, Exception? exception, AssertionMetadata assertionMetadata, string? actualExpression) { return await (await _condition1.GetAssertionResult(actualValue, exception, assertionMetadata, actualExpression)) .OrAsync(() => _condition2.GetAssertionResult(actualValue, exception, assertionMetadata, actualExpression)); diff --git a/TUnit.Assertions/AssertConditions/ConvertToAssertCondition.cs b/TUnit.Assertions/AssertConditions/ConvertToAssertCondition.cs index ef7623d7e7..2df252afb3 100644 --- a/TUnit.Assertions/AssertConditions/ConvertToAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/ConvertToAssertCondition.cs @@ -6,7 +6,7 @@ public abstract class ConvertToAssertCondition : BaseAssertC public TToType? ConvertedValue { get; private set; } - protected override sealed async ValueTask GetResult(TFromType? actualValue, Exception? exception, AssertionMetadata assertionMetadata) + protected sealed override async ValueTask GetResult(TFromType? actualValue, Exception? exception, AssertionMetadata assertionMetadata) { var (result, convertedValue) = await ConvertValue(actualValue); diff --git a/TUnit.Assertions/AssertConditions/DelegateAssertCondition.cs b/TUnit.Assertions/AssertConditions/DelegateAssertCondition.cs index 7dad1571be..498ddb833e 100644 --- a/TUnit.Assertions/AssertConditions/DelegateAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/DelegateAssertCondition.cs @@ -43,7 +43,7 @@ AssertionMetadata assertionMetadata protected virtual string GetFailureMessage(TException? exception) => ""; - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return GetFailureMessage(Exception as TException); } diff --git a/TUnit.Assertions/AssertConditions/EnumerableSatisfiesAssertCondition.cs b/TUnit.Assertions/AssertConditions/EnumerableSatisfiesAssertCondition.cs index a2bc3904fb..2e649bd130 100644 --- a/TUnit.Assertions/AssertConditions/EnumerableSatisfiesAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/EnumerableSatisfiesAssertCondition.cs @@ -20,7 +20,7 @@ public EnumerableSatisfiesAssertCondition(Func?> mapper SetSubject(mapperExpression); } - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to satisfy {_assertionBuilderExpression}"; protected override async ValueTask GetResult( diff --git a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageContainingExpectedValueAssertCondition.cs b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageContainingExpectedValueAssertCondition.cs index e7be965bca..e3ce66464f 100644 --- a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageContainingExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageContainingExpectedValueAssertCondition.cs @@ -7,7 +7,7 @@ public class ExceptionMessageContainingExpectedValueAssertCondition( : ExpectedValueAssertCondition(expected) where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"message to contain {Formatter.Format(ExpectedValue).TruncateWithEllipsis(100)}"; protected override ValueTask GetResult(TException? actualValue, string? expectedValue) diff --git a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageEndingWithExpectedValueAssertCondition.cs b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageEndingWithExpectedValueAssertCondition.cs index bf1db7260f..e02c98bf65 100644 --- a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageEndingWithExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageEndingWithExpectedValueAssertCondition.cs @@ -7,7 +7,7 @@ public class ExceptionMessageEndingWithExpectedValueAssertCondition( : ExpectedValueAssertCondition(expected) where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"message to end with {Formatter.Format(ExpectedValue).TruncateWithEllipsis(100)}"; protected override ValueTask GetResult(TException? actualValue, string? expectedValue) diff --git a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageEqualsExpectedValueAssertCondition.cs index fdb91bb530..018fd4696c 100644 --- a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageEqualsExpectedValueAssertCondition.cs @@ -7,7 +7,7 @@ public class ExceptionMessageEqualsExpectedValueAssertCondition(stri : ExpectedValueAssertCondition(expected) where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"message to be equal to {Formatter.Format(expected).TruncateWithEllipsis(100)}"; protected override ValueTask GetResult(TException? actualValue, string? expectedValue) diff --git a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageMatchingExpectedAssertCondition.cs b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageMatchingExpectedAssertCondition.cs index b508db40ec..423a9a7e80 100644 --- a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageMatchingExpectedAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageMatchingExpectedAssertCondition.cs @@ -7,7 +7,7 @@ public class ExceptionMessageMatchingExpectedAssertCondition(StringM : ExpectedValueAssertCondition(match) where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"message to match {Formatter.Format(ExpectedValue).TruncateWithEllipsis(100)}"; protected override ValueTask GetResult(TException? actualValue, StringMatcher? expectedValue) diff --git a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageStartingWithExpectedValueAssertCondition.cs b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageStartingWithExpectedValueAssertCondition.cs index 9bc6ead209..e300f7f37d 100644 --- a/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageStartingWithExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/Exceptions/ExceptionMessageStartingWithExpectedValueAssertCondition.cs @@ -7,7 +7,7 @@ public class ExceptionMessageStartingWithExpectedValueAssertCondition(expected) where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"message to start with {Formatter.Format(ExpectedValue).TruncateWithEllipsis(100)}"; protected override ValueTask GetResult(TException? actualValue, string? expectedValue) diff --git a/TUnit.Assertions/AssertConditions/ExpectedValueAssertCondition.cs b/TUnit.Assertions/AssertConditions/ExpectedValueAssertCondition.cs index b5d1ff35a1..f465c3bd0f 100644 --- a/TUnit.Assertions/AssertConditions/ExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/ExpectedValueAssertCondition.cs @@ -1,3 +1,5 @@ +using System.Diagnostics.CodeAnalysis; + namespace TUnit.Assertions.AssertConditions; public abstract class ExpectedValueAssertCondition(TExpected? expected) : BaseAssertCondition diff --git a/TUnit.Assertions/AssertConditions/FuncValueAssertCondition.cs b/TUnit.Assertions/AssertConditions/FuncValueAssertCondition.cs index 29d308c99c..23ce4b6051 100644 --- a/TUnit.Assertions/AssertConditions/FuncValueAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/FuncValueAssertCondition.cs @@ -10,7 +10,7 @@ string expectation ) : ExpectedValueAssertCondition(expected) { - internal protected override string GetExpectation() => expectation; + protected internal override string GetExpectation() => expectation; protected override ValueTask GetResult(TActual? actualValue, TExpected? expectedValue) { diff --git a/TUnit.Assertions/AssertConditions/NotNullExpectedValueAssertCondition.cs b/TUnit.Assertions/AssertConditions/NotNullExpectedValueAssertCondition.cs index 9b6d52b77e..7da1ceeb4f 100644 --- a/TUnit.Assertions/AssertConditions/NotNullExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/NotNullExpectedValueAssertCondition.cs @@ -2,7 +2,7 @@ namespace TUnit.Assertions.AssertConditions; public class NotNullExpectedValueAssertCondition : ConvertToAssertCondition where TActual : class? { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => "to not be null"; public override ValueTask<(AssertionResult, TActual?)> ConvertValue(TActual? value) @@ -19,7 +19,7 @@ internal protected override string GetExpectation() public class NotNullStructExpectedValueAssertCondition : ConvertToAssertCondition where TActual : struct { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => "to not be null"; public override ValueTask<(AssertionResult, TActual)> ConvertValue(TActual? value) diff --git a/TUnit.Assertions/AssertConditions/NullExpectedValueAssertCondition.cs b/TUnit.Assertions/AssertConditions/NullExpectedValueAssertCondition.cs index d6c18f13d4..58e2143320 100644 --- a/TUnit.Assertions/AssertConditions/NullExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/NullExpectedValueAssertCondition.cs @@ -2,7 +2,7 @@ namespace TUnit.Assertions.AssertConditions; public class NullExpectedValueAssertCondition : BaseAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => "to be null"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/AssertConditions/SatisfiesAssertCondition.cs b/TUnit.Assertions/AssertConditions/SatisfiesAssertCondition.cs index fffe5a7414..a292938677 100644 --- a/TUnit.Assertions/AssertConditions/SatisfiesAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/SatisfiesAssertCondition.cs @@ -19,7 +19,7 @@ public SatisfiesAssertCondition(Func?> mapper, SetSubject(mapperExpression); } - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to satisfy {_assertionBuilderExpression}"; protected override async ValueTask GetResult( diff --git a/TUnit.Assertions/AssertConditions/StaticMethodAssertCondition.cs b/TUnit.Assertions/AssertConditions/StaticMethodAssertCondition.cs index b06bb5d588..39722187e7 100644 --- a/TUnit.Assertions/AssertConditions/StaticMethodAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/StaticMethodAssertCondition.cs @@ -31,7 +31,7 @@ protected override ValueTask GetResult(T? actualValue, Exceptio $"'{actualValue}' was expected {expectationVerb} {_methodName}()"); } - internal protected override string GetExpectation() + protected internal override string GetExpectation() { var expectationVerb = _negated ? "not to satisfy" : "to satisfy"; return $"{expectationVerb} {_methodName}()"; diff --git a/TUnit.Assertions/AssertConditions/ValueAssertCondition.cs b/TUnit.Assertions/AssertConditions/ValueAssertCondition.cs index efa7343d1f..beb72914fc 100644 --- a/TUnit.Assertions/AssertConditions/ValueAssertCondition.cs +++ b/TUnit.Assertions/AssertConditions/ValueAssertCondition.cs @@ -51,7 +51,7 @@ AssertionMetadata assertionMetadata protected abstract string GetFailureMessage(TActual? actualValue); - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return GetFailureMessage(ActualValue); } diff --git a/TUnit.Assertions/AssertionBuilders/AssertionBuilder.cs b/TUnit.Assertions/AssertionBuilders/AssertionBuilder.cs index b0db196802..276d2720cc 100644 --- a/TUnit.Assertions/AssertionBuilders/AssertionBuilder.cs +++ b/TUnit.Assertions/AssertionBuilders/AssertionBuilder.cs @@ -86,7 +86,7 @@ internal AssertionBuilder AppendConnector(ChainType chainType) return (AssertionBuilder) ((ISource) this).AppendExpression(chainType.ToString()); } - internal protected void AppendCallerMethod(string?[] expressions, [CallerMemberName] string methodName = "") + protected internal void AppendCallerMethod(string?[] expressions, [CallerMemberName] string methodName = "") { if (string.IsNullOrEmpty(methodName)) { diff --git a/TUnit.Assertions/AssertionBuilders/InvokableAssertionBuilder.cs b/TUnit.Assertions/AssertionBuilders/InvokableAssertionBuilder.cs index d72747d17b..f625c84cb1 100644 --- a/TUnit.Assertions/AssertionBuilders/InvokableAssertionBuilder.cs +++ b/TUnit.Assertions/AssertionBuilders/InvokableAssertionBuilder.cs @@ -46,5 +46,5 @@ string IInvokableAssertionBuilder.GetExpression() return $"{expression[..100]}..."; } - internal protected Stack Assertions => Source.Assertions; + protected internal Stack Assertions => Source.Assertions; } diff --git a/TUnit.Assertions/Assertions/Chronology/Conditions/DateOnlyEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Chronology/Conditions/DateOnlyEqualsExpectedValueAssertCondition.cs index 725d9dfc13..530e2d48e6 100644 --- a/TUnit.Assertions/Assertions/Chronology/Conditions/DateOnlyEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Chronology/Conditions/DateOnlyEqualsExpectedValueAssertCondition.cs @@ -6,7 +6,7 @@ public class DateOnlyEqualsExpectedValueAssertCondition(DateOnly expected) : Exp { private int? _tolerance; - internal protected override string GetExpectation() + protected internal override string GetExpectation() { if (_tolerance is null or 0) { diff --git a/TUnit.Assertions/Assertions/Chronology/Conditions/DateTimeEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Chronology/Conditions/DateTimeEqualsExpectedValueAssertCondition.cs index 69042edb92..1ff4693c85 100644 --- a/TUnit.Assertions/Assertions/Chronology/Conditions/DateTimeEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Chronology/Conditions/DateTimeEqualsExpectedValueAssertCondition.cs @@ -4,7 +4,7 @@ public class DateTimeEqualsExpectedValueAssertCondition(DateTime expected) : Exp { private TimeSpan? _tolerance; - internal protected override string GetExpectation() + protected internal override string GetExpectation() { if (_tolerance == null || _tolerance == TimeSpan.Zero) { diff --git a/TUnit.Assertions/Assertions/Chronology/Conditions/DateTimeOffsetEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Chronology/Conditions/DateTimeOffsetEqualsExpectedValueAssertCondition.cs index 9fb1dcc672..dc049505af 100644 --- a/TUnit.Assertions/Assertions/Chronology/Conditions/DateTimeOffsetEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Chronology/Conditions/DateTimeOffsetEqualsExpectedValueAssertCondition.cs @@ -4,7 +4,7 @@ public class DateTimeOffsetEqualsExpectedValueAssertCondition(DateTimeOffset exp { private TimeSpan? _tolerance; - internal protected override string GetExpectation() + protected internal override string GetExpectation() { if (_tolerance == null || _tolerance == TimeSpan.Zero) { diff --git a/TUnit.Assertions/Assertions/Chronology/Conditions/TimeOnlyEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Chronology/Conditions/TimeOnlyEqualsExpectedValueAssertCondition.cs index edff259ad7..8a085711d4 100644 --- a/TUnit.Assertions/Assertions/Chronology/Conditions/TimeOnlyEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Chronology/Conditions/TimeOnlyEqualsExpectedValueAssertCondition.cs @@ -6,7 +6,7 @@ public class TimeOnlyEqualsExpectedValueAssertCondition(TimeOnly expected) : Exp { private TimeSpan? _tolerance; - internal protected override string GetExpectation() + protected internal override string GetExpectation() { if (_tolerance == null || _tolerance == TimeSpan.Zero) { diff --git a/TUnit.Assertions/Assertions/Chronology/Conditions/TimeSpanEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Chronology/Conditions/TimeSpanEqualsExpectedValueAssertCondition.cs index 3b99b0a173..92afe966cc 100644 --- a/TUnit.Assertions/Assertions/Chronology/Conditions/TimeSpanEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Chronology/Conditions/TimeSpanEqualsExpectedValueAssertCondition.cs @@ -4,7 +4,7 @@ public class TimeSpanEqualsExpectedValueAssertCondition(TimeSpan expected) : Exp { private TimeSpan? _tolerance; - internal protected override string GetExpectation() + protected internal override string GetExpectation() { if (_tolerance == null || _tolerance == TimeSpan.Zero) { diff --git a/TUnit.Assertions/Assertions/ClassMembers/Conditions/PropertyEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/ClassMembers/Conditions/PropertyEqualsExpectedValueAssertCondition.cs index 7891109823..873722aa5a 100644 --- a/TUnit.Assertions/Assertions/ClassMembers/Conditions/PropertyEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/ClassMembers/Conditions/PropertyEqualsExpectedValueAssertCondition.cs @@ -7,15 +7,11 @@ namespace TUnit.Assertions.AssertConditions.ClassMember; public class PropertyEqualsExpectedValueAssertCondition(Expression> propertySelector, TPropertyType expected, bool isEqual) : ExpectedValueAssertCondition(expected) { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return $"{typeof(TRootObjectType).Name}.{ExpressionHelpers.GetName(propertySelector)} to be equal to {ExpectedValue}"; } -#pragma warning disable IL2046 // Member with 'RequiresUnreferencedCodeAttribute' overrides base member without 'RequiresUnreferencedCodeAttribute' -#pragma warning disable IL3051 // Member with 'RequiresDynamicCodeAttribute' overrides base member without 'RequiresDynamicCodeAttribute' - [RequiresUnreferencedCode("Expression compilation requires unreferenced code")] - [RequiresDynamicCode("Expression compilation requires dynamic code generation")] protected override ValueTask GetResult(TRootObjectType? actualValue, TPropertyType? expectedValue) { var propertyValue = GetPropertyValue(actualValue); @@ -26,11 +22,7 @@ protected override ValueTask GetResult(TRootObjectType? actualV $"received {GetPropertyValue(actualValue)?.ToString()}" ); } -#pragma warning restore IL3051 -#pragma warning restore IL2046 - [RequiresUnreferencedCode("Expression compilation requires unreferenced code")] - [RequiresDynamicCode("Expression compilation requires dynamic code generation")] private object? GetPropertyValue(TRootObjectType? actualValue) { if (actualValue is null) diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableAllExpectedFuncAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableAllExpectedFuncAssertCondition.cs index 32326148a1..989168c849 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableAllExpectedFuncAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableAllExpectedFuncAssertCondition.cs @@ -5,7 +5,7 @@ public class EnumerableAllExpectedFuncAssertCondition( : BaseAssertCondition where TActual : IEnumerable { - internal protected override string GetExpectation() => $"to contain only entries matching {matcherString ?? "null"}"; + protected internal override string GetExpectation() => $"to contain only entries matching {matcherString ?? "null"}"; protected override ValueTask GetResult( TActual? actualValue, Exception? exception, diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableContainsExpectedFuncAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableContainsExpectedFuncAssertCondition.cs index 7307252478..9212f5c026 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableContainsExpectedFuncAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableContainsExpectedFuncAssertCondition.cs @@ -6,7 +6,7 @@ public class EnumerableContainsExpectedFuncAssertCondition( where TActual : IEnumerable { private bool _wasFound; - internal protected override string GetExpectation() => $"to contain an entry matching {matcherString ?? "null"}"; + protected internal override string GetExpectation() => $"to contain an entry matching {matcherString ?? "null"}"; protected override ValueTask GetResult( TActual? actualValue, Exception? exception, diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableContainsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableContainsExpectedValueAssertCondition.cs index 46e5be8ae4..b1e81ed6c1 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableContainsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableContainsExpectedValueAssertCondition.cs @@ -6,7 +6,7 @@ public class EnumerableContainsExpectedValueAssertCondition( : ExpectedValueAssertCondition(expected) where TActual : IEnumerable { - internal protected override string GetExpectation() => $"to contain {ExpectedValue}"; + protected internal override string GetExpectation() => $"to contain {ExpectedValue}"; protected override ValueTask GetResult(TActual? actualValue, TInner? inner) => AssertionResult diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableCountEqualToExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableCountEqualToExpectedValueAssertCondition.cs index e72fb14221..56e12afa26 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableCountEqualToExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableCountEqualToExpectedValueAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.AssertConditions.Collections; public class EnumerableCountEqualToExpectedValueAssertCondition(int expected) : ExpectedValueAssertCondition(expected) where TActual : IEnumerable { - internal protected override string GetExpectation() => $"to have a count of {ExpectedValue}"; + protected internal override string GetExpectation() => $"to have a count of {ExpectedValue}"; protected override ValueTask GetResult(TActual? actualValue, int count) { diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableCountNotEqualToExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableCountNotEqualToExpectedValueAssertCondition.cs index b4d697af64..c5c4f9147b 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableCountNotEqualToExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableCountNotEqualToExpectedValueAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.AssertConditions.Collections; public class EnumerableCountNotEqualToExpectedValueAssertCondition(int expected) : ExpectedValueAssertCondition(expected) where TActual : IEnumerable { - internal protected override string GetExpectation() => $"to have a count different to {ExpectedValue}"; + protected internal override string GetExpectation() => $"to have a count different to {ExpectedValue}"; protected override ValueTask GetResult(TActual? actualValue, int count) { diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableDistinctItemsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableDistinctItemsExpectedValueAssertCondition.cs index 86bb0acac4..4db31b339c 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableDistinctItemsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableDistinctItemsExpectedValueAssertCondition.cs @@ -3,7 +3,7 @@ namespace TUnit.Assertions.AssertConditions.Collections; public class EnumerableDistinctItemsExpectedValueAssertCondition(IEqualityComparer? equalityComparer) : BaseAssertCondition where TActual : IEnumerable { - internal protected override string GetExpectation() => "items to be distinct"; + protected internal override string GetExpectation() => "items to be distinct"; protected override ValueTask GetResult( TActual? actualValue, Exception? exception, diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableEquivalentToExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableEquivalentToExpectedValueAssertCondition.cs index 5a6605d399..44d762c715 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableEquivalentToExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableEquivalentToExpectedValueAssertCondition.cs @@ -12,7 +12,7 @@ public class EnumerableEquivalentToExpectedValueAssertCondition : ExpectedValueAssertCondition>(expected) where TActual : IEnumerable? { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { if (!typeof(TInner).IsSimpleType() && equalityComparer is EquivalentToEqualityComparer { ComparisonFailures.Length: > 0 }) diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotContainsExpectedFuncAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotContainsExpectedFuncAssertCondition.cs index a28d8e76ae..2570bfca53 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotContainsExpectedFuncAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotContainsExpectedFuncAssertCondition.cs @@ -5,7 +5,7 @@ public class EnumerableNotContainsExpectedFuncAssertCondition( : BaseAssertCondition where TActual : IEnumerable { - internal protected override string GetExpectation() => $"to contain no entry matching {matcherString ?? "null"}"; + protected internal override string GetExpectation() => $"to contain no entry matching {matcherString ?? "null"}"; protected override ValueTask GetResult( TActual? actualValue, Exception? exception, diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotContainsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotContainsExpectedValueAssertCondition.cs index 11d7e99569..6294b87f32 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotContainsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotContainsExpectedValueAssertCondition.cs @@ -6,7 +6,7 @@ public class EnumerableNotContainsExpectedValueAssertCondition( : ExpectedValueAssertCondition(expected) where TActual : IEnumerable { - internal protected override string GetExpectation() => $"to not contain {ExpectedValue}"; + protected internal override string GetExpectation() => $"to not contain {ExpectedValue}"; protected override ValueTask GetResult(TActual? actualValue, TInner? inner) => AssertionResult diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotEquivalentToExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotEquivalentToExpectedValueAssertCondition.cs index 89f0d4dc45..44cb55f017 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotEquivalentToExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableNotEquivalentToExpectedValueAssertCondition.cs @@ -10,7 +10,7 @@ public class EnumerableNotEquivalentToExpectedValueAssertCondition>(expected) where TActual : IEnumerable? { - internal protected override string GetExpectation() => $"to not be equivalent to {(ExpectedValue != null ? Formatter.Format(ExpectedValue) : null)}"; + protected internal override string GetExpectation() => $"to not be equivalent to {(ExpectedValue != null ? Formatter.Format(ExpectedValue) : null)}"; protected override ValueTask GetResult(TActual? actualValue, IEnumerable? expectedValue) { diff --git a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableOrderedByAssertCondition.cs b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableOrderedByAssertCondition.cs index ba5d8dfff3..57f885e850 100644 --- a/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableOrderedByAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Collections/Conditions/EnumerableOrderedByAssertCondition.cs @@ -8,7 +8,7 @@ public class EnumerableOrderedByAssertCondition where TActual : IEnumerable { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return $"to be in {order} order"; } diff --git a/TUnit.Assertions/Assertions/Comparables/Conditions/BetweenAssertCondition.cs b/TUnit.Assertions/Assertions/Comparables/Conditions/BetweenAssertCondition.cs index 6e561b17ba..96f9739403 100644 --- a/TUnit.Assertions/Assertions/Comparables/Conditions/BetweenAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Comparables/Conditions/BetweenAssertCondition.cs @@ -5,7 +5,7 @@ public class BetweenAssertCondition(TActual minimum, TActual maximum) : { private bool _inclusiveBounds; - internal protected override string GetExpectation() => $"to be between {minimum} & {maximum} ({GetRange()} Range)"; + protected internal override string GetExpectation() => $"to be between {minimum} & {maximum} ({GetRange()} Range)"; protected override ValueTask GetResult( TActual? actualValue, Exception? exception, diff --git a/TUnit.Assertions/Assertions/Comparables/Conditions/NotBetweenAssertCondition.cs b/TUnit.Assertions/Assertions/Comparables/Conditions/NotBetweenAssertCondition.cs index 6712efaaaf..0acc08b9d6 100644 --- a/TUnit.Assertions/Assertions/Comparables/Conditions/NotBetweenAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Comparables/Conditions/NotBetweenAssertCondition.cs @@ -5,7 +5,7 @@ public class NotBetweenAssertCondition(TActual minimum, TActual maximum { private bool _inclusiveBounds; - internal protected override string GetExpectation() => $"to not be between {minimum} & {minimum} ({GetRange()} Range)"; + protected internal override string GetExpectation() => $"to not be between {minimum} & {minimum} ({GetRange()} Range)"; protected override ValueTask GetResult( TActual? actualValue, Exception? exception, diff --git a/TUnit.Assertions/Assertions/Delegates/Conditions/CompleteWithinAssertCondition.cs b/TUnit.Assertions/Assertions/Delegates/Conditions/CompleteWithinAssertCondition.cs index f339ea9cb7..090d245660 100644 --- a/TUnit.Assertions/Assertions/Delegates/Conditions/CompleteWithinAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Delegates/Conditions/CompleteWithinAssertCondition.cs @@ -6,7 +6,7 @@ namespace TUnit.Assertions.Assertions.Delegates; public class CompleteWithinAssertCondition(TimeSpan timeSpan) : DelegateAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to complete within {timeSpan.PrettyPrint()}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveFlagAssertCondition.cs b/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveFlagAssertCondition.cs index bdbf3fbf76..45c96ee5e4 100644 --- a/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveFlagAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveFlagAssertCondition.cs @@ -4,7 +4,7 @@ namespace TUnit.Assertions.Assertions.Enums.Conditions; public class EnumDoesNotHaveFlagAssertCondition(TEnum expected) : BaseAssertCondition where TEnum : Enum { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return $"to not have the flag {expected.ToString()}"; } diff --git a/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveSameNameAsCondition.cs b/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveSameNameAsCondition.cs index f33a453526..8e8c44c900 100644 --- a/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveSameNameAsCondition.cs +++ b/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveSameNameAsCondition.cs @@ -6,7 +6,7 @@ public class EnumDoesNotHaveSameNameAsCondition(TExpected expe where TEnum : Enum where TExpected : Enum { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return $"to not have the same name as {Enum.GetName(typeof(TExpected), expected)}"; } diff --git a/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveSameValueAsCondition.cs b/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveSameValueAsCondition.cs index a2e85913c2..4143be7b4e 100644 --- a/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveSameValueAsCondition.cs +++ b/TUnit.Assertions/Assertions/Enums/Conditions/EnumDoesNotHaveSameValueAsCondition.cs @@ -6,7 +6,7 @@ public class EnumDoesNotHaveSameValueAsCondition(TExpected exp where TEnum : Enum where TExpected : Enum { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return $"to not have the same value as {Enum.GetName(typeof(TExpected), expected)}"; } diff --git a/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasFlagAssertCondition.cs b/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasFlagAssertCondition.cs index 6cd7dd39be..7b7ee25669 100644 --- a/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasFlagAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasFlagAssertCondition.cs @@ -4,7 +4,7 @@ namespace TUnit.Assertions.Assertions.Enums.Conditions; public class EnumHasFlagAssertCondition(TEnum expected) : BaseAssertCondition where TEnum : Enum { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return $"to have the flag {expected.ToString()}"; } diff --git a/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasSameNameAsCondition.cs b/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasSameNameAsCondition.cs index 84c74ee6be..9344c89d05 100644 --- a/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasSameNameAsCondition.cs +++ b/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasSameNameAsCondition.cs @@ -6,7 +6,7 @@ public class EnumHasSameNameAsCondition(TExpected expected) : where TEnum : Enum where TExpected : Enum { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return $"to have the same name as {Enum.GetName(typeof(TExpected), expected)}"; } diff --git a/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasSameValueAsCondition.cs b/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasSameValueAsCondition.cs index b9b7308763..42652f8fad 100644 --- a/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasSameValueAsCondition.cs +++ b/TUnit.Assertions/Assertions/Enums/Conditions/EnumHasSameValueAsCondition.cs @@ -6,7 +6,7 @@ public class EnumHasSameValueAsCondition(TExpected expected) : where TEnum : Enum where TExpected : Enum { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return $"to have the same value as {Enum.GetName(typeof(TExpected), expected)}"; } diff --git a/TUnit.Assertions/Assertions/Enums/Conditions/EnumIsDefinedAssertCondition.cs b/TUnit.Assertions/Assertions/Enums/Conditions/EnumIsDefinedAssertCondition.cs index 88e46efb68..4e716788d4 100644 --- a/TUnit.Assertions/Assertions/Enums/Conditions/EnumIsDefinedAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Enums/Conditions/EnumIsDefinedAssertCondition.cs @@ -7,7 +7,7 @@ namespace TUnit.Assertions.Assertions.Enums.Conditions; public class EnumIsDefinedAssertCondition : BaseAssertCondition where TEnum : struct, Enum { - internal protected override string GetExpectation() => "to be defined"; + protected internal override string GetExpectation() => "to be defined"; protected override ValueTask GetResult( TEnum actualValue, Exception? exception, @@ -22,7 +22,7 @@ AssertionMetadata assertionMetadata public class EnumIsNotDefinedAssertCondition : BaseAssertCondition where TEnum : struct, Enum { - internal protected override string GetExpectation() => "to not be defined"; + protected internal override string GetExpectation() => "to not be defined"; protected override ValueTask GetResult( TEnum actualValue, Exception? exception, diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/AssignableFromExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/AssignableFromExpectedValueAssertCondition.cs index f409fbb439..5ffe74869a 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/AssignableFromExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/AssignableFromExpectedValueAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class AssignableFromExpectedValueAssertCondition(Type expectedType) : BaseAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to be assignable from type {expectedType.Name}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/AssignableToExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/AssignableToExpectedValueAssertCondition.cs index fe4a766291..1b1030a065 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/AssignableToExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/AssignableToExpectedValueAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class AssignableToExpectedValueAssertCondition(Type expectedType) : BaseAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to be assignable to type {expectedType.Name}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/ConvertExceptionToValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/ConvertExceptionToValueAssertCondition.cs index 8a410cb68a..dcaf46f1d8 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/ConvertExceptionToValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/ConvertExceptionToValueAssertCondition.cs @@ -5,14 +5,14 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class ConvertExceptionToValueAssertCondition : BaseAssertCondition where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() { return $"to throw {typeof(TException).Name}"; } public TException? ConvertedExceptionValue { get; private set; } - protected override sealed ValueTask GetResult(object? actualValue, Exception? exception, AssertionMetadata assertionMetadata) + protected sealed override ValueTask GetResult(object? actualValue, Exception? exception, AssertionMetadata assertionMetadata) { if (exception is null) { diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/DefaultAssertionCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/DefaultAssertionCondition.cs index 15e21a35fe..6ed110bbd5 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/DefaultAssertionCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/DefaultAssertionCondition.cs @@ -6,7 +6,7 @@ public class DefaultExpectedValueAssertCondition : BaseAssertCondition< { private readonly TActual? _defaultValue = default; - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to be {(_defaultValue is null ? "null" : _defaultValue)}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/DelegateConversionAssertionCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/DelegateConversionAssertionCondition.cs index d4cdd14dab..be037ecb4e 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/DelegateConversionAssertionCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/DelegateConversionAssertionCondition.cs @@ -7,7 +7,7 @@ public class DelegateConversionAssertionCondition( IDelegateSource source, BaseAssertCondition assertCondition) : BaseAssertCondition where TToType : Exception { - internal protected override string GetExpectation() => assertCondition.GetExpectation(); + protected internal override string GetExpectation() => assertCondition.GetExpectation(); protected override async ValueTask GetResult( TToType? actualValue, Exception? exception, diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/EqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/EqualsExpectedValueAssertCondition.cs index e62733b824..586e8c420d 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/EqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/EqualsExpectedValueAssertCondition.cs @@ -11,7 +11,7 @@ public EqualsExpectedValueAssertCondition(TActual expected) : this(expected, Equ { } - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to be equal to {ExpectedValue}"; protected override ValueTask GetResult(TActual? actualValue, TActual? expectedValue) diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/EquivalentToExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/EquivalentToExpectedValueAssertCondition.cs index 98646d1d5b..83892da041 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/EquivalentToExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/EquivalentToExpectedValueAssertCondition.cs @@ -18,7 +18,7 @@ public class EquivalentToExpectedValueAssertCondition< public EquivalencyKind EquivalencyKind { get; set; } = EquivalencyKind.Full; - internal protected override string GetExpectation() + protected internal override string GetExpectation() { var expectedMessage = typeof(TExpected).IsSimpleType() || typeof(IEnumerable).IsAssignableFrom(typeof(TExpected)) ? Formatter.Format(ExpectedValue) diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/NotAssignableFromExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/NotAssignableFromExpectedValueAssertCondition.cs index ebf87f078a..9ccfa75d32 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/NotAssignableFromExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/NotAssignableFromExpectedValueAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class NotAssignableFromExpectedValueAssertCondition(Type expectedType) : BaseAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to not be assignable from type {expectedType.Name}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/NotAssignableToExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/NotAssignableToExpectedValueAssertCondition.cs index 30f3b2e652..8713de0a58 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/NotAssignableToExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/NotAssignableToExpectedValueAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class NotAssignableToExpectedValueAssertCondition(Type expectedType) : BaseAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to not be assignable to type {expectedType.Name}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/NotDefaultAssertionCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/NotDefaultAssertionCondition.cs index 85a77f91a4..1f248a2994 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/NotDefaultAssertionCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/NotDefaultAssertionCondition.cs @@ -6,7 +6,7 @@ public class NotDefaultExpectedValueAssertCondition() : ExpectedValueAs { private readonly TActual? _defaultValue = default; - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to not be {(_defaultValue is null ? "null" : _defaultValue)}"; protected override ValueTask GetResult(TActual? actualValue, TActual? expectedValue) diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/NotEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/NotEqualsExpectedValueAssertCondition.cs index 645f8e63eb..41150af165 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/NotEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/NotEqualsExpectedValueAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class NotEqualsExpectedValueAssertCondition(TActual expected) : ExpectedValueAssertCondition(expected) { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to not be equal to {ExpectedValue}"; protected override ValueTask GetResult(TActual? actualValue, TActual? expectedValue) => AssertionResult diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/NotEquivalentToExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/NotEquivalentToExpectedValueAssertCondition.cs index fe7c74ebf0..02b4617484 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/NotEquivalentToExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/NotEquivalentToExpectedValueAssertCondition.cs @@ -19,7 +19,7 @@ public class NotEquivalentToExpectedValueAssertCondition< public EquivalencyKind EquivalencyKind { get; set; } = EquivalencyKind.Full; - internal protected override string GetExpectation() + protected internal override string GetExpectation() { var expectedMessage = typeof(TExpected).IsSimpleType() || typeof(IEnumerable).IsAssignableFrom(typeof(TExpected)) ? Formatter.Format(ExpectedValue) diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/NotSameReferenceExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/NotSameReferenceExpectedValueAssertCondition.cs index 585bfa2799..06f9403a56 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/NotSameReferenceExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/NotSameReferenceExpectedValueAssertCondition.cs @@ -6,7 +6,7 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class NotSameReferenceExpectedValueAssertCondition(TExpected expected) : ExpectedValueAssertCondition(expected) { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to not have the same reference as {ExpectedValue}"; protected override ValueTask GetResult(TActual? actualValue, TExpected? expectedValue) diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/NotTypeOfExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/NotTypeOfExpectedValueAssertCondition.cs index d3590f7f2e..b5032f3ad5 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/NotTypeOfExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/NotTypeOfExpectedValueAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class NotTypeOfExpectedValueAssertCondition(Type expected) : BaseAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to not be of type {expected.Name}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/SameReferenceExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/SameReferenceExpectedValueAssertCondition.cs index 839ff8caf8..3103e426a9 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/SameReferenceExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/SameReferenceExpectedValueAssertCondition.cs @@ -6,7 +6,7 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class SameReferenceExpectedValueAssertCondition(TExpected expected) : ExpectedValueAssertCondition(expected) { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to have the same reference as {ExpectedValue}"; protected override ValueTask GetResult(TActual? actualValue, TExpected? expectedValue) diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/TypeOfExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/TypeOfExpectedValueAssertCondition.cs index 1a0388d24a..1873e2bb9d 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/TypeOfExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/TypeOfExpectedValueAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.Assertions.Generics.Conditions; public class TypeOfExpectedValueAssertCondition(Type expectedType) : BaseAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to be of type {expectedType.Name}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Generics/Conditions/ValueConversionAssertionCondition.cs b/TUnit.Assertions/Assertions/Generics/Conditions/ValueConversionAssertionCondition.cs index abc8df47ce..3ed90a94b1 100644 --- a/TUnit.Assertions/Assertions/Generics/Conditions/ValueConversionAssertionCondition.cs +++ b/TUnit.Assertions/Assertions/Generics/Conditions/ValueConversionAssertionCondition.cs @@ -7,7 +7,7 @@ public class ValueConversionAssertionCondition( ISource source, ConvertToAssertCondition convertToAssertCondition) : BaseAssertCondition { - internal protected override string GetExpectation() => convertToAssertCondition.GetExpectation(); + protected internal override string GetExpectation() => convertToAssertCondition.GetExpectation(); protected override async ValueTask GetResult( TToType? actualValue, Exception? exception, diff --git a/TUnit.Assertions/Assertions/Strings/Conditions/StringContainsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Strings/Conditions/StringContainsExpectedValueAssertCondition.cs index f585e0d1f4..1f2c82b850 100644 --- a/TUnit.Assertions/Assertions/Strings/Conditions/StringContainsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Strings/Conditions/StringContainsExpectedValueAssertCondition.cs @@ -9,7 +9,7 @@ public class StringContainsExpectedValueAssertCondition(string expected, StringC { internal bool IgnoreWhitespace { get; set; } - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to contain {Formatter.Format(ExpectedValue).TruncateWithEllipsis(100)}"; protected override ValueTask GetResult(string? actualValue, string? expectedValue) diff --git a/TUnit.Assertions/Assertions/Strings/Conditions/StringEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Strings/Conditions/StringEqualsExpectedValueAssertCondition.cs index e5a6a31726..0c5fc8341c 100644 --- a/TUnit.Assertions/Assertions/Strings/Conditions/StringEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Strings/Conditions/StringEqualsExpectedValueAssertCondition.cs @@ -6,7 +6,7 @@ namespace TUnit.Assertions.AssertConditions.String; public class StringEqualsExpectedValueAssertCondition(string expected, StringComparison stringComparison) : ExpectedValueAssertCondition(expected) { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to be equal to {Formatter.Format(ExpectedValue).TruncateWithEllipsis(100)}"; protected override ValueTask GetResult(string? actualValue, string? expectedValue) diff --git a/TUnit.Assertions/Assertions/Strings/Conditions/StringNotContainsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Strings/Conditions/StringNotContainsExpectedValueAssertCondition.cs index 097ae274c0..c635183b46 100644 --- a/TUnit.Assertions/Assertions/Strings/Conditions/StringNotContainsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Strings/Conditions/StringNotContainsExpectedValueAssertCondition.cs @@ -6,7 +6,7 @@ namespace TUnit.Assertions.AssertConditions.String; public class StringNotContainsExpectedValueAssertCondition(string expected, StringComparison stringComparison) : ExpectedValueAssertCondition(expected) { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to not contain {Formatter.Format(ExpectedValue).TruncateWithEllipsis(100)}"; protected override ValueTask GetResult(string? actualValue, string? expectedValue) diff --git a/TUnit.Assertions/Assertions/Strings/Conditions/StringNotEqualsExpectedValueAssertCondition.cs b/TUnit.Assertions/Assertions/Strings/Conditions/StringNotEqualsExpectedValueAssertCondition.cs index 011d1c6fec..27941eac79 100644 --- a/TUnit.Assertions/Assertions/Strings/Conditions/StringNotEqualsExpectedValueAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Strings/Conditions/StringNotEqualsExpectedValueAssertCondition.cs @@ -6,7 +6,7 @@ namespace TUnit.Assertions.AssertConditions.String; public class StringNotEqualsExpectedValueAssertCondition(string expected, StringComparison stringComparison) : ExpectedValueAssertCondition(expected) { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to not be equal to {Formatter.Format(ExpectedValue).TruncateWithEllipsis(100)}"; protected override ValueTask GetResult(string? actualValue, string? expectedValue) diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsAnyExceptionAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsAnyExceptionAssertCondition.cs index 8e8468d31e..6e0576e5b1 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsAnyExceptionAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsAnyExceptionAssertCondition.cs @@ -3,7 +3,7 @@ namespace TUnit.Assertions.AssertConditions.Throws; public class ThrowsAnyExceptionAssertCondition : DelegateAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => "to throw an exception"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsExactlyAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsExactlyAssertCondition.cs index 5eefcbb60e..79c29dac7d 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsExactlyAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsExactlyAssertCondition.cs @@ -5,7 +5,7 @@ namespace TUnit.Assertions.AssertConditions.Throws; public class ThrowsExactTypeOfDelegateAssertCondition : DelegateAssertCondition where TExpectedException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to throw exactly {typeof(TExpectedException).Name.PrependAOrAn()}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsNothingAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsNothingAssertCondition.cs index 317fb715d9..668763cc0e 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsNothingAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsNothingAssertCondition.cs @@ -4,7 +4,7 @@ namespace TUnit.Assertions.AssertConditions.Throws; public class ThrowsNothingAssertCondition : DelegateAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => "to throw nothing"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsOfTypeAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsOfTypeAssertCondition.cs index 5708a1a327..d15f8df4e5 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsOfTypeAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsOfTypeAssertCondition.cs @@ -4,7 +4,7 @@ namespace TUnit.Assertions.AssertConditions.Throws; public class ThrowsOfTypeAssertCondition(Type type) : DelegateAssertCondition { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to throw {type.Name.PrependAOrAn()}"; protected override ValueTask GetResult( @@ -21,7 +21,7 @@ AssertionMetadata assertionMetadata public class ThrowsOfTypeAssertCondition : DelegateAssertCondition where TExpectedException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to throw {typeof(TExpectedException).Name.PrependAOrAn()}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageAssertCondition.cs index 551d00e99f..2350d75a41 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageAssertCondition.cs @@ -10,7 +10,7 @@ public class ThrowsWithMessageAssertCondition( : DelegateAssertCondition where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to throw {typeof(TException).Name.PrependAOrAn()} which message equals \"{expectedMessage.ShowNewLines().TruncateWithEllipsis(100)}\""; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageContainingAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageContainingAssertCondition.cs index 1138edd1ba..13638ad18b 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageContainingAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageContainingAssertCondition.cs @@ -9,7 +9,7 @@ public class ThrowsWithMessageContainingAssertCondition( : DelegateAssertCondition where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to throw {typeof(TException).Name.PrependAOrAn()} which message contains \"{expected?.ShowNewLines().TruncateWithEllipsis(100)}\""; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageMatchingAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageMatchingAssertCondition.cs index 0cdee87585..4afbf691d3 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageMatchingAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageMatchingAssertCondition.cs @@ -8,7 +8,7 @@ public class ThrowsWithMessageMatchingAssertCondition( : DelegateAssertCondition where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to throw {typeof(TException).Name.PrependAOrAn()} which message matches \"{match.ToString()?.ShowNewLines().TruncateWithEllipsis(100)}\""; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageNotContainingAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageNotContainingAssertCondition.cs index a5c6565745..544668a21b 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageNotContainingAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsWithMessageNotContainingAssertCondition.cs @@ -9,7 +9,7 @@ public class ThrowsWithMessageNotContainingAssertCondition( : DelegateAssertCondition where TException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to throw {typeof(TException).Name.PrependAOrAn()} which message does not contain \"{expected?.ShowNewLines().TruncateWithEllipsis(100)}\""; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsWithParamNameAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsWithParamNameAssertCondition.cs index e1b9840ed2..e99c58fe9b 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsWithParamNameAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsWithParamNameAssertCondition.cs @@ -10,7 +10,7 @@ public class ThrowsWithParamNameAssertCondition( : DelegateAssertCondition() where TException : ArgumentException { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to throw {typeof(TException).Name.PrependAOrAn()} which param name equals \"{expectedParamName.TruncateWithEllipsis(100)}\""; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Assertions/Throws/ThrowsWithinAssertCondition.cs b/TUnit.Assertions/Assertions/Throws/ThrowsWithinAssertCondition.cs index 82c98589ae..61758c88a4 100644 --- a/TUnit.Assertions/Assertions/Throws/ThrowsWithinAssertCondition.cs +++ b/TUnit.Assertions/Assertions/Throws/ThrowsWithinAssertCondition.cs @@ -8,7 +8,7 @@ namespace TUnit.Assertions.AssertConditions.Throws; public class ThrowsWithinAssertCondition(TimeSpan timeSpan) : DelegateAssertCondition where TExpectedException : Exception { - internal protected override string GetExpectation() + protected internal override string GetExpectation() => $"to throw {typeof(TExpectedException).Name.PrependAOrAn()} within {timeSpan.PrettyPrint()}"; protected override ValueTask GetResult( diff --git a/TUnit.Assertions/Compare.cs b/TUnit.Assertions/Compare.cs index 52a366e3bd..7b665f35ab 100644 --- a/TUnit.Assertions/Compare.cs +++ b/TUnit.Assertions/Compare.cs @@ -1,15 +1,13 @@ -#pragma warning disable IL2072 // Target type's member does not satisfy requirements -#pragma warning disable IL2075 // Target method return value does not satisfy requirements -// Note: Comparison logic uses reflection for deep object comparison. For AOT scenarios, use explicit comparison methods. - -using System.Collections; +using System.Collections; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Runtime.CompilerServices; using TUnit.Assertions.Enums; using TUnit.Assertions.Extensions; namespace TUnit.Assertions; +[UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "AOT mode uses the attributed compiler type instead of the runtime GetType.")] public static class Compare { private static readonly BindingFlags BindingFlags = @@ -65,7 +63,20 @@ private static IEnumerable CheckEquivalent< yield break; } - if (actual.GetType().IsSimpleType()) + var actualType = +#if NET + RuntimeFeature.IsDynamicCodeSupported ? actual.GetType() : typeof(TActual); +#else + actual.GetType(); +#endif + var expectedType = +#if NET + RuntimeFeature.IsDynamicCodeSupported ? expected.GetType() : typeof(TExpected); +#else + expected.GetType(); +#endif + + if (actualType.IsSimpleType()) { yield return new ComparisonFailure { @@ -157,7 +168,7 @@ private static IEnumerable CheckEquivalent< yield break; } - foreach (var fieldName in actual.GetType().GetFields().Concat(expected.GetType().GetFields()) + foreach (var fieldName in actualType.GetFields().Concat(expectedType.GetFields()) .Where(x => !x.Name.StartsWith('<')) .Select(x => x.Name) .Distinct()) @@ -169,8 +180,8 @@ private static IEnumerable CheckEquivalent< continue; } - var actualFieldInfo = actual.GetType().GetField(fieldName, BindingFlags); - var expectedFieldInfo = expected.GetType().GetField(fieldName, BindingFlags); + var actualFieldInfo = actualType.GetField(fieldName, BindingFlags); + var expectedFieldInfo = expectedType.GetField(fieldName, BindingFlags); // Check if field type should be ignored if (actualFieldInfo != null && ShouldIgnoreType(actualFieldInfo.FieldType, options.TypesToIgnore)) @@ -217,7 +228,7 @@ private static IEnumerable CheckEquivalent< } } - foreach (var propertyName in actual.GetType().GetProperties().Concat(expected.GetType().GetProperties()) + foreach (var propertyName in actualType.GetProperties().Concat(expectedType.GetProperties()) .Where(p => p.GetIndexParameters().Length == 0) .Select(x => x.Name) .Distinct()) @@ -229,8 +240,8 @@ private static IEnumerable CheckEquivalent< continue; } - var actualPropertyInfo = actual.GetType().GetProperty(propertyName, BindingFlags); - var expectedPropertyInfo = expected.GetType().GetProperty(propertyName, BindingFlags); + var actualPropertyInfo = actualType.GetProperty(propertyName, BindingFlags); + var expectedPropertyInfo = expectedType.GetProperty(propertyName, BindingFlags); // Check if property type should be ignored if (actualPropertyInfo != null && ShouldIgnoreType(actualPropertyInfo.PropertyType, options.TypesToIgnore)) @@ -306,8 +317,8 @@ private static bool ShouldIgnoreType(Type type, Type[] typesToIgnore) var underlyingType = Nullable.GetUnderlyingType(type) ?? type; // Check if the type or its underlying type (for nullable) should be ignored - return typesToIgnore.Any(ignoredType => - type == ignoredType || + return typesToIgnore.Any(ignoredType => + type == ignoredType || underlyingType == ignoredType || type.IsAssignableFrom(ignoredType) || underlyingType.IsAssignableFrom(ignoredType)); diff --git a/TUnit.Core.SourceGenerator.Tests/ArgsAsArrayTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ArgsAsArrayTests.Test.verified.txt index dafd68991a..7bee396621 100644 --- a/TUnit.Core.SourceGenerator.Tests/ArgsAsArrayTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ArgsAsArrayTests.Test.verified.txt @@ -15,8 +15,7 @@ internal sealed class ArgsAsArrayTests_Params_TestSource_GUID : global::TUnit.Co Dependencies = global::System.Array.Empty(), AttributeFactory = () => [ - new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("arg1", "arg2", "arg3") + new global::TUnit.Core.TestAttribute() ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] { @@ -164,8 +163,7 @@ internal sealed class ArgsAsArrayTests_NonParams_TestSource_GUID : global::TUnit Dependencies = global::System.Array.Empty(), AttributeFactory = () => [ - new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("arg1", "arg2", "arg3") + new global::TUnit.Core.TestAttribute() ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] { @@ -277,8 +275,7 @@ internal sealed class ArgsAsArrayTests_ParamsEnumerable_TestSource_GUID : global Dependencies = global::System.Array.Empty(), AttributeFactory = () => [ - new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("arg1", "arg2", "arg3") + new global::TUnit.Core.TestAttribute() ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] { @@ -426,8 +423,7 @@ internal sealed class ArgsAsArrayTests_Enumerable_TestSource_GUID : global::TUni Dependencies = global::System.Array.Empty(), AttributeFactory = () => [ - new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("arg1", "arg2", "arg3") + new global::TUnit.Core.TestAttribute() ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] { @@ -539,8 +535,7 @@ internal sealed class ArgsAsArrayTests_Following_Non_Params_TestSource_GUID : gl Dependencies = global::System.Array.Empty(), AttributeFactory = () => [ - new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1, "arg1", "arg2", "arg3") + new global::TUnit.Core.TestAttribute() ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] { diff --git a/TUnit.Core.SourceGenerator.Tests/ArgumentWithImplicitConverterTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ArgumentWithImplicitConverterTests.Test.verified.txt index 7c34c38f6e..21f00af10f 100644 --- a/TUnit.Core.SourceGenerator.Tests/ArgumentWithImplicitConverterTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ArgumentWithImplicitConverterTests.Test.verified.txt @@ -16,9 +16,6 @@ internal sealed class ArgumentWithImplicitConverterTests_Explicit_TestSource_GUI AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), - new global::TUnit.Core.ArgumentsAttribute(2), - new global::TUnit.Core.ArgumentsAttribute(3), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -134,9 +131,6 @@ internal sealed class ArgumentWithImplicitConverterTests_Implicit_TestSource_GUI AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), - new global::TUnit.Core.ArgumentsAttribute(2), - new global::TUnit.Core.ArgumentsAttribute(3), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/AsyncMethodDataSourceDrivenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/AsyncMethodDataSourceDrivenTests.Test.verified.txt index 5f56d0cfc9..35f44841f8 100644 --- a/TUnit.Core.SourceGenerator.Tests/AsyncMethodDataSourceDrivenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/AsyncMethodDataSourceDrivenTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class AsyncMethodDataSourceDrivenTests_AsyncMethodDataSource_Sin AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("AsyncDataMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -149,7 +148,6 @@ internal sealed class AsyncMethodDataSourceDrivenTests_AsyncMethodDataSource_Tup AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("AsyncDataMethodWithTuples"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -289,7 +287,6 @@ internal sealed class AsyncMethodDataSourceDrivenTests_AsyncMethodDataSource_Enu AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("AsyncEnumerableDataMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -422,7 +419,6 @@ internal sealed class AsyncMethodDataSourceDrivenTests_AsyncMethodDataSource_Fun AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("AsyncFuncDataMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -555,8 +551,6 @@ internal sealed class AsyncMethodDataSourceDrivenTests_AsyncMethodDataSource_Wit AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("AsyncDataMethodWithArgs") -{Arguments = new object[]{5},}, new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -689,7 +683,6 @@ internal sealed class AsyncMethodDataSourceDrivenTests_AsyncMethodDataSource_Ext AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute(typeof(global::TUnit.TestProject.AsyncExternalDataSource), "GetData"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -822,7 +815,6 @@ internal sealed class AsyncMethodDataSourceDrivenTests_ValueTaskMethodDataSource AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("ValueTaskDataMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/ClassAndMethodArgumentsTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ClassAndMethodArgumentsTests.Test.verified.txt index 1c762b648f..ed3be73b16 100644 --- a/TUnit.Core.SourceGenerator.Tests/ClassAndMethodArgumentsTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ClassAndMethodArgumentsTests.Test.verified.txt @@ -118,8 +118,6 @@ internal sealed class ClassAndMethodArgumentsTests_WithMethodLevel_TestSource_GU AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("3"), - new global::TUnit.Core.ArgumentsAttribute("4"), new global::TUnit.Core.ArgumentsAttribute("1"), new global::TUnit.Core.ArgumentsAttribute("2") ], @@ -249,8 +247,6 @@ internal sealed class ClassAndMethodArgumentsTests_IgnoreParameters_TestSource_G AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("3"), - new global::TUnit.Core.ArgumentsAttribute("4"), new global::TUnit.Core.ArgumentsAttribute("1"), new global::TUnit.Core.ArgumentsAttribute("2") ], diff --git a/TUnit.Core.SourceGenerator.Tests/ClassDataSourceDrivenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ClassDataSourceDrivenTests.Test.verified.txt index 89a64e9308..71a9fe04e8 100644 --- a/TUnit.Core.SourceGenerator.Tests/ClassDataSourceDrivenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ClassDataSourceDrivenTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class ClassDataSourceDrivenTests_DataSource_Class_TestSource_GUI AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ClassDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -130,7 +129,6 @@ internal sealed class ClassDataSourceDrivenTests_DataSource_Class_Generic_TestSo AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ClassDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -244,7 +242,6 @@ internal sealed class ClassDataSourceDrivenTests_IsInitialized_With_1_ClassDataS AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ClassDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -356,7 +353,6 @@ internal sealed class ClassDataSourceDrivenTests_IsInitialized_With_2_ClassDataS AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ClassDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -475,7 +471,6 @@ internal sealed class ClassDataSourceDrivenTests_IsInitialized_With_3_ClassDataS AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ClassDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -601,7 +596,6 @@ internal sealed class ClassDataSourceDrivenTests_IsInitialized_With_4_ClassDataS AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ClassDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -734,7 +728,6 @@ internal sealed class ClassDataSourceDrivenTests_IsInitialized_With_5_ClassDataS AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ClassDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/ClassDataSourceDrivenTestsSharedKeyed.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ClassDataSourceDrivenTestsSharedKeyed.Test.verified.txt index b850a9b3bc..94e899eceb 100644 --- a/TUnit.Core.SourceGenerator.Tests/ClassDataSourceDrivenTestsSharedKeyed.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ClassDataSourceDrivenTestsSharedKeyed.Test.verified.txt @@ -16,8 +16,6 @@ internal sealed class ClassDataSourceDrivenTestsSharedKeyed_DataSource_Class_Tes AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ClassDataSourceAttribute() -{Shared = global::TUnit.Core.SharedType.Keyed,Key = "🔑",}, new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -132,8 +130,6 @@ internal sealed class ClassDataSourceDrivenTestsSharedKeyed_DataSource_Class_Gen AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ClassDataSourceAttribute() -{Shared = global::TUnit.Core.SharedType.Keyed,Key = "🔑",}, new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/ClassTupleDataSourceDrivenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ClassTupleDataSourceDrivenTests.Test.verified.txt index 888f0ad98e..89dc171c3a 100644 --- a/TUnit.Core.SourceGenerator.Tests/ClassTupleDataSourceDrivenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ClassTupleDataSourceDrivenTests.Test.verified.txt @@ -26,8 +26,6 @@ internal sealed class ClassTupleDataSourceDrivenTests_DataSource_TupleMethod_Tes AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("TupleMethod"), - new global::TUnit.Core.MethodDataSourceAttribute("NamedTupleMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.MethodDataSourceAttribute("TupleMethod"), new global::TUnit.Core.MethodDataSourceAttribute("NamedTupleMethod") diff --git a/TUnit.Core.SourceGenerator.Tests/ConstantArgumentsTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ConstantArgumentsTests.Test.verified.txt index b65fd08ba1..c1003259b8 100644 --- a/TUnit.Core.SourceGenerator.Tests/ConstantArgumentsTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ConstantArgumentsTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class ConstantArgumentsTests_String1_TestSource_GUID : global::T AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("123"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -128,7 +127,6 @@ internal sealed class ConstantArgumentsTests_Int_TestSource_GUID : global::TUnit AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(123), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -240,7 +238,6 @@ internal sealed class ConstantArgumentsTests_Double_TestSource_GUID : global::TU AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1.23d), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -352,7 +349,6 @@ internal sealed class ConstantArgumentsTests_Float_TestSource_GUID : global::TUn AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1.23000002f), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -464,7 +460,6 @@ internal sealed class ConstantArgumentsTests_Long_TestSource_GUID : global::TUni AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(123L), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -576,7 +571,6 @@ internal sealed class ConstantArgumentsTests_UInt_TestSource_GUID : global::TUni AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(123U), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -688,7 +682,6 @@ internal sealed class ConstantArgumentsTests_ULong_TestSource_GUID : global::TUn AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(123UL), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/ConstantInBaseClassTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ConstantInBaseClassTests.Test.verified.txt index 470c136172..ef3e725cf2 100644 --- a/TUnit.Core.SourceGenerator.Tests/ConstantInBaseClassTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ConstantInBaseClassTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class ConstantInBaseClassTests_SomeTest_TestSource_GUID : global AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("Value"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/ConstantsInInterpolatedStringsTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ConstantsInInterpolatedStringsTests.Test.verified.txt index e75ddb5b67..d41d2a0f8f 100644 --- a/TUnit.Core.SourceGenerator.Tests/ConstantsInInterpolatedStringsTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ConstantsInInterpolatedStringsTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class ConstantsInInterpolatedStringsTests_SomeTest_TestSource_GU AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute($"{"Value"}1"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/CustomDisplayNameTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/CustomDisplayNameTests.Test.verified.txt index bcab9a30f4..19c4536dd1 100644 --- a/TUnit.Core.SourceGenerator.Tests/CustomDisplayNameTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/CustomDisplayNameTests.Test.verified.txt @@ -214,8 +214,6 @@ internal sealed class CustomDisplayNameTests_Test3_TestSource_GUID : global::TUn AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("foo", 1, true), - new global::TUnit.Core.ArgumentsAttribute("bar", 2, false), new global::TUnit.Core.DisplayNameAttribute("Test with: $value1 $value2 $value3!"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], @@ -356,7 +354,6 @@ internal sealed class CustomDisplayNameTests_MethodDataSourceTest_TestSource_GUI AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("Method"), new global::TUnit.Core.DisplayNameAttribute("Test using MethodDataSource"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], @@ -494,9 +491,6 @@ internal sealed class CustomDisplayNameTests_TestParameterNamePrefixBug_TestSour [ new global::TUnit.Core.TestAttribute(), new global::TUnit.Core.DisplayNameAttribute("Test this($someValue, $someValueType)"), - new global::TUnit.Core.ArgumentsAttribute(100, "Type1"), - new global::TUnit.Core.ArgumentsAttribute(200, "Type2"), - new global::TUnit.Core.ArgumentsAttribute(300, "Type1"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -630,7 +624,6 @@ internal sealed class CustomDisplayNameTests_PasswordTest_TestSource_GUID : glob AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.TestProject.CustomDisplayNameTests.MyGenerator(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/DataDrivenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/DataDrivenTests.Test.verified.txt index 72998c2175..bd6694251a 100644 --- a/TUnit.Core.SourceGenerator.Tests/DataDrivenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/DataDrivenTests.Test.verified.txt @@ -16,9 +16,6 @@ internal sealed class DataDrivenTests_DataSource_Method_TestSource_GUID : global AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), - new global::TUnit.Core.ArgumentsAttribute(2), - new global::TUnit.Core.ArgumentsAttribute(3), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -134,9 +131,6 @@ internal sealed class DataDrivenTests_DataSource_Method_TestSource_GUID : global AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1, "String"), - new global::TUnit.Core.ArgumentsAttribute(2, "String2"), - new global::TUnit.Core.ArgumentsAttribute(3, "String3"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -259,9 +253,6 @@ internal sealed class DataDrivenTests_EnumValue_TestSource_GUID : global::TUnit. AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.TestEnum.One), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.TestEnum.Two), - new global::TUnit.Core.ArgumentsAttribute(-1), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -377,7 +368,6 @@ internal sealed class DataDrivenTests_NullValue_TestSource_GUID : global::TUnit. AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(null), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -491,7 +481,6 @@ internal sealed class DataDrivenTests_EmptyString_TestSource_GUID : global::TUni AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(""), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -605,7 +594,6 @@ internal sealed class DataDrivenTests_NonEmptyString_TestSource_GUID : global::T AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("Foo bar!"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -719,9 +707,6 @@ internal sealed class DataDrivenTests_BooleanString_TestSource_GUID : global::TU AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(null), - new global::TUnit.Core.ArgumentsAttribute(false), - new global::TUnit.Core.ArgumentsAttribute(true), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -837,7 +822,6 @@ internal sealed class DataDrivenTests_Type_TestSource_GUID : global::TUnit.Core. AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(typeof(object)), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -951,7 +935,6 @@ internal sealed class DataDrivenTests_IntegerArray_TestSource_GUID : global::TUn AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(new[] { 1, 2, 3 }), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -1065,7 +1048,6 @@ internal sealed class DataDrivenTests_IntMaxValue_TestSource_GUID : global::TUni AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(2147483647), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/DataSourceClassCombinedWithDataSourceMethodTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/DataSourceClassCombinedWithDataSourceMethodTests.Test.verified.txt index d186d12d00..f03636f42b 100644 --- a/TUnit.Core.SourceGenerator.Tests/DataSourceClassCombinedWithDataSourceMethodTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/DataSourceClassCombinedWithDataSourceMethodTests.Test.verified.txt @@ -16,9 +16,6 @@ internal sealed class DataSourceClassCombinedWithDataSourceMethod_DataSourceClas AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute(typeof(global::TUnit.TestProject.CommonTestData), "One"), - new global::TUnit.Core.MethodDataSourceAttribute(typeof(global::TUnit.TestProject.CommonTestData), "Two"), - new global::TUnit.Core.MethodDataSourceAttribute(typeof(global::TUnit.TestProject.CommonTestData), "Three"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.MethodDataSourceAttribute(typeof(global::TUnit.TestProject.CommonTestData), "One"), new global::TUnit.Core.MethodDataSourceAttribute(typeof(global::TUnit.TestProject.CommonTestData), "Two"), diff --git a/TUnit.Core.SourceGenerator.Tests/DataSourceGeneratorTests.Typed.verified.txt b/TUnit.Core.SourceGenerator.Tests/DataSourceGeneratorTests.Typed.verified.txt index 67e98e7342..faafce358f 100644 --- a/TUnit.Core.SourceGenerator.Tests/DataSourceGeneratorTests.Typed.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/DataSourceGeneratorTests.Typed.verified.txt @@ -16,7 +16,6 @@ internal sealed class DataSourceGeneratorTests_GeneratedData_Method_TestSource_G AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.TestProject.Attributes.AutoFixtureGeneratorAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.TestProject.Attributes.AutoFixtureGeneratorAttribute(), new global::TUnit.TestProject.Attributes.AutoFixtureGeneratorAttribute() @@ -162,7 +161,6 @@ internal sealed class DataSourceGeneratorTests_GeneratedData_Method2_TestSource_ AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.TestProject.Attributes.AutoFixtureGeneratorAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.TestProject.Attributes.AutoFixtureGeneratorAttribute(), new global::TUnit.TestProject.Attributes.AutoFixtureGeneratorAttribute() @@ -322,7 +320,6 @@ internal sealed class DataSourceGeneratorTests_GeneratedData_Method3_TestSource_ AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.TestProject.Attributes.AutoFixtureGeneratorAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.TestProject.Attributes.AutoFixtureGeneratorAttribute(), new global::TUnit.TestProject.Attributes.AutoFixtureGeneratorAttribute() diff --git a/TUnit.Core.SourceGenerator.Tests/DataSourceGeneratorTests.Untyped.verified.txt b/TUnit.Core.SourceGenerator.Tests/DataSourceGeneratorTests.Untyped.verified.txt index f385bb3eb4..cf5c8366db 100644 --- a/TUnit.Core.SourceGenerator.Tests/DataSourceGeneratorTests.Untyped.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/DataSourceGeneratorTests.Untyped.verified.txt @@ -15,7 +15,6 @@ internal sealed class AutoDataTests_Test1_TestSource_GUID : global::TUnit.Core.I Dependencies = global::System.Array.Empty(), AttributeFactory = () => [ - new global::TUnit.TestProject.Attributes.AutoDataAttribute(), new global::TUnit.Core.TestAttribute() ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/EnumMemberNamesTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/EnumMemberNamesTests.Test.verified.txt index ad9794da47..4f9613f40a 100644 --- a/TUnit.Core.SourceGenerator.Tests/EnumMemberNamesTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/EnumMemberNamesTests.Test.verified.txt @@ -16,9 +16,6 @@ internal sealed class EnumMemberNamesTests_SomeTest_TestSource_GUID : global::TU AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("A"), - new global::TUnit.Core.ArgumentsAttribute("B"), - new global::TUnit.Core.ArgumentsAttribute("C"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/EnumerableDataSourceDrivenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/EnumerableDataSourceDrivenTests.Test.verified.txt index 8311bdc7d0..ae37999ebb 100644 --- a/TUnit.Core.SourceGenerator.Tests/EnumerableDataSourceDrivenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/EnumerableDataSourceDrivenTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class EnumerableDataSourceDrivenTests_DataSource_Method_TestSour AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -149,7 +148,6 @@ internal sealed class EnumerableDataSourceDrivenTests_DataSource_Method2_TestSou AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -282,7 +280,6 @@ internal sealed class EnumerableDataSourceDrivenTests_DataSource_WithBaseReturn_ AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("MethodWithBaseReturn"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/EnumerableTupleDataSourceDrivenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/EnumerableTupleDataSourceDrivenTests.Test.verified.txt index 2d06b8ce27..0884280fd2 100644 --- a/TUnit.Core.SourceGenerator.Tests/EnumerableTupleDataSourceDrivenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/EnumerableTupleDataSourceDrivenTests.Test.verified.txt @@ -16,8 +16,6 @@ internal sealed class EnumerableTupleDataSourceDrivenTests_DataSource_TupleMetho AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("TupleMethod"), - new global::TUnit.Core.MethodDataSourceAttribute("NamedTupleMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/ExpectedArgumentTypeTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/ExpectedArgumentTypeTests.Test.verified.txt index c79c5355f6..74085b70e9 100644 --- a/TUnit.Core.SourceGenerator.Tests/ExpectedArgumentTypeTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/ExpectedArgumentTypeTests.Test.verified.txt @@ -16,19 +16,6 @@ internal sealed class ExpectedArgumentTypeTests_TypedArguments_TestSource_GUID : AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(0d, typeof(double)), - new global::TUnit.Core.ArgumentsAttribute(0f, typeof(float)), - new global::TUnit.Core.ArgumentsAttribute((sbyte)0, typeof(sbyte)), - new global::TUnit.Core.ArgumentsAttribute((byte)0, typeof(byte)), - new global::TUnit.Core.ArgumentsAttribute((short)0, typeof(short)), - new global::TUnit.Core.ArgumentsAttribute((ushort)0, typeof(ushort)), - new global::TUnit.Core.ArgumentsAttribute(0, typeof(int)), - new global::TUnit.Core.ArgumentsAttribute((uint)0, typeof(uint)), - new global::TUnit.Core.ArgumentsAttribute(0u, typeof(uint)), - new global::TUnit.Core.ArgumentsAttribute((long)0, typeof(long)), - new global::TUnit.Core.ArgumentsAttribute(0L, typeof(long)), - new global::TUnit.Core.ArgumentsAttribute((ulong)0, typeof(ulong)), - new global::TUnit.Core.ArgumentsAttribute(0UL, typeof(ulong)), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -159,14 +146,6 @@ internal sealed class ExpectedArgumentTypeTests_EnumTypes_TestSource_GUID : glob AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.ByteEnum.Default, typeof(global::TUnit.TestProject.ByteEnum), typeof(byte)), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.SByteEnum.Default, typeof(global::TUnit.TestProject.SByteEnum), typeof(sbyte)), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.Int16Enum.Default, typeof(global::TUnit.TestProject.Int16Enum), typeof(short)), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.UInt16Enum.Default, typeof(global::TUnit.TestProject.UInt16Enum), typeof(ushort)), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.Int32Enum.Default, typeof(global::TUnit.TestProject.Int32Enum), typeof(int)), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.UInt32Enum.Default, typeof(global::TUnit.TestProject.UInt32Enum), typeof(uint)), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.Int64Enum.Default, typeof(global::TUnit.TestProject.Int64Enum), typeof(long)), - new global::TUnit.Core.ArgumentsAttribute(global::TUnit.TestProject.UInt64Enum.Default, typeof(global::TUnit.TestProject.UInt64Enum), typeof(ulong)), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/InheritedTestsFromDifferentProjectTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/InheritedTestsFromDifferentProjectTests.Test.verified.txt index 7fd4323872..464767efce 100644 --- a/TUnit.Core.SourceGenerator.Tests/InheritedTestsFromDifferentProjectTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/InheritedTestsFromDifferentProjectTests.Test.verified.txt @@ -105,7 +105,6 @@ internal sealed class InheritedTestsFromDifferentProjectTests_GenericMethodDataS AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("Foo"), new global::TUnit.TestProject.Attributes.EngineTest(Pass), new global::TUnit.Core.InheritsTestsAttribute(), new global::TUnit.Core.CategoryAttribute("BaseCategoriesOnClass") @@ -221,7 +220,6 @@ internal sealed class InheritedTestsFromDifferentProjectTests_NonGenericMethodDa AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute(typeof(global::TUnit.TestProject.TestData), "Foo"), new global::TUnit.TestProject.Attributes.EngineTest(Pass), new global::TUnit.Core.InheritsTestsAttribute(), new global::TUnit.Core.CategoryAttribute("BaseCategoriesOnClass") @@ -705,7 +703,6 @@ internal sealed class InheritedTestsFromDifferentProjectTests_GenericMethodDataS AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("Foo"), new global::TUnit.TestProject.Attributes.EngineTest(Pass), new global::TUnit.Core.InheritsTestsAttribute(), new global::TUnit.Core.CategoryAttribute("BaseCategoriesOnClass") @@ -821,7 +818,6 @@ internal sealed class InheritedTestsFromDifferentProjectTests_NonGenericMethodDa AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute(typeof(global::TUnit.TestProject.TestData), "Foo"), new global::TUnit.TestProject.Attributes.EngineTest(Pass), new global::TUnit.Core.InheritsTestsAttribute(), new global::TUnit.Core.CategoryAttribute("BaseCategoriesOnClass") diff --git a/TUnit.Core.SourceGenerator.Tests/InheritsTestsTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/InheritsTestsTests.Test.verified.txt index f8eb279c21..8e30925753 100644 --- a/TUnit.Core.SourceGenerator.Tests/InheritsTestsTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/InheritsTestsTests.Test.verified.txt @@ -20,9 +20,6 @@ internal sealed class BaseClass_Test_TestSource_GUID : global::TUnit.Core.Interf AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), - new global::TUnit.Core.ArgumentsAttribute(2), - new global::TUnit.Core.ArgumentsAttribute(3), new global::TUnit.Core.RepeatAttribute(10), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], @@ -183,9 +180,6 @@ internal sealed class Tests_Test_TestSource_GUID : global::TUnit.Core.Interfaces AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), - new global::TUnit.Core.ArgumentsAttribute(2), - new global::TUnit.Core.ArgumentsAttribute(3), new global::TUnit.Core.RepeatAttribute(10), new global::TUnit.Core.InheritsTestsAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) @@ -334,9 +328,6 @@ internal sealed class Tests2_Test_TestSource_GUID : global::TUnit.Core.Interface AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), - new global::TUnit.Core.ArgumentsAttribute(2), - new global::TUnit.Core.ArgumentsAttribute(3), new global::TUnit.Core.RepeatAttribute(10), new global::TUnit.Core.InheritsTestsAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) @@ -485,9 +476,6 @@ internal sealed class Tests3_Test_TestSource_GUID : global::TUnit.Core.Interface AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), - new global::TUnit.Core.ArgumentsAttribute(2), - new global::TUnit.Core.ArgumentsAttribute(3), new global::TUnit.Core.RepeatAttribute(10), new global::TUnit.Core.InheritsTestsAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) diff --git a/TUnit.Core.SourceGenerator.Tests/MatrixTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/MatrixTests.Test.verified.txt index 1d219f9047..2d9962b5a1 100644 --- a/TUnit.Core.SourceGenerator.Tests/MatrixTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/MatrixTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class MatrixTests_MatrixTest_One_TestSource_GUID : global::TUnit AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -142,7 +141,6 @@ internal sealed class MatrixTests_MatrixTest_Two_TestSource_GUID : global::TUnit AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -275,7 +273,6 @@ internal sealed class MatrixTests_MatrixTest_Enum_TestSource_GUID : global::TUni AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -401,7 +398,6 @@ internal sealed class MatrixTests_AutoGenerateBools_TestSource_GUID : global::TU AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -520,7 +516,6 @@ internal sealed class MatrixTests_AutoGenerateBools2_TestSource_GUID : global::T AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -639,7 +634,6 @@ internal sealed class MatrixTests_ImplicitConversion_TestSource_GUID : global::T AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -758,7 +752,6 @@ internal sealed class MatrixTests_ExcludingAutoGeneratedMatrixValues_TestSource_ AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -877,7 +870,6 @@ internal sealed class MatrixTests_Method1_TestSource_GUID : global::TUnit.Core.I AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -989,7 +981,6 @@ internal sealed class MatrixTests_Method2_TestSource_GUID : global::TUnit.Core.I AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -1101,7 +1092,6 @@ internal sealed class MatrixTests_Method3_TestSource_GUID : global::TUnit.Core.I AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -1213,7 +1203,6 @@ internal sealed class MatrixTests_Method4_TestSource_GUID : global::TUnit.Core.I AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -1325,7 +1314,6 @@ internal sealed class MatrixTests_Exclusion_TestSource_GUID : global::TUnit.Core AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.Core.MatrixExclusionAttribute(1, 1), new global::TUnit.Core.MatrixExclusionAttribute(2, 2), new global::TUnit.Core.MatrixExclusionAttribute(3, 3), diff --git a/TUnit.Core.SourceGenerator.Tests/MethodDataSourceDrivenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/MethodDataSourceDrivenTests.Test.verified.txt index e0a2af45d6..0a2f909478 100644 --- a/TUnit.Core.SourceGenerator.Tests/MethodDataSourceDrivenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/MethodDataSourceDrivenTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class MethodDataSourceDrivenTests_DataSource_Method_TestSource_G AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -141,7 +140,6 @@ internal sealed class MethodDataSourceDrivenTests_DataSource_Method2_TestSource_ AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -266,7 +264,6 @@ internal sealed class MethodDataSourceDrivenTests_DataSource_Method_WithAction_T AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("SomeAction"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -391,10 +388,6 @@ internal sealed class MethodDataSourceDrivenTests_DataSource_Method3_TestSource_ AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod") -{Arguments = new object[]{5},}, - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod") -{Arguments = new object[] { 5 },}, new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -534,14 +527,6 @@ internal sealed class MethodDataSourceDrivenTests_DataSource_Method4_TestSource_ AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod") -{Arguments = new object[]{"Hello World!",5,true},}, - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod") -{Arguments = new object[] { "Hello World!", 6, true },}, - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod") -{Arguments = new object[]{"Hello World!",7,true},}, - new global::TUnit.Core.MethodDataSourceAttribute("SomeMethod") -{Arguments = new object[] { "Hello World!", 8, true },}, new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -708,7 +693,6 @@ internal sealed class MethodDataSourceDrivenTests_DataSource_WithBaseReturn_Test AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("MethodWithBaseReturn"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -833,7 +817,6 @@ internal sealed class MethodDataSourceDrivenTests_EnumerableFuncArrayTest_TestSo AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("EnumerableFuncArrayTestData"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/MethodDataSourceDrivenWithCancellationTokenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/MethodDataSourceDrivenWithCancellationTokenTests.Test.verified.txt index 9f7c5ed9c2..89d8a5cbd9 100644 --- a/TUnit.Core.SourceGenerator.Tests/MethodDataSourceDrivenWithCancellationTokenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/MethodDataSourceDrivenWithCancellationTokenTests.Test.verified.txt @@ -16,12 +16,6 @@ internal sealed class MethodDataSourceDrivenWithCancellationTokenTests_MyTest_Te AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("T"), - new global::TUnit.Core.MethodDataSourceAttribute("FuncT"), - new global::TUnit.Core.MethodDataSourceAttribute("EnumerableT"), - new global::TUnit.Core.MethodDataSourceAttribute("EnumerableFuncT"), - new global::TUnit.Core.MethodDataSourceAttribute("ArrayT"), - new global::TUnit.Core.MethodDataSourceAttribute("ArrayFuncT"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute("Usage", "TUnit0046:Return a `Func` rather than a ``") ], diff --git a/TUnit.Core.SourceGenerator.Tests/NameOfArgumentTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/NameOfArgumentTests.Test.verified.txt index b9f086e558..9e6c152647 100644 --- a/TUnit.Core.SourceGenerator.Tests/NameOfArgumentTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/NameOfArgumentTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class NameOfArgumentTests_TestName_TestSource_GUID : global::TUn AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("TestName"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/NullableByteArgumentTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/NullableByteArgumentTests.Test.verified.txt index 0d26317868..9378d83854 100644 --- a/TUnit.Core.SourceGenerator.Tests/NullableByteArgumentTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/NullableByteArgumentTests.Test.verified.txt @@ -16,8 +16,6 @@ internal sealed class NullableByteArgumentTests_Test_TestSource_GUID : global::T AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute((byte) 1), - new global::TUnit.Core.ArgumentsAttribute(null), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -132,8 +130,6 @@ internal sealed class NullableByteArgumentTests_Test2_TestSource_GUID : global:: AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute((byte) 1, (byte) 1), - new global::TUnit.Core.ArgumentsAttribute((byte) 1, null), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.Test.verified.txt index 14507d190b..d0e118c78a 100644 --- a/TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class NumberArgumentTests_Int_TestSource_GUID : global::TUnit.Co AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -130,7 +129,6 @@ internal sealed class NumberArgumentTests_Double_TestSource_GUID : global::TUnit AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1.1), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -244,7 +242,6 @@ internal sealed class NumberArgumentTests_Float_TestSource_GUID : global::TUnit. AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1.1f), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -358,7 +355,6 @@ internal sealed class NumberArgumentTests_Long_TestSource_GUID : global::TUnit.C AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1L), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -472,7 +468,6 @@ internal sealed class NumberArgumentTests_ULong_TestSource_GUID : global::TUnit. AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1UL), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -586,7 +581,6 @@ internal sealed class NumberArgumentTests_UInt_TestSource_GUID : global::TUnit.C AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1U), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.TestDE.verified.txt b/TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.TestDE.verified.txt index 14507d190b..d0e118c78a 100644 --- a/TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.TestDE.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.TestDE.verified.txt @@ -16,7 +16,6 @@ internal sealed class NumberArgumentTests_Int_TestSource_GUID : global::TUnit.Co AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -130,7 +129,6 @@ internal sealed class NumberArgumentTests_Double_TestSource_GUID : global::TUnit AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1.1), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -244,7 +242,6 @@ internal sealed class NumberArgumentTests_Float_TestSource_GUID : global::TUnit. AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1.1f), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -358,7 +355,6 @@ internal sealed class NumberArgumentTests_Long_TestSource_GUID : global::TUnit.C AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1L), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -472,7 +468,6 @@ internal sealed class NumberArgumentTests_ULong_TestSource_GUID : global::TUnit. AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1UL), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -586,7 +581,6 @@ internal sealed class NumberArgumentTests_UInt_TestSource_GUID : global::TUnit.C AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1U), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/StringArgumentTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/StringArgumentTests.Test.verified.txt index c7e94f8b6f..b2ec37bb85 100644 --- a/TUnit.Core.SourceGenerator.Tests/StringArgumentTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/StringArgumentTests.Test.verified.txt @@ -16,18 +16,6 @@ internal sealed class StringArgumentTests_Normal_TestSource_GUID : global::TUnit AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(""), - new global::TUnit.Core.ArgumentsAttribute(@"\"), - new global::TUnit.Core.ArgumentsAttribute(@"\t"), - new global::TUnit.Core.ArgumentsAttribute("\t"), - new global::TUnit.Core.ArgumentsAttribute("\\t"), - new global::TUnit.Core.ArgumentsAttribute("\\\t"), - new global::TUnit.Core.ArgumentsAttribute("\\\\t"), - new global::TUnit.Core.ArgumentsAttribute( """ - Hello - World - """ -), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -152,14 +140,6 @@ internal sealed class StringArgumentTests_Nullable_TestSource_GUID : global::TUn AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(""), - new global::TUnit.Core.ArgumentsAttribute(@"\"), - new global::TUnit.Core.ArgumentsAttribute(@"\t"), - new global::TUnit.Core.ArgumentsAttribute("\t"), - new global::TUnit.Core.ArgumentsAttribute("\\t"), - new global::TUnit.Core.ArgumentsAttribute("\\\t"), - new global::TUnit.Core.ArgumentsAttribute("\\\\t"), - new global::TUnit.Core.ArgumentsAttribute(null), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/Tests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests.Test.verified.txt index 469f153f46..38860630b1 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests.Test.verified.txt @@ -16,11 +16,6 @@ internal sealed class Tests_TryParse_InvalidString_ReturnsFailure_TestSource_GUI AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("\"2c48c152-7cb7-4f51-8f01-704454f36e60\""), - new global::TUnit.Core.ArgumentsAttribute("invalidNotAGui"), - new global::TUnit.Core.ArgumentsAttribute(""), - new global::TUnit.Core.ArgumentsAttribute(" "), - new global::TUnit.Core.ArgumentsAttribute(null), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -145,11 +140,6 @@ internal sealed class Tests_Parse_InvalidString_ThrowsException_TestSource_GUID AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("\"2c48c152-7cb7-4f51-8f01-704454f36e60\""), - new global::TUnit.Core.ArgumentsAttribute("invalidNotAGui"), - new global::TUnit.Core.ArgumentsAttribute(""), - new global::TUnit.Core.ArgumentsAttribute(" "), - new global::TUnit.Core.ArgumentsAttribute(null), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -265,8 +255,6 @@ internal sealed class Tests_TryParse_ValidString_ReturnsAccountId_TestSource_GUI AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute("2c48c152-7cb7-4f51-8f01-704454f36e60"), - new global::TUnit.Core.ArgumentsAttribute("00000000-0000-0000-0000-000000000000"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/Tests1538.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests1538.Test.verified.txt index 0dec4e8656..3783d4bb34 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests1538.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests1538.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class Tests_Eight_Args_TestSource_GUID : global::TUnit.Core.Inte AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("EightItems"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -200,7 +199,6 @@ internal sealed class Tests_SixteenArgs_TestSource_GUID : global::TUnit.Core.Int AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("SixteenItems"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/Tests1603.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests1603.Test.verified.txt index fbe83f4b20..14ed292e06 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests1603.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests1603.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class Tests_Casted_Integer_To_Short_Converts_TestSource_GUID : g AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute((short) -123), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -128,7 +127,6 @@ internal sealed class Tests_Integer_To_Short_Converts_TestSource_GUID : global:: AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(-123), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/Tests1692.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests1692.Test.verified.txt index a6b96c2f2a..8e90c3aaec 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests1692.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests1692.Test.verified.txt @@ -16,8 +16,6 @@ internal sealed class Tests_NullTest_TestSource_GUID : global::TUnit.Core.Interf AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(null), - new global::TUnit.Core.ArgumentsAttribute(null), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/Tests1821.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests1821.Test.verified.txt index cb204a3bdd..cc648fd9b3 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests1821.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests1821.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class Tests_MethodDataSource_TestSource_GUID : global::TUnit.Cor AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.InstanceMethodDataSourceAttribute("DataSource"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.ClassDataSourceAttribute() ], @@ -144,7 +143,6 @@ internal sealed class Tests_MatrixDataSource_TestSource_GUID : global::TUnit.Cor AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.ClassDataSourceAttribute() ], diff --git a/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.DotNet8_0.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.DotNet8_0.verified.txt index 8ec4749fbf..b0bd08ba83 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.DotNet8_0.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.DotNet8_0.verified.txt @@ -104,7 +104,6 @@ internal sealed class DerivedTest_Test2_TestSource_GUID : global::TUnit.Core.Int AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.InheritsTestsAttribute() ], @@ -219,8 +218,6 @@ internal sealed class DerivedTest_Test3_TestSource_GUID : global::TUnit.Core.Int AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(false), - new global::TUnit.Core.ArgumentsAttribute(true), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.InheritsTestsAttribute() ], diff --git a/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.DotNet9_0.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.DotNet9_0.verified.txt index 8ec4749fbf..b0bd08ba83 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.DotNet9_0.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.DotNet9_0.verified.txt @@ -104,7 +104,6 @@ internal sealed class DerivedTest_Test2_TestSource_GUID : global::TUnit.Core.Int AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.InheritsTestsAttribute() ], @@ -219,8 +218,6 @@ internal sealed class DerivedTest_Test3_TestSource_GUID : global::TUnit.Core.Int AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(false), - new global::TUnit.Core.ArgumentsAttribute(true), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.InheritsTestsAttribute() ], diff --git a/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.Net4_7.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.Net4_7.verified.txt index 3675e2a7e4..98f643b6e5 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.Net4_7.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests1889.Test.Net4_7.verified.txt @@ -104,7 +104,6 @@ internal sealed class DerivedTest_Test2_TestSource_GUID : global::TUnit.Core.Int AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.InheritsTestsAttribute() ], @@ -219,8 +218,6 @@ internal sealed class DerivedTest_Test3_TestSource_GUID : global::TUnit.Core.Int AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(false), - new global::TUnit.Core.ArgumentsAttribute(true), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), new global::TUnit.Core.InheritsTestsAttribute() ], diff --git a/TUnit.Core.SourceGenerator.Tests/Tests2083.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests2083.Test.verified.txt index fb37dd48b4..367b570fff 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests2083.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests2083.Test.verified.txt @@ -16,12 +16,6 @@ internal sealed class Tests_MyTest_TestSource_GUID : global::TUnit.Core.Interfac AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(0), - new global::TUnit.Core.ArgumentsAttribute((byte)255), - new global::TUnit.Core.ArgumentsAttribute((short)32767), - new global::TUnit.Core.ArgumentsAttribute('\uffff'), - new global::TUnit.Core.ArgumentsAttribute(2147483647), - new global::TUnit.Core.ArgumentsAttribute(9223372036854775807L), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/Tests2085.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests2085.Test.verified.txt index efd32c836e..4945406a04 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests2085.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests2085.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class Tests_Double_SpecialConsts_TestSource_GUID : global::TUnit AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -128,7 +127,6 @@ internal sealed class Tests_Float_SpecialConsts_TestSource_GUID : global::TUnit. AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/Tests2112.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/Tests2112.Test.verified.txt index d13078efaa..c863aae48f 100644 --- a/TUnit.Core.SourceGenerator.Tests/Tests2112.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/Tests2112.Test.verified.txt @@ -16,8 +16,6 @@ internal sealed class Tests_Test_TestSource_GUID : global::TUnit.Core.Interfaces AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(0, 1L), - new global::TUnit.Core.ArgumentsAttribute(0, 1L), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] @@ -175,8 +173,6 @@ internal sealed class Tests_Test2_TestSource_GUID : global::TUnit.Core.Interface AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(0, 1L, 2L, 3L), - new global::TUnit.Core.ArgumentsAttribute(0, 1L, 2L, 3L), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/TimeoutCancellationTokenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/TimeoutCancellationTokenTests.Test.verified.txt index 256426fce0..35aab20568 100644 --- a/TUnit.Core.SourceGenerator.Tests/TimeoutCancellationTokenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/TimeoutCancellationTokenTests.Test.verified.txt @@ -418,7 +418,6 @@ internal sealed class TimeoutCancellationTokenTests_DataTest_TestSource_GUID : g AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1), new global::TUnit.Core.TimeoutAttribute(5_000), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Failure), new global::TUnit.Core.MethodDataSourceAttribute("DataSource"), @@ -577,7 +576,6 @@ internal sealed class TimeoutCancellationTokenTests_DataSourceTest_TestSource_GU Dependencies = global::System.Array.Empty(), AttributeFactory = () => [ - new global::TUnit.Core.MethodDataSourceAttribute("DataSource"), new global::TUnit.Core.TimeoutAttribute(5_000), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Failure), new global::TUnit.Core.TestAttribute(), @@ -759,7 +757,6 @@ internal sealed class TimeoutCancellationTokenTests_MatrixTest_TestSource_GUID : AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MatrixDataSourceAttribute(), new global::TUnit.Core.TimeoutAttribute(5_000), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Failure), new global::TUnit.Core.CategoryAttribute("Blah"), diff --git a/TUnit.Core.SourceGenerator.Tests/TupleDataSourceDrivenTests.Test.verified.txt b/TUnit.Core.SourceGenerator.Tests/TupleDataSourceDrivenTests.Test.verified.txt index 34a2d34b28..5d7f6925e1 100644 --- a/TUnit.Core.SourceGenerator.Tests/TupleDataSourceDrivenTests.Test.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/TupleDataSourceDrivenTests.Test.verified.txt @@ -16,7 +16,6 @@ internal sealed class TupleDataSourceDrivenTests_DataSource_TupleMethod_TestSour AttributeFactory = () => [ new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.MethodDataSourceAttribute("TupleMethod"), new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass) ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] diff --git a/TUnit.Core.SourceGenerator.Tests/UnifiedReflectionFreeTests.Test_AotSafeDataSourceFactories.verified.txt b/TUnit.Core.SourceGenerator.Tests/UnifiedReflectionFreeTests.Test_AotSafeDataSourceFactories.verified.txt index a056ee3ff7..19c576e293 100644 --- a/TUnit.Core.SourceGenerator.Tests/UnifiedReflectionFreeTests.Test_AotSafeDataSourceFactories.verified.txt +++ b/TUnit.Core.SourceGenerator.Tests/UnifiedReflectionFreeTests.Test_AotSafeDataSourceFactories.verified.txt @@ -15,9 +15,7 @@ internal sealed class AotDataSourceTest_TestWithDataSource_TestSource_GUID : glo Dependencies = global::System.Array.Empty(), AttributeFactory = () => [ - new global::TUnit.Core.TestAttribute(), - new global::TUnit.Core.ArgumentsAttribute(1, 2, 3), - new global::TUnit.Core.ArgumentsAttribute(4, 5, 6) + new global::TUnit.Core.TestAttribute() ], DataSources = new global::TUnit.Core.IDataSourceAttribute[] { diff --git a/TUnit.Core.SourceGenerator/Generators/TestMetadataGenerator.cs b/TUnit.Core.SourceGenerator/Generators/TestMetadataGenerator.cs index 4a5b9f9415..178dc8bcd8 100644 --- a/TUnit.Core.SourceGenerator/Generators/TestMetadataGenerator.cs +++ b/TUnit.Core.SourceGenerator/Generators/TestMetadataGenerator.cs @@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; +using TUnit.Core.SourceGenerator.CodeGenerators.Formatting; using TUnit.Core.SourceGenerator.CodeGenerators.Helpers; using TUnit.Core.SourceGenerator.CodeGenerators.Writers; using TUnit.Core.SourceGenerator.Extensions; @@ -519,6 +520,7 @@ private static void GenerateMetadata(CodeWriter writer, Compilation compilation, writer.Indent(); var attributes = methodSymbol.GetAttributes() + .Where(a => !DataSourceAttributeHelper.IsDataSourceAttribute(a.AttributeClass)) .Concat(testMethod.TypeSymbol.GetAttributesIncludingBaseTypes()) .Concat(testMethod.TypeSymbol.ContainingAssembly.GetAttributes()) .ToImmutableArray(); @@ -661,6 +663,19 @@ private static void GenerateDataSourceAttribute(CodeWriter writer, Compilation c { GenerateMethodDataSourceAttribute(writer, attr, methodSymbol, typeSymbol); } + else if (attrName == "global::TUnit.Core.ArgumentsAttribute") + { + try + { + GenerateArgumentsAttributeWithParameterTypes(writer, compilation, attr, methodSymbol); + } + catch + { + // Fall back to default behavior if parameter type matching fails + AttributeWriter.WriteAttribute(writer, compilation, attr); + writer.AppendLine(","); + } + } else { AttributeWriter.WriteAttribute(writer, compilation, attr); @@ -668,6 +683,128 @@ private static void GenerateDataSourceAttribute(CodeWriter writer, Compilation c } } + private static void GenerateArgumentsAttributeWithParameterTypes(CodeWriter writer, Compilation compilation, AttributeData attr, IMethodSymbol methodSymbol) + { + if (attr.AttributeClass == null) + { + return; + } + + var attrTypeName = attr.AttributeClass.GloballyQualified(); + var testMethodParameters = methodSymbol.Parameters; + + // Get the attribute syntax to access source text (preserves precision for decimals) + var attributeSyntax = attr.ApplicationSyntaxReference?.GetSyntax() as AttributeSyntax; + if (attributeSyntax == null) + { + // No syntax available - fall back to TypedConstant-based formatting + var formatter = new TypedConstantFormatter(); + writer.Append($"new {attrTypeName}("); + + if (attr.ConstructorArguments.Length == 1 && attr.ConstructorArguments[0].Kind == TypedConstantKind.Array) + { + var arrayValues = attr.ConstructorArguments[0].Values; + for (int i = 0; i < arrayValues.Length; i++) + { + var targetType = i < testMethodParameters.Length ? testMethodParameters[i].Type : null; + writer.Append(formatter.FormatForCode(arrayValues[i], targetType)); + if (i < arrayValues.Length - 1) writer.Append(", "); + } + } + else + { + for (int i = 0; i < attr.ConstructorArguments.Length; i++) + { + var targetType = i < testMethodParameters.Length ? testMethodParameters[i].Type : null; + writer.Append(formatter.FormatForCode(attr.ConstructorArguments[i], targetType)); + if (i < attr.ConstructorArguments.Length - 1) writer.Append(", "); + } + } + + writer.AppendLine("),"); + return; + } + + // Get the argument expressions from syntax + var argumentList = attributeSyntax.ArgumentList; + if (argumentList == null || argumentList.Arguments.Count == 0) + { + writer.AppendLine($"new {attrTypeName}(),"); + return; + } + + // Get semantic model for rewriting expressions with fully qualified names + var semanticModel = compilation.GetSemanticModel(attributeSyntax.SyntaxTree); + + writer.Append($"new {attrTypeName}("); + + // Only process positional arguments (exclude named arguments) + var positionalArgs = argumentList.Arguments.Where(a => a.NameEquals == null).ToList(); + + for (int i = 0; i < positionalArgs.Count; i++) + { + var argumentSyntax = positionalArgs[i]; + var expression = argumentSyntax.Expression; + + // Get target parameter type + ITypeSymbol? targetParameterType = i < testMethodParameters.Length + ? testMethodParameters[i].Type + : null; + + // For decimal parameters, preserve source text and add 'm' suffix (only for numeric literals) + if (targetParameterType?.SpecialType == SpecialType.System_Decimal + && expression.Kind() != SyntaxKind.StringLiteralExpression + && expression.Kind() != SyntaxKind.NullLiteralExpression) + { + var sourceText = expression.ToString().TrimEnd('d', 'D', 'f', 'F', 'm', 'M').Trim(); + writer.Append($"{sourceText}m"); + } + else + { + // For other types (including strings and nulls), rewrite with fully qualified names + var fullyQualifiedExpression = expression.Accept(new FullyQualifiedWithGlobalPrefixRewriter(semanticModel))!; + writer.Append(fullyQualifiedExpression.ToFullString()); + } + + if (i < positionalArgs.Count - 1) + { + writer.Append(", "); + } + } + + writer.Append(")"); + + // Handle named arguments (like Skip property) + var namedArgs = argumentList.Arguments.Where(a => a.NameEquals != null).ToList(); + if (namedArgs.Count > 0) + { + writer.AppendLine(); + writer.AppendLine("{"); + writer.Indent(); + + for (int i = 0; i < namedArgs.Count; i++) + { + var namedArg = namedArgs[i]; + var propertyName = namedArg.NameEquals!.Name.ToString(); + var fullyQualifiedExpression = namedArg.Expression.Accept(new FullyQualifiedWithGlobalPrefixRewriter(semanticModel))!; + writer.Append($"{propertyName} = {fullyQualifiedExpression.ToFullString()}"); + + if (i < namedArgs.Count - 1) + { + writer.AppendLine(","); + } + } + + writer.AppendLine(); + writer.Unindent(); + writer.AppendLine("},"); + } + else + { + writer.AppendLine(","); + } + } + private static void GenerateMethodDataSourceAttribute(CodeWriter writer, AttributeData attr, IMethodSymbol methodSymbol, INamedTypeSymbol typeSymbol) { // Extract method name and target type diff --git a/TUnit.Core/AotCompatibility/GenericTestRegistry.cs b/TUnit.Core/AotCompatibility/GenericTestRegistry.cs index 01222ff887..0afcdd7588 100644 --- a/TUnit.Core/AotCompatibility/GenericTestRegistry.cs +++ b/TUnit.Core/AotCompatibility/GenericTestRegistry.cs @@ -121,7 +121,7 @@ public readonly bool Equals(GenericMethodKey other) TypeArrayComparer.Instance.Equals(TypeArguments, other.TypeArguments); } - public readonly override int GetHashCode() + public override readonly int GetHashCode() { #if NETSTANDARD2_0 unchecked diff --git a/TUnit.Core/AsyncConvert.cs b/TUnit.Core/AsyncConvert.cs index 1447840b3b..d793369cf3 100644 --- a/TUnit.Core/AsyncConvert.cs +++ b/TUnit.Core/AsyncConvert.cs @@ -55,6 +55,10 @@ public static async ValueTask Convert(Func action) | MethodImplOptions.AggressiveOptimization #endif )] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("ConvertObject uses reflection to handle custom awaitable types and F# async. For AOT compatibility, use Task or ValueTask directly.")] + [RequiresDynamicCode("ConvertObject may require dynamic invocation for custom awaitable types. For AOT compatibility, use Task or ValueTask directly.")] + #endif public static async ValueTask ConvertObject(object? invoke) { if (invoke is Delegate @delegate) @@ -114,16 +118,10 @@ public static async ValueTask ConvertObject(object? invoke) [System.Diagnostics.CodeAnalysis.DynamicDependency(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods, "Microsoft.FSharp.Control.FSharpAsync", "FSharp.Core")] [System.Diagnostics.CodeAnalysis.DynamicDependency("StartAsTask", "Microsoft.FSharp.Control.FSharpAsync", "FSharp.Core")] - [UnconditionalSuppressMessage("Trimming", "IL2077:Target parameter argument does not satisfy \'DynamicallyAccessedMembersAttribute\' in call to target method. The source field does not have matching annotations.", - Justification = "F# async support requires FSharp.Core types. The DynamicDependency attributes preserve required members.")] - [UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter argument does not satisfy \'DynamicallyAccessedMembersAttribute\' in call to target method. The return value of the source method does not have matching annotations.", - Justification = "F# async type resolution is preserved through DynamicDependency. For AOT, ensure FSharp.Core is properly referenced.")] - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break functionality when AOT compiling.", - Justification = "F# async interop requires MakeGenericMethod. F# tests in AOT scenarios should use Task-based APIs.")] - [UnconditionalSuppressMessage("Trimming", "IL2060:Call to \'System.Reflection.MethodInfo.MakeGenericMethod\' can not be statically analyzed. It\'s not possible to guarantee the availability of requirements of the generic method.", - Justification = "Generic method instantiation for F# async types. The type parameter comes from the F# async type itself.")] - [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", - Justification = "F# async support is optional. Tests using F# async should ensure FSharp.Core is preserved in AOT scenarios.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("F# async support requires FSharp.Core types and reflection. For AOT, use Task-based APIs.")] + [RequiresDynamicCode("F# async interop requires MakeGenericMethod. For AOT, use Task-based APIs.")] + #endif private static ValueTask StartAsFSharpTask(object invoke, Type type) { var startAsTaskOpenGenericMethod = (_fSharpAsyncType ??= type.Assembly.GetType("Microsoft.FSharp.Control.FSharpAsync"))! @@ -145,10 +143,10 @@ private static ValueTask StartAsFSharpTask(object invoke, Type type) /// /// Safely invokes F# async conversion with proper suppression for the call site. /// - [UnconditionalSuppressMessage("Trimming", "IL2026:Using member with RequiresUnreferencedCodeAttribute", - Justification = "F# async is an optional feature. AOT applications should use Task-based APIs.")] - [UnconditionalSuppressMessage("AOT", "IL3050:Using member with RequiresDynamicCodeAttribute", - Justification = "F# async requires runtime code generation. This is documented as not AOT-compatible.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("F# async is an optional feature. AOT applications should use Task-based APIs.")] + [RequiresDynamicCode("F# async requires runtime code generation. This is documented as not AOT-compatible.")] + #endif private static async ValueTask StartAsFSharpTaskSafely(object invoke, Type type) { if (IsFSharpAsyncSupported()) @@ -183,8 +181,10 @@ private static bool IsFSharpAsyncSupported() } } - [UnconditionalSuppressMessage("Trimming", "IL2075:\'this\' argument does not satisfy \'DynamicallyAccessedMembersAttribute\' in call to target method. The return value of the source method does not have matching annotations.", - Justification = "GetAwaiter pattern detection for custom awaitables. For AOT, use standard Task/ValueTask types or implement IAsyncEnumerable.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("GetAwaiter pattern detection requires reflection for custom awaitable types. For AOT, use Task/ValueTask.")] + [RequiresDynamicCode("Custom awaitable handling may require dynamic invocation. For AOT, use Task/ValueTask.")] + #endif public static bool TryGetAwaitableTask(object awaitable, [NotNullWhen(true)] out Task? task) { var getAwaiter = awaitable.GetType().GetMethod("GetAwaiter", Type.EmptyTypes); diff --git a/TUnit.Core/Attributes/Executors/CultureAttribute.cs b/TUnit.Core/Attributes/Executors/CultureAttribute.cs index f3b39c2b08..30e3706921 100644 --- a/TUnit.Core/Attributes/Executors/CultureAttribute.cs +++ b/TUnit.Core/Attributes/Executors/CultureAttribute.cs @@ -12,6 +12,9 @@ public CultureAttribute(string cultureName) : this(CultureInfo.GetCultureInfo(cu public int Order => 0; +#if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] +#endif public ValueTask OnTestRegistered(TestRegisteredContext context) { context.SetTestExecutor(new CultureExecutor(cultureInfo)); diff --git a/TUnit.Core/Attributes/Executors/STAThreadExecutorAttribute.cs b/TUnit.Core/Attributes/Executors/STAThreadExecutorAttribute.cs index 403b6604b2..52b43a538e 100644 --- a/TUnit.Core/Attributes/Executors/STAThreadExecutorAttribute.cs +++ b/TUnit.Core/Attributes/Executors/STAThreadExecutorAttribute.cs @@ -9,6 +9,9 @@ public class STAThreadExecutorAttribute : TUnitAttribute, ITestRegisteredEventRe { public int Order => 0; +#if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] +#endif public ValueTask OnTestRegistered(TestRegisteredContext context) { var executor = new STAThreadExecutor(); diff --git a/TUnit.Core/Attributes/Executors/TestExecutorAttribute.cs b/TUnit.Core/Attributes/Executors/TestExecutorAttribute.cs index c549172816..9d32a2d863 100644 --- a/TUnit.Core/Attributes/Executors/TestExecutorAttribute.cs +++ b/TUnit.Core/Attributes/Executors/TestExecutorAttribute.cs @@ -8,6 +8,9 @@ namespace TUnit.Core.Executors; { public int Order => 0; +#if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] +#endif public ValueTask OnTestRegistered(TestRegisteredContext context) { context.SetTestExecutor(new T()); @@ -20,6 +23,9 @@ public sealed class TestExecutorAttribute([DynamicallyAccessedMembers(Dynamicall { public int Order => 0; +#if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] +#endif public ValueTask OnTestRegistered(TestRegisteredContext context) { context.SetTestExecutor((ITestExecutor) Activator.CreateInstance(type)!); diff --git a/TUnit.Core/Attributes/ParallelLimiterAttribute.cs b/TUnit.Core/Attributes/ParallelLimiterAttribute.cs index 2bc23a15ce..1b5cc88b84 100644 --- a/TUnit.Core/Attributes/ParallelLimiterAttribute.cs +++ b/TUnit.Core/Attributes/ParallelLimiterAttribute.cs @@ -57,6 +57,9 @@ public sealed class ParallelLimiterAttribute : TUnitAttribute, I public int Order => 0; /// +#if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] +#endif public ValueTask OnTestRegistered(TestRegisteredContext context) { context.SetParallelLimiter(new TParallelLimit()); diff --git a/TUnit.Core/Attributes/TestData/ArgumentsAttribute.cs b/TUnit.Core/Attributes/TestData/ArgumentsAttribute.cs index 6974b8c03f..0ff0cc87ff 100644 --- a/TUnit.Core/Attributes/TestData/ArgumentsAttribute.cs +++ b/TUnit.Core/Attributes/TestData/ArgumentsAttribute.cs @@ -1,10 +1,14 @@ +using TUnit.Core.Interfaces; + namespace TUnit.Core; [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)] -public sealed class ArgumentsAttribute : Attribute, IDataSourceAttribute +public sealed class ArgumentsAttribute : Attribute, IDataSourceAttribute, ITestRegisteredEventReceiver { public object?[] Values { get; } + public string? Skip { get; set; } + public ArgumentsAttribute(params object?[]? values) { if (values == null || values.Length == 0) @@ -22,14 +26,48 @@ public ArgumentsAttribute(params object?[]? values) yield return () => Task.FromResult(Values); await Task.CompletedTask; } + +#if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] +#endif + public ValueTask OnTestRegistered(TestRegisteredContext context) + { + if(!string.IsNullOrEmpty(Skip)) + { + context.TestContext.SkipReason = Skip; + context.TestContext.TestDetails.ClassInstance = SkippedTestInstance.Instance; + } + + return default; + } + + public int Order => 0; } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)] -public sealed class ArgumentsAttribute(T value) : TypedDataSourceAttribute +public sealed class ArgumentsAttribute(T value) : TypedDataSourceAttribute, ITestRegisteredEventReceiver { + public string? Skip { get; set; } + public override async IAsyncEnumerable>> GetTypedDataRowsAsync(DataGeneratorMetadata dataGeneratorMetadata) { yield return () => Task.FromResult(value); await default(ValueTask); } + +#if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] +#endif + public ValueTask OnTestRegistered(TestRegisteredContext context) + { + if(!string.IsNullOrEmpty(Skip)) + { + context.TestContext.SkipReason = Skip; + context.TestContext.TestDetails.ClassInstance = SkippedTestInstance.Instance; + } + + return default; + } + + public int Order => 0; } diff --git a/TUnit.Core/Attributes/TestData/AsyncUntypedDataSourceSourceGeneratorAttribute.cs b/TUnit.Core/Attributes/TestData/AsyncUntypedDataSourceSourceGeneratorAttribute.cs index 1d4dcd9b50..e483358c28 100644 --- a/TUnit.Core/Attributes/TestData/AsyncUntypedDataSourceSourceGeneratorAttribute.cs +++ b/TUnit.Core/Attributes/TestData/AsyncUntypedDataSourceSourceGeneratorAttribute.cs @@ -1,10 +1,12 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace TUnit.Core; [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)] +#if NET6_0_OR_GREATER [RequiresDynamicCode("AsyncUntypedDataSourceGeneratorAttribute requires dynamic code generation for runtime data source creation. Consider using strongly-typed AsyncDataSourceGeneratorAttribute overloads for AOT compatibility.")] [RequiresUnreferencedCode("AsyncUntypedDataSourceGeneratorAttribute may require unreferenced code for runtime data source creation. Consider using strongly-typed AsyncDataSourceGeneratorAttribute overloads for AOT compatibility.")] +#endif public abstract class AsyncUntypedDataSourceGeneratorAttribute : Attribute, IAsyncUntypedDataSourceGeneratorAttribute { protected abstract IAsyncEnumerable>> GenerateDataSourcesAsync(DataGeneratorMetadata dataGeneratorMetadata); diff --git a/TUnit.Core/Attributes/TestData/ClassDataSourceAttribute.cs b/TUnit.Core/Attributes/TestData/ClassDataSourceAttribute.cs index 8290bf3e7c..8fb04980a7 100644 --- a/TUnit.Core/Attributes/TestData/ClassDataSourceAttribute.cs +++ b/TUnit.Core/Attributes/TestData/ClassDataSourceAttribute.cs @@ -25,22 +25,28 @@ protected override IEnumerable> GenerateDataSources(DataGeneratorMetadat } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] -[UnconditionalSuppressMessage("Trimming", "IL2109:Type derives from type with 'RequiresUnreferencedCodeAttribute' which can break functionality when trimming application code", - Justification = "The specific constructors (1-5 parameters) are AOT-compatible when used with typeof() expressions. Only the params constructor is incompatible.")] +#if NET6_0_OR_GREATER +[RequiresUnreferencedCode("ClassDataSourceAttribute uses reflection to instantiate and access test data classes. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] +[RequiresDynamicCode("ClassDataSourceAttribute may require runtime type generation. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] +#endif public sealed class ClassDataSourceAttribute : UntypedDataSourceGeneratorAttribute { private readonly Type[] _types; - [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "These constructors delegate to the params constructor but are AOT-safe when used with typeof() expressions at compile time. The DynamicallyAccessedMembers annotations ensure required members are preserved.")] - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break functionality when AOT compiling.", Justification = "These constructors are AOT-compatible when types are specified using typeof() at compile time. Only the params constructor requires dynamic code.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("ClassDataSourceAttribute uses reflection to instantiate and access test data classes. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + [RequiresDynamicCode("ClassDataSourceAttribute may require runtime type generation. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + #endif public ClassDataSourceAttribute( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicMethods)] Type type) : this([type]) { } - [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "These constructors delegate to the params constructor but are AOT-safe when used with typeof() expressions at compile time. The DynamicallyAccessedMembers annotations ensure required members are preserved.")] - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break functionality when AOT compiling.", Justification = "These constructors are AOT-compatible when types are specified using typeof() at compile time. Only the params constructor requires dynamic code.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("ClassDataSourceAttribute uses reflection to instantiate and access test data classes. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + [RequiresDynamicCode("ClassDataSourceAttribute may require runtime type generation. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + #endif public ClassDataSourceAttribute( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicMethods)] Type type, @@ -49,8 +55,10 @@ public ClassDataSourceAttribute( { } - [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "These constructors delegate to the params constructor but are AOT-safe when used with typeof() expressions at compile time. The DynamicallyAccessedMembers annotations ensure required members are preserved.")] - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break functionality when AOT compiling.", Justification = "These constructors are AOT-compatible when types are specified using typeof() at compile time. Only the params constructor requires dynamic code.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("ClassDataSourceAttribute uses reflection to instantiate and access test data classes. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + [RequiresDynamicCode("ClassDataSourceAttribute may require runtime type generation. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + #endif public ClassDataSourceAttribute( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicMethods)] Type type, @@ -61,8 +69,10 @@ public ClassDataSourceAttribute( { } - [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "These constructors delegate to the params constructor but are AOT-safe when used with typeof() expressions at compile time. The DynamicallyAccessedMembers annotations ensure required members are preserved.")] - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break functionality when AOT compiling.", Justification = "These constructors are AOT-compatible when types are specified using typeof() at compile time. Only the params constructor requires dynamic code.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("ClassDataSourceAttribute uses reflection to instantiate and access test data classes. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + [RequiresDynamicCode("ClassDataSourceAttribute may require runtime type generation. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + #endif public ClassDataSourceAttribute( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicMethods)] Type type, @@ -75,8 +85,10 @@ public ClassDataSourceAttribute( { } - [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "These constructors delegate to the params constructor but are AOT-safe when used with typeof() expressions at compile time. The DynamicallyAccessedMembers annotations ensure required members are preserved.")] - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break functionality when AOT compiling.", Justification = "These constructors are AOT-compatible when types are specified using typeof() at compile time. Only the params constructor requires dynamic code.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("ClassDataSourceAttribute uses reflection to instantiate and access test data classes. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + [RequiresDynamicCode("ClassDataSourceAttribute may require runtime type generation. For AOT compatibility, use strongly-typed ClassDataSourceAttribute instead.")] + #endif public ClassDataSourceAttribute( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicMethods)] Type type, @@ -91,8 +103,10 @@ public ClassDataSourceAttribute( { } + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("Reflection")] [RequiresDynamicCode("Reflection")] + #endif public ClassDataSourceAttribute(params Type[] types) { _types = types; @@ -101,7 +115,10 @@ public ClassDataSourceAttribute(params Type[] types) public SharedType[] Shared { get; set; } = [SharedType.None]; public string[] Keys { get; set; } = []; - [UnconditionalSuppressMessage("Trimming", "IL2062:The parameter of method has a DynamicallyAccessedMembersAttribute, but the value passed to it can not be statically analyzed.", Justification = "The _types array is populated from constructor parameters that have DynamicallyAccessedMembers attributes, ensuring the required members are preserved at the call site.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Reflection")] + [RequiresDynamicCode("Reflection")] + #endif protected override IEnumerable> GenerateDataSources(DataGeneratorMetadata dataGeneratorMetadata) { yield return () => diff --git a/TUnit.Core/Attributes/TestData/DependencyInjectionDataSourceSourceAttribute.cs b/TUnit.Core/Attributes/TestData/DependencyInjectionDataSourceSourceAttribute.cs index bcaa40d58b..817035eba9 100644 --- a/TUnit.Core/Attributes/TestData/DependencyInjectionDataSourceSourceAttribute.cs +++ b/TUnit.Core/Attributes/TestData/DependencyInjectionDataSourceSourceAttribute.cs @@ -2,8 +2,10 @@ namespace TUnit.Core; +#if NET6_0_OR_GREATER [RequiresDynamicCode("DependencyInjectionDataSourceAttribute requires dynamic code generation for dependency injection container access. This attribute is inherently incompatible with AOT compilation.")] [RequiresUnreferencedCode("DependencyInjectionDataSourceAttribute may require unreferenced code for dependency injection container access. This attribute is inherently incompatible with AOT compilation.")] +#endif public abstract class DependencyInjectionDataSourceAttribute : UntypedDataSourceGeneratorAttribute { protected override IEnumerable> GenerateDataSources(DataGeneratorMetadata dataGeneratorMetadata) diff --git a/TUnit.Core/Attributes/TestData/MatrixDataSourceAttribute.cs b/TUnit.Core/Attributes/TestData/MatrixDataSourceAttribute.cs index 66f7ce99be..18abcc9d44 100644 --- a/TUnit.Core/Attributes/TestData/MatrixDataSourceAttribute.cs +++ b/TUnit.Core/Attributes/TestData/MatrixDataSourceAttribute.cs @@ -5,10 +5,16 @@ namespace TUnit.Core; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] -[UnconditionalSuppressMessage("AOT", "IL2109:Type 'MatrixDataSourceAttribute' derives from base class with RequiresUnreferencedCodeAttribute", - Justification = "Matrix data source implementation is AOT-compatible with proper enum field preservation")] +#if NET6_0_OR_GREATER +[RequiresUnreferencedCode("MatrixDataSource uses reflection to access parameter attributes and test metadata. For AOT compatibility, consider using explicit data sources.")] +[RequiresDynamicCode("MatrixDataSource may process enum types dynamically")] +#endif public sealed class MatrixDataSourceAttribute : UntypedDataSourceGeneratorAttribute, IAccessesInstanceData { + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Matrix generation requires reflection")] + [RequiresDynamicCode("Matrix generation may process enum types dynamically")] + #endif protected override IEnumerable> GenerateDataSources(DataGeneratorMetadata dataGeneratorMetadata) { var parameterInformation = dataGeneratorMetadata @@ -84,8 +90,9 @@ private bool IsExcluded(object?[] exclusion, IEnumerable row) .ToArray(); } - [UnconditionalSuppressMessage("AOT", "IL2072:Target parameter argument does not satisfy DynamicallyAccessedMemberTypes requirements", - Justification = "Test parameter types are comprehensively preserved by the source generation system for matrix data scenarios")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Test parameter types accessed through reflection")] + #endif private IReadOnlyList GetAllArguments(DataGeneratorMetadata dataGeneratorMetadata, ParameterMetadata sourceGeneratedParameterInformation) { diff --git a/TUnit.Core/Attributes/TestData/MethodDataSourceAttribute.cs b/TUnit.Core/Attributes/TestData/MethodDataSourceAttribute.cs index a7e9c3d55e..7eda317f4f 100644 --- a/TUnit.Core/Attributes/TestData/MethodDataSourceAttribute.cs +++ b/TUnit.Core/Attributes/TestData/MethodDataSourceAttribute.cs @@ -52,8 +52,8 @@ public MethodDataSourceAttribute( MethodNameProvidingDataSource = methodNameProvidingDataSource; } - [UnconditionalSuppressMessage("AOT", "IL2072:UnrecognizedReflectionPattern", Justification = "Method data sources require runtime discovery and invocation of methods. The target type is determined dynamically from test metadata. For AOT scenarios, source generation should be used to pre-compile method references.")] - [UnconditionalSuppressMessage("AOT", "IL2075:UnrecognizedReflectionPattern", Justification = "GetType() is called on runtime objects from test class instances. The actual types cannot be statically determined. For AOT scenarios, source generation captures these types at compile time.")] + [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Method data sources require runtime discovery. AOT users should use Factory property.")] + [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Method data sources require runtime discovery. AOT users should use Factory property.")] public async IAsyncEnumerable>> GetDataRowsAsync(DataGeneratorMetadata dataGeneratorMetadata) { if (Factory != null) @@ -237,7 +237,9 @@ private static bool IsAsyncEnumerable([DynamicallyAccessedMembers(DynamicallyAcc i.GetGenericTypeDefinition() == typeof(IAsyncEnumerable<>)); } - [UnconditionalSuppressMessage("AOT", "IL2075:UnrecognizedReflectionPattern", Justification = "Reflection is required to convert IAsyncEnumerable from data source methods. The generic type T is determined at runtime from the data source's return type. For AOT scenarios, source generation should be used instead.")] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Reflection usage is documented. AOT-safe path available via Factory property")] + [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Reflection usage is documented. AOT-safe path available via Factory property")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Dynamic code usage is documented. AOT-safe path available via Factory property")] private static async IAsyncEnumerable ConvertToAsyncEnumerable(object asyncEnumerable, [EnumeratorCancellation] CancellationToken cancellationToken = default) { var type = asyncEnumerable.GetType(); @@ -316,7 +318,9 @@ private static bool IsAsyncEnumerable([DynamicallyAccessedMembers(DynamicallyAcc } } - [UnconditionalSuppressMessage("AOT", "IL2075:UnrecognizedReflectionPattern", Justification = "Accessing Result property on Task requires reflection since T is not known at compile time. This is used to extract values from data source methods that return Task. For AOT, source generation pre-compiles these access patterns.")] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Reflection usage is documented. AOT-safe path available via Factory property")] + [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Reflection usage is documented. AOT-safe path available via Factory property")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Dynamic code usage is documented. AOT-safe path available via Factory property")] private static object? GetTaskResult(Task task) { var taskType = task.GetType(); diff --git a/TUnit.Core/Attributes/TestData/UntypedDataSourceGeneratorAttribute.cs b/TUnit.Core/Attributes/TestData/UntypedDataSourceGeneratorAttribute.cs index 657f650d25..52c1b3b349 100644 --- a/TUnit.Core/Attributes/TestData/UntypedDataSourceGeneratorAttribute.cs +++ b/TUnit.Core/Attributes/TestData/UntypedDataSourceGeneratorAttribute.cs @@ -3,8 +3,10 @@ namespace TUnit.Core; [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true)] +#if NET6_0_OR_GREATER [RequiresDynamicCode("UntypedDataSourceGeneratorAttribute requires dynamic code generation for runtime data source creation. Consider using strongly-typed AsyncDataSourceGeneratorAttribute overloads for AOT compatibility.")] [RequiresUnreferencedCode("UntypedDataSourceGeneratorAttribute may require unreferenced code for runtime data source creation. Consider using strongly-typed AsyncDataSourceGeneratorAttribute overloads for AOT compatibility.")] +#endif public abstract class UntypedDataSourceGeneratorAttribute : AsyncUntypedDataSourceGeneratorAttribute { protected abstract IEnumerable> GenerateDataSources(DataGeneratorMetadata dataGeneratorMetadata); diff --git a/TUnit.Core/Attributes/TestMetadata/SkipAttribute.cs b/TUnit.Core/Attributes/TestMetadata/SkipAttribute.cs index 0b5b7e6feb..f57dff0f0d 100644 --- a/TUnit.Core/Attributes/TestMetadata/SkipAttribute.cs +++ b/TUnit.Core/Attributes/TestMetadata/SkipAttribute.cs @@ -16,6 +16,9 @@ public SkipAttribute(string reason) public int Order => int.MinValue; /// +#if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] +#endif public async ValueTask OnTestRegistered(TestRegisteredContext context) { if (await ShouldSkip(context)) diff --git a/TUnit.Core/DataGeneratorMetadataCreator.cs b/TUnit.Core/DataGeneratorMetadataCreator.cs index 79461e41c6..bcb0d6ef55 100644 --- a/TUnit.Core/DataGeneratorMetadataCreator.cs +++ b/TUnit.Core/DataGeneratorMetadataCreator.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using TUnit.Core.Enums; @@ -206,7 +206,9 @@ public static DataGeneratorMetadata CreateForPropertyInjection( /// /// Creates DataGeneratorMetadata for property injection using PropertyInfo (reflection mode). /// - [UnconditionalSuppressMessage("Trimming", "IL2072:'value' argument does not satisfy 'DynamicallyAccessedMemberTypes' in call to 'TUnit.Core.PropertyMetadata.Type.init'", Justification = "Property types are resolved through reflection")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Property types are resolved through reflection")] + #endif public static DataGeneratorMetadata CreateForPropertyInjection( PropertyInfo property, Type containingType, @@ -253,9 +255,9 @@ private static ParameterMetadata[] FilterOutCancellationToken(ParameterMetadata[ return parameters; } - [UnconditionalSuppressMessage("Trimming", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'System.Type.GetConstructors(BindingFlags)'", Justification = "Constructor discovery needed for metadata")] - [UnconditionalSuppressMessage("Trimming", "IL2067:'value' argument does not satisfy 'DynamicallyAccessedMemberTypes' in call to 'TUnit.Core.ClassMetadata.Type.init'", Justification = "Type annotations are handled by reflection")] - [UnconditionalSuppressMessage("Trimming", "IL2072:'Type' argument does not satisfy 'DynamicallyAccessedMemberTypes' in call to 'TUnit.Core.ParameterMetadata.ParameterMetadata(Type)'", Justification = "Parameter types are known through reflection")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Class metadata creation requires reflection")] + #endif private static ClassMetadata GetClassMetadataForType(Type type) { return ClassMetadata.GetOrAdd(type.FullName ?? type.Name, () => diff --git a/TUnit.Core/DataSources/DataSourceProcessor.cs b/TUnit.Core/DataSources/DataSourceProcessor.cs index 8eaaf70375..98d8c131fd 100644 --- a/TUnit.Core/DataSources/DataSourceProcessor.cs +++ b/TUnit.Core/DataSources/DataSourceProcessor.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace TUnit.Core.DataSources; @@ -54,8 +54,10 @@ public static class DataSourceProcessor /// Processes a generator result item and extracts the data values /// This method uses reflection and is only suitable for reflection mode /// + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("This method uses reflection to process data sources")] [RequiresDynamicCode("This method may create types at runtime")] + #endif public static async Task> ProcessGeneratorItemAsync(object? item) { var items = new List(); @@ -141,8 +143,10 @@ public static class DataSourceProcessor /// Resolves a value that might be wrapped in a Func or Task /// This method uses reflection and is only suitable for reflection mode /// + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("This method uses reflection to resolve values")] [RequiresDynamicCode("This method may invoke methods dynamically")] + #endif public static async Task ResolveValueAsync(object? value) { if (value == null) @@ -209,7 +213,9 @@ public static class DataSourceProcessor /// Processes method data source results into a consistent format /// This method uses reflection for tuple processing and is not AOT-compatible /// + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("This method uses reflection for tuple processing")] + #endif public static IEnumerable ProcessMethodDataSourceResult(object? result) { if (result == null) @@ -289,13 +295,17 @@ public static class DataSourceProcessor #region Tuple Processing Helpers (Reflection-based, not AOT-compatible) + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("Tuple processing requires reflection")] + #endif private static bool TryProcessTupleArray(object result, Type resultType) { return resultType.IsArray && resultType.GetElementType()?.Name.StartsWith("ValueTuple") == true; } + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("Tuple processing requires reflection")] + #endif private static IEnumerable ProcessTupleArray(object result, Type resultType) { var array = (Array)result; @@ -316,13 +326,17 @@ private static bool TryProcessTupleArray(object result, Type resultType) } } + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("Tuple processing requires reflection")] + #endif private static bool TryProcessSingleTuple(object result, Type resultType) { return resultType.Name.StartsWith("ValueTuple"); } + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("Tuple processing requires reflection")] + #endif private static object?[] ProcessSingleTuple(object result, Type resultType) { var fields = GetTupleFields(resultType); @@ -342,7 +356,9 @@ private static bool TryProcessSingleTuple(object result, Type resultType) /// /// Gets the Result property from a Task type with proper AOT attribution /// + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("Property access requires reflection")] + #endif private static PropertyInfo? GetTaskResultProperty([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type taskType) { return taskType.GetProperty("Result"); @@ -351,7 +367,9 @@ private static bool TryProcessSingleTuple(object result, Type resultType) /// /// Gets the Invoke method from a delegate type with proper AOT attribution /// + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("Method access requires reflection")] + #endif private static MethodInfo? GetDelegateInvokeMethod([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type delegateType) { return delegateType.GetMethod("Invoke"); @@ -360,11 +378,13 @@ private static bool TryProcessSingleTuple(object result, Type resultType) /// /// Gets fields from a tuple type with proper AOT attribution /// + #if NET6_0_OR_GREATER [RequiresUnreferencedCode("Field access requires reflection")] + #endif private static FieldInfo[] GetTupleFields([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] Type tupleType) { return tupleType.GetFields(); } #endregion -} \ No newline at end of file +} diff --git a/TUnit.Core/DynamicTestBuilderContext.cs b/TUnit.Core/DynamicTestBuilderContext.cs index 0c6c04bbbb..c827b7a99d 100644 --- a/TUnit.Core/DynamicTestBuilderContext.cs +++ b/TUnit.Core/DynamicTestBuilderContext.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace TUnit.Core; @@ -22,7 +22,9 @@ public DynamicTestBuilderContext(string filePath, int lineNumber) public IReadOnlyList Tests => _tests.AsReadOnly(); + #if NET6_0_OR_GREATER [RequiresDynamicCode("Adding dynamic tests requires reflection which is not supported in native AOT scenarios.")] + #endif public void AddTest(AbstractDynamicTest test) { // Set creator location if the test implements IDynamicTestCreatorLocation diff --git a/TUnit.Core/Executors/DedicatedThreadExecutor.cs b/TUnit.Core/Executors/DedicatedThreadExecutor.cs index b64267d4a9..9871446ada 100644 --- a/TUnit.Core/Executors/DedicatedThreadExecutor.cs +++ b/TUnit.Core/Executors/DedicatedThreadExecutor.cs @@ -377,6 +377,9 @@ public override SynchronizationContext CreateCopy() } } +#if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] +#endif public ValueTask OnTestRegistered(TestRegisteredContext context) { context.SetParallelLimiter(new ProcessorCountParallelLimit()); diff --git a/TUnit.Core/Extensions/ReflectionExtensions.cs b/TUnit.Core/Extensions/ReflectionExtensions.cs index c83837571a..2094ddc1c1 100644 --- a/TUnit.Core/Extensions/ReflectionExtensions.cs +++ b/TUnit.Core/Extensions/ReflectionExtensions.cs @@ -109,6 +109,10 @@ public static T[] GetCustomAttributesSafe(this ICustomAttributeProvider provi #endif } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Attribute instantiation uses reflection for .NET Framework compatibility")] + [RequiresDynamicCode("Activator.CreateInstance required for attribute instantiation")] + #endif private static Attribute[] GetAttributesViaCustomAttributeData(ICustomAttributeProvider provider, Type attributeType, bool inherit) { var attributes = new List(); @@ -171,12 +175,10 @@ private static Attribute[] GetAttributesViaCustomAttributeData(ICustomAttributeP return attributes.ToArray(); } - [UnconditionalSuppressMessage("AOT", "IL2072:Target type's member does not satisfy requirements", - Justification = "Attribute instantiation uses known constructor patterns. For AOT scenarios, use source-generated attribute discovery.")] - [UnconditionalSuppressMessage("AOT", "IL2075:Target parameter does not satisfy requirements", - Justification = "Attribute types with known constructors are preserved. This is a fallback for non-source-generated scenarios.")] - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", - Justification = "Required for .NET Framework compatibility. AOT scenarios should use source-generated test discovery.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Attribute instantiation uses reflection for .NET Framework compatibility")] + [RequiresDynamicCode("Activator.CreateInstance required for attribute instantiation")] + #endif private static Attribute? CreateAttributeInstance(CustomAttributeData attributeData) { var attributeType = attributeData.AttributeType; @@ -241,10 +243,13 @@ private static Attribute[] GetAttributesViaCustomAttributeData(ICustomAttributeP return attribute; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Runtime type property access for attribute argument extraction")] + #endif private static object? ExtractArgumentValue(CustomAttributeTypedArgument arg) { var value = arg.Value; - + // In .NET Framework, params arrays come as ReadOnlyCollection if (value != null && value.GetType().FullName?.Contains("CustomAttributeTypedArgument") == true) { @@ -269,15 +274,16 @@ private static Attribute[] GetAttributesViaCustomAttributeData(ICustomAttributeP return items.ToArray(); } } - + return value; } /// /// Gets the "Value" property from a type in an AOT-safer manner. /// - [UnconditionalSuppressMessage("Trimming", "IL2075:Target method return value does not satisfy annotation requirements", - Justification = "Value property access is used for unwrapping test data. For AOT scenarios, use strongly-typed data sources.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Property access used for unwrapping test data")] + #endif private static PropertyInfo? GetValuePropertySafe([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type) { return type.GetProperty("Value"); @@ -286,10 +292,9 @@ private static Attribute[] GetAttributesViaCustomAttributeData(ICustomAttributeP /// /// Gets the "Value" property from a runtime type. /// - [UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter does not satisfy annotation requirements", - Justification = "Runtime type from GetType() cannot have static annotations. This is used for CustomAttributeTypedArgument unwrapping.")] - [UnconditionalSuppressMessage("Trimming", "IL2067:Target parameter does not satisfy annotation requirements", - Justification = "The type parameter comes from runtime GetType() which cannot be annotated. Used for attribute argument extraction.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Runtime type property access for attribute argument extraction")] + #endif private static PropertyInfo? GetValuePropertyForType(Type type) { return GetValuePropertySafe(type); diff --git a/TUnit.Core/Extensions/TestContextExtensions.cs b/TUnit.Core/Extensions/TestContextExtensions.cs index d17875ecef..0e1e05984e 100644 --- a/TUnit.Core/Extensions/TestContextExtensions.cs +++ b/TUnit.Core/Extensions/TestContextExtensions.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using TUnit.Core.Helpers; using TUnit.Core.Interfaces; @@ -23,7 +23,10 @@ public static string GetClassTypeName(this TestContext context) return $"{context.TestDetails.ClassType.Name}({string.Join(", ", context.TestDetails.TestClassArguments.Select(a => ArgumentFormatter.Format(a, context.ArgumentDisplayFormatters)))})"; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dynamic test metadata creation uses reflection")] [RequiresDynamicCode("Adding dynamic tests requires reflection which is not supported in native AOT scenarios.")] + #endif public static async Task AddDynamicTest<[DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors diff --git a/TUnit.Core/Helpers/CastHelper.cs b/TUnit.Core/Helpers/CastHelper.cs index d0ac03195f..14d7b5d1c5 100644 --- a/TUnit.Core/Helpers/CastHelper.cs +++ b/TUnit.Core/Helpers/CastHelper.cs @@ -7,10 +7,10 @@ namespace TUnit.Core.Helpers; public static class CastHelper { - [UnconditionalSuppressMessage("Trimming", "IL2072", - Justification = "Type conversion uses DynamicallyAccessedMembers for known conversion patterns. For AOT scenarios, use explicit type conversions.")] - [UnconditionalSuppressMessage("AOT", "IL3050", - Justification = "Reflection-based conversion is a fallback for runtime scenarios. AOT applications should use explicit conversions.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Type conversion uses reflection for custom conversions")] + [RequiresDynamicCode("Dynamic type conversion may require runtime code generation")] + #endif public static T? Cast<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] T>(object? value) { if (value is null) @@ -175,10 +175,10 @@ public static class CastHelper } } - [UnconditionalSuppressMessage("Trimming", "IL2072", - Justification = "Type conversion uses DynamicallyAccessedMembers for known conversion patterns. For AOT scenarios, use explicit type conversions.")] - [UnconditionalSuppressMessage("AOT", "IL3050", - Justification = "Reflection-based conversion is a fallback for runtime scenarios. AOT applications should use explicit conversions.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Type conversion uses reflection for custom conversions")] + [RequiresDynamicCode("Dynamic type conversion may require runtime code generation")] + #endif public static object? Cast([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type type, object? value) { if (value is null) @@ -372,8 +372,9 @@ private static bool HasCorrectInputType(Type baseType, MethodInfo mi) /// /// Gets the "Value" property from a type in an AOT-safer manner. /// - [UnconditionalSuppressMessage("Trimming", "IL2075:Target method return value does not satisfy annotation requirements", - Justification = "Value property access is used for unwrapping CustomAttributeTypedArgument. For AOT scenarios, use source-generated attribute discovery.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Property access for CustomAttributeTypedArgument unwrapping")] + #endif private static PropertyInfo? GetValuePropertySafe([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type) { return type.GetProperty("Value"); diff --git a/TUnit.Core/Helpers/DataSourceHelpers.cs b/TUnit.Core/Helpers/DataSourceHelpers.cs index 1312329cfa..f9a57ebffd 100644 --- a/TUnit.Core/Helpers/DataSourceHelpers.cs +++ b/TUnit.Core/Helpers/DataSourceHelpers.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -71,8 +71,6 @@ public static T InvokeIfFunc(object? value) /// /// AOT-compatible tuple unwrapping that handles common tuple types without reflection /// - [UnconditionalSuppressMessage("Trimming", "IL2091:Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type.", - Justification = "We handle specific known tuple types without reflection")] public static object?[] UnwrapTupleAot(object? value) { if (value == null) @@ -567,6 +565,10 @@ public static void RegisterTypeCreator(Func> /// Resolves a data source property value at runtime. /// This method handles all IDataSourceAttribute implementations generically. /// + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Property types are resolved through reflection")] + [RequiresDynamicCode("Data source resolution may require dynamic code generation")] + #endif public static async Task ResolveDataSourceForPropertyAsync([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] Type containingType, string propertyName, MethodMetadata testInformation, string testSessionId) { // Use PropertyInjectionService to resolve the data source attribute @@ -583,7 +585,7 @@ public static void RegisterTypeCreator(Func> } var dataSourceAttribute = (IDataSourceAttribute)dataSourceAttributes[0]; - + // Create the data generator metadata with required fields var dataGeneratorMetadata = DataGeneratorMetadataCreator.CreateForPropertyInjection( propertyInfo, @@ -598,7 +600,7 @@ public static void RegisterTypeCreator(Func> // Generate the data source value using the attribute's GetDataRowsAsync method var dataRows = dataSourceAttribute.GetDataRowsAsync(dataGeneratorMetadata); - + // Get the first value from the async enumerable await foreach (var factory in dataRows) { @@ -606,10 +608,10 @@ public static void RegisterTypeCreator(Func> if (args is { Length: > 0 }) { var value = args[0]; - + // Initialize the value if it implements IAsyncInitializer await ObjectInitializer.InitializeAsync(value); - + return value; } } diff --git a/TUnit.Core/Helpers/GenericTypeHelper.cs b/TUnit.Core/Helpers/GenericTypeHelper.cs index 1648d186c1..563b80202b 100644 --- a/TUnit.Core/Helpers/GenericTypeHelper.cs +++ b/TUnit.Core/Helpers/GenericTypeHelper.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace TUnit.Core.Helpers; @@ -16,10 +16,9 @@ public static class GenericTypeHelper /// The constructed generic type /// Thrown when genericTypeDefinition is null /// Thrown when type arguments don't match the generic type definition - [UnconditionalSuppressMessage("AOT", "IL2055:UnrecognizedReflectionPattern", - Justification = "MakeGenericType is used as a fallback. AOT analyzer warns at compile time.")] - [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", - Justification = "MakeGenericType is used as a fallback. AOT analyzer warns at compile time.")] + #if NET6_0_OR_GREATER + [RequiresDynamicCode("MakeGenericType requires runtime code generation")] + #endif public static Type MakeGenericTypeSafe(Type genericTypeDefinition, params Type[] typeArguments) { if (genericTypeDefinition == null) @@ -52,7 +51,11 @@ public static Type MakeGenericTypeSafe(Type genericTypeDefinition, params Type[] try { // Reflection mode - use MakeGenericType directly - return genericTypeDefinition.MakeGenericType(typeArguments); + // Method is already annotated with RequiresDynamicCode, suppressing IL2055 + [UnconditionalSuppressMessage("Trimming", "IL2055:MakeGenericType", Justification = "Method is already properly annotated with RequiresDynamicCode to indicate AOT incompatibility")] + static Type MakeGenericTypeUnsafe(Type genericType, Type[] args) => genericType.MakeGenericType(args); + + return MakeGenericTypeUnsafe(genericTypeDefinition, typeArguments); } catch (ArgumentException ex) { @@ -85,4 +88,4 @@ public static Type GetGenericTypeDefinition(Type type) return type.IsGenericTypeDefinition ? type : type.GetGenericTypeDefinition(); } -} \ No newline at end of file +} diff --git a/TUnit.Core/Helpers/TupleHelper.cs b/TUnit.Core/Helpers/TupleHelper.cs index cab89c794d..159b279d8b 100644 --- a/TUnit.Core/Helpers/TupleHelper.cs +++ b/TUnit.Core/Helpers/TupleHelper.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; @@ -163,8 +163,9 @@ public static bool IsTupleArrayType(Type type) /// Expands an array of tuples into individual tuple elements for data source generation /// For example: [(1, "a"), (2, "b")] becomes individual items that each unwrap to [1, "a"] and [2, "b"] /// - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", - Justification = "Reflection is used as a fallback. AOT analyzer warns at compile time.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Tuple expansion uses reflection as fallback")] + #endif public static IEnumerable ExpandTupleArray(object? value) { if (value == null) diff --git a/TUnit.Core/Hooks/LastTestInClassAdapter.cs b/TUnit.Core/Hooks/LastTestInClassAdapter.cs index 0435fc94a6..d328c2d245 100644 --- a/TUnit.Core/Hooks/LastTestInClassAdapter.cs +++ b/TUnit.Core/Hooks/LastTestInClassAdapter.cs @@ -3,7 +3,9 @@ namespace TUnit.Core.Hooks; -[UnconditionalSuppressMessage("Trimming", "IL2111:Method with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can\'t guarantee availability of the requirements of the method.")] +#if NET6_0_OR_GREATER +[RequiresUnreferencedCode("Method with DynamicallyAccessedMembersAttribute accessed via reflection")] +#endif public class LastTestInClassAdapter(ILastTestInClassEventReceiver lastTestInClassEventReceiver, TestContext testContext) : IExecutableHook { public string Name => nameof(lastTestInClassEventReceiver.OnLastTestInClass); diff --git a/TUnit.Core/Interfaces/ITestRegisteredEventReceiver.cs b/TUnit.Core/Interfaces/ITestRegisteredEventReceiver.cs index f42ef301f0..fd429a4ac2 100644 --- a/TUnit.Core/Interfaces/ITestRegisteredEventReceiver.cs +++ b/TUnit.Core/Interfaces/ITestRegisteredEventReceiver.cs @@ -8,5 +8,8 @@ public interface ITestRegisteredEventReceiver : IEventReceiver /// /// Called when a test is registered /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif ValueTask OnTestRegistered(TestRegisteredContext context); } diff --git a/TUnit.Core/Interfaces/ITestRegistry.cs b/TUnit.Core/Interfaces/ITestRegistry.cs index f35120875e..6c98b90363 100644 --- a/TUnit.Core/Interfaces/ITestRegistry.cs +++ b/TUnit.Core/Interfaces/ITestRegistry.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace TUnit.Core.Interfaces; @@ -14,7 +14,10 @@ public interface ITestRegistry /// The current test context /// The dynamic test instance to add /// A task that completes when the test has been queued for execution + #if NET6_0_OR_GREATER [RequiresDynamicCode("Adding dynamic tests requires runtime compilation and reflection which are not supported in native AOT scenarios.")] + [RequiresUnreferencedCode("Dynamic test metadata creation uses reflection")] + #endif Task AddDynamicTest<[DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors @@ -24,4 +27,4 @@ public interface ITestRegistry | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] T>(TestContext context, DynamicTest dynamicTest) where T : class; -} \ No newline at end of file +} diff --git a/TUnit.Core/Models/TestModels/ParameterMetadata.cs b/TUnit.Core/Models/TestModels/ParameterMetadata.cs index 36a9876101..790c84ef89 100644 --- a/TUnit.Core/Models/TestModels/ParameterMetadata.cs +++ b/TUnit.Core/Models/TestModels/ParameterMetadata.cs @@ -6,15 +6,26 @@ namespace TUnit.Core; [DebuggerDisplay("{Type} {Name}")] public record ParameterMetadata<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors + | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods + | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)] T>() : ParameterMetadata(typeof(T)); [DebuggerDisplay("{Type} {Name}")] public record ParameterMetadata([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors + | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods + | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)] Type Type) : MemberMetadata { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors + | DynamicallyAccessedMemberTypes.NonPublicConstructors + | DynamicallyAccessedMemberTypes.PublicMethods + | DynamicallyAccessedMemberTypes.NonPublicMethods + | DynamicallyAccessedMemberTypes.PublicProperties)] + public override Type Type { get; init; } = Type; + public required TypeReference TypeReference { get; init; } public required ParameterInfo ReflectionInfo { get; set; } public bool IsParams => CachedIsParams ?? ReflectionInfo.IsDefined(typeof(ParamArrayAttribute), false); diff --git a/TUnit.Core/PropertyInjection/ClassMetadataHelper.cs b/TUnit.Core/PropertyInjection/ClassMetadataHelper.cs index 7f49da4cf0..e43d50fa05 100644 --- a/TUnit.Core/PropertyInjection/ClassMetadataHelper.cs +++ b/TUnit.Core/PropertyInjection/ClassMetadataHelper.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace TUnit.Core.PropertyInjection; @@ -12,14 +12,16 @@ internal static class ClassMetadataHelper /// /// Gets or creates ClassMetadata for the specified type. /// - [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Metadata creation")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Metadata creation requires reflection")] + #endif public static ClassMetadata GetOrCreateClassMetadata( [DynamicallyAccessedMembers( - DynamicallyAccessedMemberTypes.PublicConstructors | - DynamicallyAccessedMemberTypes.NonPublicConstructors | - DynamicallyAccessedMemberTypes.PublicMethods | - DynamicallyAccessedMemberTypes.NonPublicMethods | - DynamicallyAccessedMemberTypes.PublicProperties)] + DynamicallyAccessedMemberTypes.PublicConstructors | + DynamicallyAccessedMemberTypes.NonPublicConstructors | + DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.NonPublicMethods | + DynamicallyAccessedMemberTypes.PublicProperties)] Type type) { return ClassMetadata.GetOrAdd(type.FullName ?? type.Name, () => @@ -52,4 +54,4 @@ public static ClassMetadata GetOrCreateClassMetadata( }; }); } -} \ No newline at end of file +} diff --git a/TUnit.Core/PropertyInjection/PropertyInjectionCache.cs b/TUnit.Core/PropertyInjection/PropertyInjectionCache.cs index 7cf13fcc91..161e647840 100644 --- a/TUnit.Core/PropertyInjection/PropertyInjectionCache.cs +++ b/TUnit.Core/PropertyInjection/PropertyInjectionCache.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using TUnit.Core.Data; namespace TUnit.Core.PropertyInjection; @@ -25,7 +25,9 @@ internal static class PropertyInjectionCache /// The plan builder will use source-generated metadata if available, /// otherwise falls back to reflection-based discovery. /// - [UnconditionalSuppressMessage("Trimming", "IL2067", Justification = "Type comes from runtime objects that cannot be annotated")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public static PropertyInjectionPlan GetOrCreatePlan(Type type) { return _injectionPlans.GetOrAdd(type, _ => PropertyInjectionPlanBuilder.Build(type)); @@ -34,7 +36,9 @@ public static PropertyInjectionPlan GetOrCreatePlan(Type type) /// /// Checks if a type has injectable properties using caching. /// - [UnconditionalSuppressMessage("Trimming", "IL2067", Justification = "Type comes from runtime objects that cannot be annotated")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public static bool HasInjectableProperties(Type type) { return _shouldInjectCache.GetOrAdd(type, t => diff --git a/TUnit.Core/PropertyInjection/PropertyInjectionPlanBuilder.cs b/TUnit.Core/PropertyInjection/PropertyInjectionPlanBuilder.cs index b020a2fa30..f0507f1418 100644 --- a/TUnit.Core/PropertyInjection/PropertyInjectionPlanBuilder.cs +++ b/TUnit.Core/PropertyInjection/PropertyInjectionPlanBuilder.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using TUnit.Core.Interfaces.SourceGenerator; @@ -14,7 +14,9 @@ internal static class PropertyInjectionPlanBuilder /// Creates an injection plan for source-generated mode. /// Walks the inheritance chain to include all injectable properties from base classes. /// - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "BaseType reflection is required for inheritance support")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("BaseType reflection required for inheritance support")] + #endif public static PropertyInjectionPlan BuildSourceGeneratedPlan(Type type) { var allProperties = new List(); @@ -54,8 +56,9 @@ public static PropertyInjectionPlan BuildSourceGeneratedPlan(Type type) /// /// Creates an injection plan for reflection mode. /// - [UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "Reflection mode support")] - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "BaseType reflection is required for inheritance support")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Reflection mode requires runtime property discovery")] + #endif public static PropertyInjectionPlan BuildReflectionPlan(Type type) { var propertyDataSourcePairs = new List<(PropertyInfo property, IDataSourceAttribute dataSource)>(); @@ -103,7 +106,9 @@ public static PropertyInjectionPlan BuildReflectionPlan(Type type) /// /// Builds an injection plan based on the current execution mode. /// - [UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "Handles both AOT and non-AOT scenarios")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Property injection plan building requires reflection")] + #endif public static PropertyInjectionPlan Build(Type type) { return SourceRegistrar.IsEnabled @@ -121,4 +126,4 @@ internal sealed class PropertyInjectionPlan public required PropertyInjectionMetadata[] SourceGeneratedProperties { get; init; } public required (PropertyInfo Property, IDataSourceAttribute DataSource)[] ReflectionProperties { get; init; } public required bool HasProperties { get; init; } -} \ No newline at end of file +} diff --git a/TUnit.Core/PropertyInjection/PropertySetterFactory.cs b/TUnit.Core/PropertyInjection/PropertySetterFactory.cs index 747542b7f7..78ee5fc005 100644 --- a/TUnit.Core/PropertyInjection/PropertySetterFactory.cs +++ b/TUnit.Core/PropertyInjection/PropertySetterFactory.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace TUnit.Core.PropertyInjection; @@ -12,6 +12,9 @@ internal static class PropertySetterFactory /// /// Creates a setter delegate for the given property. /// + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Backing field access for init-only properties requires reflection")] + #endif public static Action CreateSetter(PropertyInfo property) { if (property.CanWrite && property.SetMethod != null) @@ -43,8 +46,9 @@ internal static class PropertySetterFactory /// /// Gets the backing field for a property. /// - [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Accessing backing fields for init-only and required properties in reflection mode. The compiler-generated field naming pattern (k__BackingField) is stable. For AOT, source generation creates direct setters.")] - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "PropertyInfo.DeclaringType may not carry field annotations, but we only access compiler-generated backing fields which are preserved when the property is preserved. For AOT, use source-generated setters.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Backing field access for init-only properties requires reflection")] + #endif private static FieldInfo? GetBackingField(PropertyInfo property) { var declaringType = property.DeclaringType; @@ -84,11 +88,13 @@ internal static class PropertySetterFactory /// /// Helper method to get field with proper trimming suppression. /// - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Safe field access when DynamicallyAccessedMembers annotations are present. The caller ensures the type has the required field preservation. This is only used for setting property backing fields in reflection mode.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Field access for property backing fields requires reflection")] + #endif private static FieldInfo? GetFieldSafe( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] - Type type, - string name, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] + Type type, + string name, BindingFlags bindingFlags) { return type.GetField(name, bindingFlags); @@ -97,11 +103,13 @@ internal static class PropertySetterFactory /// /// Checks if a method is init-only. /// - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Checking for System.Runtime.CompilerServices.IsExternalInit modreq to identify init-only setters. This is a stable .NET runtime convention. For AOT, the source generator identifies init-only properties at compile time and generates appropriate setters.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Checking for init-only setters requires reflection")] + #endif private static bool IsInitOnlyMethod(MethodInfo setMethod) { var methodType = setMethod.GetType(); var isInitOnlyProperty = methodType.GetProperty("IsInitOnly"); return isInitOnlyProperty != null && (bool)isInitOnlyProperty.GetValue(setMethod)!; } -} \ No newline at end of file +} diff --git a/TUnit.Core/PropertyInjection/TupleValueResolver.cs b/TUnit.Core/PropertyInjection/TupleValueResolver.cs index 20ce2445bf..f023fd09ac 100644 --- a/TUnit.Core/PropertyInjection/TupleValueResolver.cs +++ b/TUnit.Core/PropertyInjection/TupleValueResolver.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using TUnit.Core.Helpers; namespace TUnit.Core.PropertyInjection; @@ -15,10 +15,12 @@ internal static class TupleValueResolver /// The expected property type /// The arguments from the data source /// The resolved value, potentially a tuple - [UnconditionalSuppressMessage("Trimming", "IL2067", Justification = "Tuple types are created dynamically")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Tuple types are created dynamically")] + #endif public static object? ResolveTupleValue( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] - Type propertyType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] + Type propertyType, object?[]? args) { if (args == null) @@ -59,4 +61,4 @@ internal static class TupleValueResolver // Single non-tuple argument for tuple property - shouldn't happen but handle gracefully return args.FirstOrDefault(); } -} \ No newline at end of file +} diff --git a/TUnit.Core/PropertySourceRegistry.cs b/TUnit.Core/PropertySourceRegistry.cs index 1ccd2770ed..65f024443e 100644 --- a/TUnit.Core/PropertySourceRegistry.cs +++ b/TUnit.Core/PropertySourceRegistry.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using TUnit.Core.Interfaces.SourceGenerator; @@ -78,7 +78,9 @@ public static void Register(Type type, IPropertySource source) /// /// Discovers injectable properties using reflection (legacy compatibility) /// - [UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "Reflection discovery is used when source-generated metadata is not available. This supports dynamically loaded assemblies and runtime property injection. For AOT scenarios, the source generator pre-discovers all injectable properties.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Reflection discovery is used when source-generated metadata is not available")] + #endif public static PropertyInjectionData[] DiscoverInjectableProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] Type type) { // First try source-generated data @@ -147,6 +149,9 @@ private static PropertyDataSource ConvertToPropertyDataSource(PropertyInjectionM /// /// Creates PropertyInjectionData from PropertyInfo (legacy compatibility) /// + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Backing field access for init-only properties requires reflection")] + #endif private static PropertyInjectionData CreatePropertyInjection(System.Reflection.PropertyInfo property) { var setter = CreatePropertySetter(property); @@ -164,6 +169,9 @@ private static PropertyInjectionData CreatePropertyInjection(System.Reflection.P /// /// Creates property setter (legacy compatibility) /// + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Backing field access for init-only properties requires reflection")] + #endif private static Action CreatePropertySetter(System.Reflection.PropertyInfo property) { if (property.CanWrite && property.SetMethod != null) @@ -195,8 +203,9 @@ private static PropertyInjectionData CreatePropertyInjection(System.Reflection.P /// /// Gets backing field for property (legacy compatibility) /// - [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Backing field discovery is needed for init-only and required properties in reflection mode. The field naming convention (k__BackingField) is stable in the .NET runtime. For AOT, source generation captures these relationships at compile time.")] - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "DeclaringType from PropertyInfo may not have field annotations, but we only access compiler-generated backing fields which follow predictable patterns. For AOT, use source-generated property setters.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Backing field discovery needed for init-only properties in reflection mode")] + #endif private static System.Reflection.FieldInfo? GetBackingField(System.Reflection.PropertyInfo property) { var declaringType = property.DeclaringType; @@ -236,7 +245,9 @@ private static PropertyInjectionData CreatePropertyInjection(System.Reflection.P /// /// Helper method to get field with proper trimming suppression /// - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Field access is constrained to backing fields of properties with data source attributes. The DynamicallyAccessedMembers annotation ensures fields are preserved when this method is called. For AOT, source generation provides direct field access.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Field access for property backing fields requires reflection")] + #endif private static System.Reflection.FieldInfo? GetFieldSafe([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] Type type, string name, System.Reflection.BindingFlags bindingFlags) { return type.GetField(name, bindingFlags); @@ -245,11 +256,13 @@ private static PropertyInjectionData CreatePropertyInjection(System.Reflection.P /// /// Checks if method is init-only (legacy compatibility) /// - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Checking for IsExternalInit modreq is required to identify init-only setters in reflection mode. This uses stable .NET runtime conventions. For AOT, the source generator identifies init-only properties at compile time.")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Checking for init-only setters requires reflection")] + #endif private static bool IsInitOnlyMethod(System.Reflection.MethodInfo setMethod) { var methodType = setMethod.GetType(); var isInitOnlyProperty = methodType.GetProperty("IsInitOnly"); return isInitOnlyProperty != null && (bool)isInitOnlyProperty.GetValue(setMethod)!; } -} \ No newline at end of file +} diff --git a/TUnit.Core/Services/GenericTypeResolver.cs b/TUnit.Core/Services/GenericTypeResolver.cs index f1e56e3ed8..251177643e 100644 --- a/TUnit.Core/Services/GenericTypeResolver.cs +++ b/TUnit.Core/Services/GenericTypeResolver.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using TUnit.Core.Exceptions; using TUnit.Core.Interfaces; @@ -8,8 +8,10 @@ namespace TUnit.Core.Services; /// /// Implementation of generic type resolution for test methods and classes /// +#if NET6_0_OR_GREATER [RequiresDynamicCode("Generic type resolution requires runtime type generation")] [RequiresUnreferencedCode("Generic type resolution may access types not preserved by trimming")] +#endif public class GenericTypeResolver : IGenericTypeResolver { /// diff --git a/TUnit.Core/StaticPropertyReflectionInitializer.cs b/TUnit.Core/StaticPropertyReflectionInitializer.cs index aa31ab09ed..a9c60ad217 100644 --- a/TUnit.Core/StaticPropertyReflectionInitializer.cs +++ b/TUnit.Core/StaticPropertyReflectionInitializer.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using System.Reflection; using TUnit.Core.Enums; @@ -8,15 +8,9 @@ namespace TUnit.Core; /// /// Handles initialization of static properties with data sources in reflection mode /// -[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access", - Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2067:Target parameter argument does not satisfy annotation requirements", - Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties'", - Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2075:'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties'", - Justification = "Reflection mode requires dynamic access")] - +#if NET6_0_OR_GREATER +[RequiresUnreferencedCode("Reflection mode requires dynamic access for static property initialization")] +#endif public static class StaticPropertyReflectionInitializer { private static readonly ConcurrentDictionary _initializedTypes = new(); @@ -24,6 +18,9 @@ public static class StaticPropertyReflectionInitializer /// /// Initializes static properties with data sources for all loaded types /// +#if NET6_0_OR_GREATER + [RequiresDynamicCode("Data source initialization may require dynamic code generation")] +#endif public static async Task InitializeAllStaticPropertiesAsync() { var assemblies = AppDomain.CurrentDomain.GetAssemblies() @@ -52,6 +49,9 @@ public static async Task InitializeAllStaticPropertiesAsync() /// /// Initializes static properties with data sources for a specific type /// +#if NET6_0_OR_GREATER + [RequiresDynamicCode("Data source initialization may require dynamic code generation")] +#endif public static async Task InitializeStaticPropertiesForType(Type type) { // Skip if already initialized @@ -84,6 +84,9 @@ private static bool HasDataSourceAttribute(PropertyInfo property) .Any(attr => attr is IDataSourceAttribute); } +#if NET6_0_OR_GREATER + [RequiresDynamicCode("Data source initialization may require dynamic code generation")] +#endif private static async Task InitializeStaticProperty(Type type, PropertyInfo property) { if (property.GetCustomAttributes() diff --git a/TUnit.Core/TestContext.cs b/TUnit.Core/TestContext.cs index 62bc086615..75248495a6 100644 --- a/TUnit.Core/TestContext.cs +++ b/TUnit.Core/TestContext.cs @@ -59,7 +59,6 @@ internal set public static string? OutputDirectory { - [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "Dynamic code check implemented")] get { #if NET @@ -68,8 +67,14 @@ public static string? OutputDirectory return AppContext.BaseDirectory; } #endif - return Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location) - ?? Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + [UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "Dynamic code check implemented")] + string GetOutputDirectory() + { + return Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location) + ?? Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!; + } + + return GetOutputDirectory(); } } @@ -320,6 +325,8 @@ public async Task ReregisterTestWithArguments(object?[]? methodArguments = null, public DateTimeOffset? TestEnd { get; set; } + public int CurrentRetryAttempt { get; internal set; } + public IEnumerable GetTests(Func predicate) { diff --git a/TUnit.Core/Tracking/ObjectTracker.cs b/TUnit.Core/Tracking/ObjectTracker.cs index 3626d9e890..e357dd3daa 100644 --- a/TUnit.Core/Tracking/ObjectTracker.cs +++ b/TUnit.Core/Tracking/ObjectTracker.cs @@ -1,4 +1,5 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using TUnit.Core.Helpers; namespace TUnit.Core.Tracking; @@ -11,6 +12,9 @@ internal class ObjectTracker(TrackableObjectGraphProvider trackableObjectGraphPr { private static readonly ConcurrentDictionary _trackedObjects = new(); + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Trackable object discovery uses reflection for property injection")] + #endif public void TrackObjects(TestContext testContext) { var alreadyTracked = testContext.TrackedObjects.SelectMany(x => x.Value).ToHashSet(); diff --git a/TUnit.Core/Tracking/TrackableObjectGraphProvider.cs b/TUnit.Core/Tracking/TrackableObjectGraphProvider.cs index 5e103f8086..9668371d53 100644 --- a/TUnit.Core/Tracking/TrackableObjectGraphProvider.cs +++ b/TUnit.Core/Tracking/TrackableObjectGraphProvider.cs @@ -1,4 +1,5 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using TUnit.Core.PropertyInjection; using TUnit.Core.StaticProperties; @@ -6,6 +7,9 @@ namespace TUnit.Core.Tracking; internal class TrackableObjectGraphProvider { + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Trackable object discovery uses reflection for property injection")] + #endif public ConcurrentDictionary> GetTrackableObjects(TestContext testContext) { var visitedObjects = testContext.TrackedObjects; @@ -63,6 +67,9 @@ public IEnumerable GetStaticPropertyTrackableObjects() } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Nested object tracking uses reflection for property discovery")] + #endif private void AddNestedTrackableObjects(object obj, ConcurrentDictionary> visitedObjects, int currentDepth) { var plan = PropertyInjectionCache.GetOrCreatePlan(obj.GetType()); diff --git a/TUnit.Engine/Building/Collectors/AotTestDataCollector.cs b/TUnit.Engine/Building/Collectors/AotTestDataCollector.cs index 90aa7ad316..ffa495e8b6 100644 --- a/TUnit.Engine/Building/Collectors/AotTestDataCollector.cs +++ b/TUnit.Engine/Building/Collectors/AotTestDataCollector.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; @@ -15,6 +15,12 @@ namespace TUnit.Engine.Building.Collectors; /// internal sealed class AotTestDataCollector : ITestDataCollector { + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2046", Justification = "AOT implementation uses source-generated metadata, not reflection")] + [UnconditionalSuppressMessage("AOT", "IL3051", Justification = "AOT implementation uses source-generated metadata, not dynamic code")] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Dynamic tests are optional and not used in AOT scenarios")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Dynamic tests are optional and not used in AOT scenarios")] + #endif public async Task> CollectTestsAsync(string testSessionId) { // Stream from all test sources @@ -31,6 +37,10 @@ public async Task> CollectTestsAsync(string testSessio return [..standardTestMetadatas, ..dynamicTestMetadatas]; } + #if NET6_0_OR_GREATER + [RequiresDynamicCode("Dynamic test conversion requires expression compilation")] + [RequiresUnreferencedCode("Method extraction from expressions uses reflection")] + #endif private async IAsyncEnumerable CollectDynamicTestsStreaming( string testSessionId, [EnumeratorCancellation] CancellationToken cancellationToken = default) @@ -76,8 +86,10 @@ private async IAsyncEnumerable CollectDynamicTestsStreaming( } } - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", - Justification = "Dynamic tests are opt-in and users are warned via RequiresDynamicCode on the method they call")] + #if NET6_0_OR_GREATER + [RequiresDynamicCode("Dynamic test conversion requires expression compilation")] + [RequiresUnreferencedCode("Method extraction from expressions uses reflection")] + #endif private async IAsyncEnumerable ConvertDynamicTestToMetadataStreaming( AbstractDynamicTest abstractDynamicTest, [EnumeratorCancellation] CancellationToken cancellationToken = default) @@ -94,7 +106,10 @@ private async IAsyncEnumerable ConvertDynamicTestToMetadataStreami } } - [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Dynamic tests require runtime compilation of lambda expressions and are not supported in native AOT scenarios.")] + #if NET6_0_OR_GREATER + [RequiresDynamicCode("Dynamic test metadata creation requires expression extraction and reflection")] + [RequiresUnreferencedCode("Method extraction from expressions uses reflection")] + #endif private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult result) { if (result.TestClassType == null || result.TestMethod == null) @@ -124,9 +139,7 @@ private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDisco return Task.FromResult(new AotDynamicTestMetadata(result) { TestName = testName, -#pragma warning disable IL2072 TestClassType = result.TestClassType, -#pragma warning restore IL2072 TestMethodName = methodInfo.Name, Dependencies = result.Attributes.OfType().Select(a => a.ToTestDependency()).ToArray(), DataSources = [], // Dynamic tests don't use data sources in the same way @@ -141,28 +154,14 @@ private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDisco GenericMethodInfo = null, GenericMethodTypeArguments = null, AttributeFactory = () => result.Attributes.ToArray(), -#pragma warning disable IL2072 PropertyInjections = PropertySourceRegistry.DiscoverInjectableProperties(result.TestClassType) -#pragma warning restore IL2072 }); } - [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Dynamic test instance creation requires Activator.CreateInstance and MakeGenericType which are not supported in native AOT scenarios.")] - [UnconditionalSuppressMessage("Trimming", - "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'System.Type.GetConstructors()'", - Justification = "AOT mode uses source-generated factories")] - [UnconditionalSuppressMessage("Trimming", - "IL2067:Target parameter does not satisfy annotation requirements", - Justification = "AOT mode uses source-generated factories")] - [UnconditionalSuppressMessage("Trimming", - "IL2072:Target method return value does not have matching annotations", - Justification = "AOT mode uses source-generated factories")] - [UnconditionalSuppressMessage("Trimming", - "IL2055:Call to 'MakeGenericType' can not be statically analyzed", - Justification = "Dynamic tests may use generic types")] - [UnconditionalSuppressMessage("AOT", - "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling", - Justification = "Dynamic tests require dynamic code generation")] + #if NET6_0_OR_GREATER + [RequiresDynamicCode("Dynamic instance creation uses Activator.CreateInstance and MakeGenericType")] + [RequiresUnreferencedCode("Dynamic type instantiation requires access to constructors")] + #endif private static Func? CreateAotDynamicInstanceFactory(Type testClass, object?[]? predefinedClassArgs) { // Check if we have predefined args to use as defaults @@ -191,7 +190,10 @@ private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDisco }; } - [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Dynamic test invocation requires LambdaExpression.Compile() which is not supported in native AOT scenarios.")] + #if NET6_0_OR_GREATER + [RequiresDynamicCode("Dynamic test invocation requires LambdaExpression.Compile")] + [RequiresUnreferencedCode("Expression compilation and MethodInfo.Invoke use reflection")] + #endif private static Func CreateAotDynamicTestInvoker(DynamicDiscoveryResult result) { return async (instance, args) => @@ -236,8 +238,9 @@ private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDisco }; } - [UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter argument does not satisfy \'DynamicallyAccessedMembersAttribute\' in call to target method. The return value of the source method does not have matching annotations.", - Justification = "We won't instantiate this since it failed")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Failed metadata creation accesses Type.Name and assembly info")] + #endif private static TestMetadata CreateFailedTestMetadataForDynamicSource(IDynamicTestSource source, Exception ex) { var testName = $"[DYNAMIC SOURCE FAILED] {source.GetType().Name}"; @@ -257,12 +260,9 @@ private static TestMetadata CreateFailedTestMetadataForDynamicSource(IDynamicTes }; } - [UnconditionalSuppressMessage("Trimming", - "IL2067:Target parameter does not satisfy annotation requirements", - Justification = "Dynamic test metadata creation")] - [UnconditionalSuppressMessage("Trimming", - "IL2072:Target method return value does not have matching annotations", - Justification = "Dynamic test metadata creation")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dummy metadata creation accesses type and assembly information")] + #endif private static MethodMetadata CreateDummyMethodMetadata(Type type, string methodName) { return new MethodMetadata diff --git a/TUnit.Engine/Building/Interfaces/ITestBuilder.cs b/TUnit.Engine/Building/Interfaces/ITestBuilder.cs index 3b9fb1dc90..7122df3f00 100644 --- a/TUnit.Engine/Building/Interfaces/ITestBuilder.cs +++ b/TUnit.Engine/Building/Interfaces/ITestBuilder.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using TUnit.Core; namespace TUnit.Engine.Building.Interfaces; @@ -22,6 +23,10 @@ internal interface ITestBuilder /// /// The test metadata with DataCombinationGenerator /// Collection of executable tests for all data combinations + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces")] + [RequiresDynamicCode("Hook registration may involve dynamic delegate creation")] + #endif Task> BuildTestsFromMetadataAsync(TestMetadata metadata); /// @@ -30,6 +35,10 @@ internal interface ITestBuilder /// The test metadata with DataCombinationGenerator /// Cancellation token /// Stream of executable tests for all data combinations + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces")] + [RequiresDynamicCode("Hook registration may involve dynamic delegate creation")] + #endif IAsyncEnumerable BuildTestsStreamingAsync( TestMetadata metadata, CancellationToken cancellationToken = default); diff --git a/TUnit.Engine/Building/Interfaces/ITestDataCollector.cs b/TUnit.Engine/Building/Interfaces/ITestDataCollector.cs index 77e7f28f43..da01199534 100644 --- a/TUnit.Engine/Building/Interfaces/ITestDataCollector.cs +++ b/TUnit.Engine/Building/Interfaces/ITestDataCollector.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using TUnit.Core; namespace TUnit.Engine.Building.Interfaces; @@ -11,5 +12,9 @@ internal interface ITestDataCollector /// Collects all test metadata from the configured source /// /// Collection of test metadata ready for processing + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Reflection-based implementation uses assembly scanning")] + [RequiresDynamicCode("Reflection-based implementation uses MakeGenericType")] + #endif Task> CollectTestsAsync(string testSessionId); } diff --git a/TUnit.Engine/Building/ReflectionMetadataBuilder.cs b/TUnit.Engine/Building/ReflectionMetadataBuilder.cs index 178c9f19f7..7bc5ac0edf 100644 --- a/TUnit.Engine/Building/ReflectionMetadataBuilder.cs +++ b/TUnit.Engine/Building/ReflectionMetadataBuilder.cs @@ -9,10 +9,9 @@ internal static class ReflectionMetadataBuilder /// /// Creates method metadata from reflection info with proper ReflectionInfo populated /// - [UnconditionalSuppressMessage("Trimming", "IL2067:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method", - Justification = "Parameter types discovered from MethodInfo.GetParameters() cannot be statically analyzed. Used for reflection-based and dynamic test discovery.")] - [UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations.", - Justification = "ParameterInfo.ParameterType cannot be annotated. For AOT scenarios, source-generated metadata is preferred.")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Method metadata creation uses reflection on parameters and types")] +#endif public static MethodMetadata CreateMethodMetadata( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors @@ -41,8 +40,9 @@ private static TypeReference CreateTypeReference(Type type) return TypeReference.CreateConcrete(type.AssemblyQualifiedName ?? type.FullName ?? type.Name); } - [UnconditionalSuppressMessage("Trimming", "IL2067:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method", - Justification = "ParameterMetadata constructor requires annotated types. Callers ensure types have required members preserved.")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Parameter metadata creation uses reflection")] +#endif private static ParameterMetadata CreateParameterMetadata( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods @@ -59,8 +59,9 @@ private static ParameterMetadata CreateParameterMetadata( }; } - [UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations.", - Justification = "Constructor parameter types from ParameterInfo cannot be annotated. Used for test class metadata creation.")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Class metadata creation uses reflection on constructors")] +#endif private static ClassMetadata CreateClassMetadata([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods diff --git a/TUnit.Engine/Building/TestBuilder.cs b/TUnit.Engine/Building/TestBuilder.cs index fbab7c4baa..28dcd603d1 100644 --- a/TUnit.Engine/Building/TestBuilder.cs +++ b/TUnit.Engine/Building/TestBuilder.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using TUnit.Core; using TUnit.Core.Enums; using TUnit.Core.Exceptions; @@ -18,15 +19,18 @@ internal sealed class TestBuilder : ITestBuilder private readonly IContextProvider _contextProvider; private readonly PropertyInjectionService _propertyInjectionService; private readonly DataSourceInitializer _dataSourceInitializer; + private readonly Discovery.IHookDiscoveryService _hookDiscoveryService; public TestBuilder( - string sessionId, - EventReceiverOrchestrator eventReceiverOrchestrator, + string sessionId, + EventReceiverOrchestrator eventReceiverOrchestrator, IContextProvider contextProvider, PropertyInjectionService propertyInjectionService, - DataSourceInitializer dataSourceInitializer) + DataSourceInitializer dataSourceInitializer, + Discovery.IHookDiscoveryService hookDiscoveryService) { _sessionId = sessionId; + _hookDiscoveryService = hookDiscoveryService; _eventReceiverOrchestrator = eventReceiverOrchestrator; _contextProvider = contextProvider; _propertyInjectionService = propertyInjectionService; @@ -103,6 +107,10 @@ private async Task CreateInstance(TestMetadata metadata, Type[] resolved } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Hook discovery uses reflection on methods and attributes")] + [RequiresDynamicCode("Hook registration may involve dynamic delegate creation")] + #endif public async Task> BuildTestsFromMetadataAsync(TestMetadata metadata) { var tests = new List(); @@ -143,14 +151,14 @@ public async Task> BuildTestsFromMetadataAsy ObjectBag = new Dictionary(), InitializedAttributes = attributes // Store the initialized attributes }; - + // Check for ClassConstructor attribute and set it early if present (reuse already created attributes) var classConstructorAttribute = attributes.OfType().FirstOrDefault(); if (classConstructorAttribute != null) { testBuilderContext.ClassConstructor = (IClassConstructor)Activator.CreateInstance(classConstructorAttribute.ClassConstructorType)!; } - + var contextAccessor = new TestBuilderContextAccessor(testBuilderContext); var classDataAttributeIndex = 0; @@ -252,7 +260,8 @@ public async Task> BuildTestsFromMetadataAsy { TestMetadata = metadata.MethodMetadata, Events = new TestContextEvents(), - ObjectBag = new Dictionary() + ObjectBag = new Dictionary(), + DataSourceAttribute = methodDataSource }; classData = DataUnwrapper.Unwrap(await classDataFactory() ?? []); @@ -366,7 +375,7 @@ public async Task> BuildTestsFromMetadataAsy DataSourceAttribute = contextAccessor.Current.DataSourceAttribute, // Copy any data source attribute InitializedAttributes = attributes // Pass the initialized attributes }; - + var test = await BuildTestAsync(metadata, testData, testSpecificContext); // If we have a basic skip reason, set it immediately @@ -447,8 +456,9 @@ private static Type[] TryInferClassGenericsFromMethodData(TestMetadata metadata, return resolvedTypes; } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("AOT", "IL2075:UnrecognizedReflectionPattern", - Justification = "Data sources require reflection to get method and parameter info")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Generic type inference uses reflection on data sources and parameters")] +#endif private static Type[] TryInferClassGenericsFromDataSources(TestMetadata metadata) { var genericClassType = metadata.TestClassType; @@ -599,6 +609,9 @@ private static Type[] TryInferClassGenericsFromDataSources(TestMetadata metadata return resolvedTypes; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif private async Task GetDataSourcesAsync(IDataSourceAttribute[] dataSources) { if (dataSources.Length == 0) @@ -619,6 +632,9 @@ private async Task GetDataSourcesAsync(IDataSourceAttrib /// Ensures a data source is initialized before use and returns data rows. /// This centralizes the initialization logic for all data source usage. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif private async IAsyncEnumerable>> GetInitializedDataRowsAsync( IDataSourceAttribute dataSource, DataGeneratorMetadata dataGeneratorMetadata) @@ -638,8 +654,16 @@ private async Task GetDataSourcesAsync(IDataSourceAttrib } } + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Hook discovery service handles mode-specific logic; reflection calls suppressed in AOT mode")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Hook discovery service handles mode-specific logic; dynamic code suppressed in AOT mode")] public async Task BuildTestAsync(TestMetadata metadata, TestData testData, TestBuilderContext testBuilderContext) { + // Discover instance hooks for closed generic types (no-op in source gen mode) + if (metadata.TestClassType is { IsGenericType: true, IsGenericTypeDefinition: false }) + { + _hookDiscoveryService.DiscoverInstanceHooksForType(metadata.TestClassType); + } + var testId = TestIdentifierService.GenerateTestId(metadata, testData); var context = await CreateTestContextAsync(testId, metadata, testData, testBuilderContext); @@ -698,11 +722,19 @@ public async Task BuildTestAsync(TestMetadata metadata, } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif private async ValueTask CreateTestContextAsync(string testId, TestMetadata metadata, TestData testData, TestBuilderContext testBuilderContext) { // Use attributes from context if available, or create new ones var attributes = testBuilderContext.InitializedAttributes ?? await InitializeAttributesAsync(metadata.AttributeFactory.Invoke()); + if (testBuilderContext.DataSourceAttribute != null && testBuilderContext.DataSourceAttribute is not NoDataSource) + { + attributes = [..attributes, (Attribute)testBuilderContext.DataSourceAttribute]; + } + var testDetails = new TestDetails { TestId = testId, @@ -735,6 +767,9 @@ private async ValueTask CreateTestContextAsync(string testId, TestM } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task InvokeDiscoveryEventReceiversAsync(TestContext context) { var discoveredContext = new DiscoveredTestContext( @@ -746,11 +781,17 @@ private async Task InvokeDiscoveryEventReceiversAsync(TestContext context) } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task CreateFailedTestForDataGenerationError(TestMetadata metadata, Exception exception) { return await CreateFailedTestForDataGenerationError(metadata, exception, new TestDataCombination()); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task CreateFailedTestForDataGenerationError(TestMetadata metadata, Exception exception, TestDataCombination combination) { var testId = TestIdentifierService.GenerateFailedTestId(metadata, combination); @@ -770,6 +811,9 @@ private async Task CreateFailedTestForDataGenerationErro }; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif private async Task CreateFailedTestDetails(TestMetadata metadata, string testId) { return new TestDetails @@ -790,6 +834,9 @@ private async Task CreateFailedTestDetails(TestMetadata metadata, s }; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif private async Task InitializeAttributesAsync(Attribute[] attributes) { // Initialize any attributes that need property injection or implement IAsyncInitializer @@ -802,7 +849,7 @@ private async Task InitializeAttributesAsync(Attribute[] attributes await _dataSourceInitializer.EnsureInitializedAsync(dataSource); } } - + return attributes; } @@ -824,12 +871,18 @@ private TestContext CreateFailedTestContext(TestMetadata metadata, TestDetails t + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task CreateFailedTestForInstanceDataSourceError(TestMetadata metadata, Exception exception) { var message = $"Failed to create instance for method data source expansion: {exception.Message}"; return await CreateFailedTestForDataGenerationError(metadata, exception); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task CreateFailedTestForClassDataSourceCircularDependency(TestMetadata metadata) { var instanceClassDataSources = metadata.ClassDataSources @@ -996,8 +1049,9 @@ private static bool IsDataCompatibleWithExpectedTypes(TestMetadata metadata, obj return null; } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("AOT", "IL2070:UnrecognizedReflectionPattern", - Justification = "Type checking at runtime is required for data source filtering")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Type compatibility checking uses reflection")] +#endif private static bool IsTypeCompatible(Type actualType, Type expectedType) { // Direct match @@ -1075,6 +1129,10 @@ internal class TestData public Type[] ResolvedMethodGenericArguments { get; set; } = Type.EmptyTypes; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + [RequiresDynamicCode("Hook registration may involve dynamic delegate creation")] + #endif public async IAsyncEnumerable BuildTestsStreamingAsync( TestMetadata metadata, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default) @@ -1107,7 +1165,7 @@ public async IAsyncEnumerable BuildTestsStreamingAsync( ObjectBag = new Dictionary(), InitializedAttributes = attributes // Store the initialized attributes }; - + // Check for ClassConstructor attribute and set it early if present // Look for any attribute that inherits from ClassConstructorAttribute // This handles both ClassConstructorAttribute and ClassConstructorAttribute @@ -1115,12 +1173,12 @@ public async IAsyncEnumerable BuildTestsStreamingAsync( .Where(a => a is ClassConstructorAttribute) .Cast() .FirstOrDefault(); - + if (classConstructorAttribute != null) { baseContext.ClassConstructor = (IClassConstructor)Activator.CreateInstance(classConstructorAttribute.ClassConstructorType)!; } - + var contextAccessor = new TestBuilderContextAccessor(baseContext); // Check for circular dependency @@ -1210,6 +1268,9 @@ public async IAsyncEnumerable BuildTestsStreamingAsync( } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Generic type inference uses reflection on data sources and parameters")] + #endif private Task CreateInstanceForMethodDataSources( TestMetadata metadata, int classDataAttributeIndex, int classDataLoopIndex, object?[] classData) { @@ -1252,6 +1313,10 @@ public async IAsyncEnumerable BuildTestsStreamingAsync( } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Hook discovery uses reflection on methods and attributes")] + [RequiresDynamicCode("Hook registration may involve dynamic delegate creation")] + #endif private async Task BuildSingleTestAsync( TestMetadata metadata, Func> classDataFactory, @@ -1266,7 +1331,7 @@ public async IAsyncEnumerable BuildTestsStreamingAsync( try { var classData = DataUnwrapper.Unwrap(await classDataFactory() ?? []); - + var methodData = DataUnwrapper.UnwrapWithTypes(await methodDataFactory() ?? [], metadata.MethodMetadata.Parameters); // Check data compatibility for generic methods diff --git a/TUnit.Engine/Building/TestBuilderPipeline.cs b/TUnit.Engine/Building/TestBuilderPipeline.cs index 39d0307a2c..935b949e29 100644 --- a/TUnit.Engine/Building/TestBuilderPipeline.cs +++ b/TUnit.Engine/Building/TestBuilderPipeline.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using EnumerableAsyncProcessor.Extensions; using TUnit.Core; using TUnit.Core.Interfaces; @@ -26,7 +27,7 @@ public TestBuilderPipeline( _contextProvider = contextBuilder; _eventReceiverOrchestrator = eventReceiverOrchestrator ?? throw new ArgumentNullException(nameof(eventReceiverOrchestrator)); } - + private TestBuilderContext CreateTestBuilderContext(TestMetadata metadata) { var testBuilderContext = new TestBuilderContext @@ -35,25 +36,27 @@ private TestBuilderContext CreateTestBuilderContext(TestMetadata metadata) Events = new TestContextEvents(), ObjectBag = new Dictionary() }; - + // Check for ClassConstructor attribute and set it early if present var attributes = metadata.AttributeFactory(); - + // Look for any attribute that inherits from ClassConstructorAttribute // This handles both ClassConstructorAttribute and ClassConstructorAttribute var classConstructorAttribute = attributes .Where(a => a is ClassConstructorAttribute) .Cast() .FirstOrDefault(); - + if (classConstructorAttribute != null) { testBuilderContext.ClassConstructor = (IClassConstructor)Activator.CreateInstance(classConstructorAttribute.ClassConstructorType)!; } - + return testBuilderContext; } + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Reflection mode is not used in AOT/trimmed scenarios")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Reflection mode is not used in AOT scenarios")] public async Task> BuildTestsAsync(string testSessionId) { var collectedMetadata = await _dataCollector.CollectTestsAsync(testSessionId).ConfigureAwait(false); @@ -64,6 +67,8 @@ public async Task> BuildTestsAsync(string te /// /// Streaming version that yields tests as they're built without buffering /// + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Reflection mode is not used in AOT/trimmed scenarios")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Reflection mode is not used in AOT scenarios")] public async Task> BuildTestsStreamingAsync( string testSessionId, CancellationToken cancellationToken = default) @@ -86,6 +91,8 @@ private async IAsyncEnumerable ToAsyncEnumerable(IEnumerable> BuildTestsFromMetadataAsync(IEnumerable testMetadata) { var testGroups = await testMetadata.SelectAsync(async metadata => @@ -111,6 +118,9 @@ public async Task> BuildTestsFromMetadataAsy return testGroups.SelectMany(x => x); } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task GenerateDynamicTests(TestMetadata metadata) { // Get attributes first @@ -141,14 +151,14 @@ private async Task GenerateDynamicTests(TestMetadata m }; var testId = TestIdentifierService.GenerateTestId(metadata, testData); - + var displayName = repeatCount > 0 ? $"{metadata.TestName} (Repeat {repeatIndex + 1}/{repeatCount + 1})" : metadata.TestName; // Get attributes first var attributes = metadata.AttributeFactory(); - + // Create TestDetails for dynamic tests var testDetails = new TestDetails { @@ -169,7 +179,7 @@ private async Task GenerateDynamicTests(TestMetadata m }; var testBuilderContext = CreateTestBuilderContext(metadata); - + var context = _contextProvider.CreateTestContext( metadata.TestName, metadata.TestClassType, @@ -200,6 +210,10 @@ private async Task GenerateDynamicTests(TestMetadata m /// /// Build tests from a single metadata item, yielding them as they're created /// + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Hook discovery uses reflection on methods and attributes")] + [RequiresDynamicCode("Hook registration may involve dynamic delegate creation")] + #endif private async IAsyncEnumerable BuildTestsFromSingleMetadataAsync(TestMetadata metadata) { TestMetadata resolvedMetadata; @@ -439,6 +453,9 @@ private AbstractExecutableTest CreateFailedTestForGenericResolutionError(TestMet }; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task InvokeDiscoveryEventReceiversAsync(TestContext context) { var discoveredContext = new DiscoveredTestContext( diff --git a/TUnit.Engine/Building/TestDataCollectorFactory.cs b/TUnit.Engine/Building/TestDataCollectorFactory.cs index 8ae93a709d..5ffdf78545 100644 --- a/TUnit.Engine/Building/TestDataCollectorFactory.cs +++ b/TUnit.Engine/Building/TestDataCollectorFactory.cs @@ -41,6 +41,10 @@ public static ITestDataCollector Create(bool? useSourceGeneration = null, Assemb /// Attempts AOT mode first, falls back to reflection if no source-generated tests found. /// This provides automatic mode selection for optimal performance and compatibility. /// + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Falls back to reflection mode if no source-generated tests found")] + [RequiresDynamicCode("Falls back to reflection mode if no source-generated tests found")] + #endif public static async Task CreateAutoDetectAsync(string testSessionId, Assembly[]? assembliesToScan = null) { // Try AOT mode first (check if any tests were registered) diff --git a/TUnit.Engine/Discovery/AsyncDataSourceHelper.cs b/TUnit.Engine/Discovery/AsyncDataSourceHelper.cs index 110bcee7f3..2d04375edb 100644 --- a/TUnit.Engine/Discovery/AsyncDataSourceHelper.cs +++ b/TUnit.Engine/Discovery/AsyncDataSourceHelper.cs @@ -7,6 +7,9 @@ namespace TUnit.Engine.Discovery; internal static class AsyncDataSourceHelper { /// Processes async generator items without evaluating them during discovery +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Typed placeholder creation uses reflection on generic types")] +#endif public static List ProcessAsyncGeneratorItemsForDiscovery(object? item) { var items = new List(); @@ -109,7 +112,9 @@ private static bool IsGenericFuncTask(object? item, out Type? resultType) return returnType; } - [UnconditionalSuppressMessage("Trimming", "IL2075:Target method return value does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Typed placeholder creation uses reflection on generic types")] +#endif private static AsyncDataSourcePlaceholder CreateTypedPlaceholder(object item, Type? resultType) { // Create a wrapper that preserves the typed factory diff --git a/TUnit.Engine/Discovery/ConstructorHelper.cs b/TUnit.Engine/Discovery/ConstructorHelper.cs index 04711440e0..89da30e5dd 100644 --- a/TUnit.Engine/Discovery/ConstructorHelper.cs +++ b/TUnit.Engine/Discovery/ConstructorHelper.cs @@ -12,8 +12,9 @@ internal static class ConstructorHelper /// /// Finds a suitable constructor for a test class, preferring ones marked with [TestConstructor] /// - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", - Justification = "Constructor discovery is required for test instantiation. AOT scenarios should use source-generated test metadata.")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Constructor discovery requires reflection on constructors and attributes")] +#endif public static ConstructorInfo? FindSuitableConstructor( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type testClass, Attribute[] classAttributes) @@ -35,12 +36,9 @@ internal static class ConstructorHelper /// /// Creates an instance of a test class with proper constructor parameter handling /// - [UnconditionalSuppressMessage("Trimming", "IL2067:Target type's member does not satisfy annotation requirements", - Justification = "Test class instantiation requires constructor access. AOT scenarios should use source-generated factories.")] - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", - Justification = "Dynamic property initialization is a fallback. AOT scenarios should use compile-time initialization.")] - [UnconditionalSuppressMessage("Trimming", "IL2072:Target method return value does not satisfy annotation requirements", - Justification = "Type flow in reflection mode cannot be statically analyzed. Use source generation for AOT.")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Test instance creation uses ConstructorInfo.Invoke and Activator.CreateInstance")] +#endif public static object? CreateTestClassInstanceWithConstructor( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type testClass, ConstructorInfo? constructor, @@ -115,8 +113,9 @@ internal static class ConstructorHelper /// /// Checks if a type has required properties that need initialization /// - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", - Justification = "Required property checking uses reflection. For AOT, ensure test classes don't use required properties or use source generation.")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Required property detection uses reflection on properties and attributes")] +#endif public static bool HasRequiredProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type) { // Check if the type itself has RequiredMemberAttribute (indicates it has required properties) @@ -133,10 +132,9 @@ public static bool HasRequiredProperties([DynamicallyAccessedMembers(Dynamically /// /// Tries to initialize required properties on an instance /// - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", - Justification = "Required property initialization needs reflection. AOT scenarios should initialize properties in constructors.")] - [UnconditionalSuppressMessage("Trimming", "IL2072:Target method return value does not satisfy annotation requirements", - Justification = "Property type information flows through reflection. Use explicit property initialization for AOT.")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Property initialization uses reflection on properties and their types")] +#endif public static void InitializeRequiredProperties( object instance, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type) @@ -231,8 +229,9 @@ public static void InitializeRequiredProperties( /// /// AOT-safe wrapper for Activator.CreateInstance with proper attribution /// - [UnconditionalSuppressMessage("Trimming", "IL2067:Target parameter does not satisfy annotation requirements", - Justification = "Parameterless constructor invocation with preserved type. For full AOT support, use source-generated factories.")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Activator.CreateInstance requires reflection")] +#endif private static object? CreateInstanceSafely([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) { return Activator.CreateInstance(type); diff --git a/TUnit.Engine/Discovery/GenericTestHelper.cs b/TUnit.Engine/Discovery/GenericTestHelper.cs index 8661373090..6162dcf532 100644 --- a/TUnit.Engine/Discovery/GenericTestHelper.cs +++ b/TUnit.Engine/Discovery/GenericTestHelper.cs @@ -11,8 +11,9 @@ internal static class GenericTestHelper /// /// Safely creates an instance of a test class, handling generic types /// - [UnconditionalSuppressMessage("Trimming", "IL2067:Target type's member does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Test instance creation uses reflection on constructors")] +#endif public static object? CreateTestClassInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicProperties)] Type testClass) { try @@ -53,9 +54,9 @@ internal static class GenericTestHelper /// /// Gets the method on the actual implementation class, handling inherited generic methods /// - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] - [UnconditionalSuppressMessage("Trimming", "IL2075:Target method return value does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] - [UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter argument does not satisfy annotation requirements", Justification = "BaseType access in reflection mode requires dynamic access")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Method lookup traverses type hierarchy using reflection")] +#endif public static MethodInfo? GetMethodOnImplementationType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type implementationType, string methodName, Type[] parameterTypes) { // First try exact match on implementation type @@ -163,7 +164,9 @@ public static bool IsInheritedFromGenericBase(MethodInfo method) /// /// Helper method to get method from type with proper AOT attribution /// - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Method lookup uses Type.GetMethod")] +#endif private static MethodInfo? GetMethodFromType( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type type, string methodName, diff --git a/TUnit.Engine/Discovery/IHookDiscoveryService.cs b/TUnit.Engine/Discovery/IHookDiscoveryService.cs new file mode 100644 index 0000000000..ac392694a3 --- /dev/null +++ b/TUnit.Engine/Discovery/IHookDiscoveryService.cs @@ -0,0 +1,17 @@ +namespace TUnit.Engine.Discovery; + +/// +/// Discovers hooks based on the execution mode (source generation or reflection). +/// +internal interface IHookDiscoveryService +{ + /// + /// Discovers and registers all hooks for the test session. + /// + void DiscoverHooks(); + + /// + /// Discovers instance hooks for a specific type (used for closed generic types). + /// + void DiscoverInstanceHooksForType(Type type); +} diff --git a/TUnit.Engine/Discovery/ReflectionBasedHookDiscoveryService.cs b/TUnit.Engine/Discovery/ReflectionBasedHookDiscoveryService.cs new file mode 100644 index 0000000000..673aac6bfe --- /dev/null +++ b/TUnit.Engine/Discovery/ReflectionBasedHookDiscoveryService.cs @@ -0,0 +1,31 @@ +using System.Diagnostics.CodeAnalysis; + +namespace TUnit.Engine.Discovery; + +/// +/// Hook discovery service for reflection mode. +/// Uses reflection to scan assemblies and discover hooks at runtime. +/// This implementation requires reflection and is NOT AOT-compatible. +/// +#if NET6_0_OR_GREATER +[RequiresUnreferencedCode("Hook discovery uses reflection to scan assemblies and types")] +[RequiresDynamicCode("Hook delegate creation requires dynamic code generation")] +#endif +internal sealed class ReflectionBasedHookDiscoveryService : IHookDiscoveryService +{ + /// + /// Discovers hooks using reflection by scanning all loaded assemblies. + /// + public void DiscoverHooks() + { + ReflectionHookDiscoveryService.DiscoverHooks(); + } + + /// + /// Discovers instance hooks for a specific closed generic type using reflection. + /// + public void DiscoverInstanceHooksForType(Type type) + { + ReflectionHookDiscoveryService.DiscoverInstanceHooksForType(type); + } +} diff --git a/TUnit.Engine/Discovery/ReflectionGenericTypeResolver.cs b/TUnit.Engine/Discovery/ReflectionGenericTypeResolver.cs index 3f011dd1fa..02dd343654 100644 --- a/TUnit.Engine/Discovery/ReflectionGenericTypeResolver.cs +++ b/TUnit.Engine/Discovery/ReflectionGenericTypeResolver.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using TUnit.Core; @@ -8,18 +8,14 @@ namespace TUnit.Engine.Discovery; /// /// Handles generic type resolution and instantiation for reflection-based test discovery /// -[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "Reflection mode cannot support trimming")] -[UnconditionalSuppressMessage("Trimming", "IL2055:Call to 'System.Type.MakeGenericType' can not be statically analyzed", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2065:Value passed to implicit 'this' parameter of method can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2067:Target parameter does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2075:'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "Reflection mode cannot support AOT")] internal static class ReflectionGenericTypeResolver { /// /// Determines generic type arguments from data row values /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Generic type argument determination uses reflection")] +#endif public static Type[]? DetermineGenericTypeArguments(Type genericTypeDefinition, object?[] dataRow) { #if NET @@ -82,6 +78,9 @@ internal static class ReflectionGenericTypeResolver /// /// Extracts generic type information including constraints /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Generic type info extraction uses reflection on type parameters")] +#endif public static GenericTypeInfo? ExtractGenericTypeInfo(Type testClass) { // Handle both generic type definitions and constructed generic types @@ -129,6 +128,9 @@ internal static class ReflectionGenericTypeResolver /// /// Extracts generic method information including parameter positions /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Generic method info extraction uses reflection on method parameters")] +#endif public static GenericMethodInfo? ExtractGenericMethodInfo(MethodInfo method) { if (!method.IsGenericMethodDefinition) @@ -177,6 +179,10 @@ internal static class ReflectionGenericTypeResolver /// /// Creates a concrete type from a generic type definition and validates the type arguments /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Concrete type creation uses Type.GetGenericArguments and reflection")] + [RequiresDynamicCode("Type construction uses MakeGenericType")] +#endif public static Type CreateConcreteType(Type genericTypeDefinition, Type[] typeArguments) { var genericParams = genericTypeDefinition.GetGenericArguments(); diff --git a/TUnit.Engine/Discovery/ReflectionHookDiscoveryService.cs b/TUnit.Engine/Discovery/ReflectionHookDiscoveryService.cs index 7ac904fb0e..02f5965d18 100644 --- a/TUnit.Engine/Discovery/ReflectionHookDiscoveryService.cs +++ b/TUnit.Engine/Discovery/ReflectionHookDiscoveryService.cs @@ -1,7 +1,8 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; +using Polyfills; using TUnit.Core; using TUnit.Core.Hooks; using TUnit.Core.Interfaces; @@ -11,20 +12,147 @@ namespace TUnit.Engine.Discovery; /// /// Discovers hooks at runtime using reflection for VB.NET and other languages that don't support source generation. /// -[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "Reflection mode cannot support trimming")] -[UnconditionalSuppressMessage("Trimming", "IL2055:Call to 'System.Type.MakeGenericType' can not be statically analyzed", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2067:Target parameter does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' requirements", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2075:'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "Reflection mode cannot support AOT")] +#if NET6_0_OR_GREATER +[RequiresUnreferencedCode("Uses reflection to access nested members")] +[RequiresDynamicCode("Uses reflection to access nested members")] +#endif internal sealed class ReflectionHookDiscoveryService { private static readonly ConcurrentDictionary _scannedAssemblies = new(); + private static readonly ConcurrentDictionary _registeredMethods = new(); private static int _registrationIndex = 0; + private static int _discoveryRunCount = 0; + + private static string GetMethodKey(MethodInfo method) + { + // Create a unique key for the method based on its signature + return $"{method.DeclaringType?.FullName}.{method.Name}({string.Join(",", method.GetParameters().Select(p => p.ParameterType.FullName))})"; + } + + private static void ClearSourceGeneratedHooks() + { + // Clear all hook collections to avoid duplicates when both + // source generation and reflection discovery run + Sources.BeforeTestSessionHooks.Clear(); + Sources.AfterTestSessionHooks.Clear(); + Sources.BeforeTestDiscoveryHooks.Clear(); + Sources.AfterTestDiscoveryHooks.Clear(); + Sources.BeforeEveryTestHooks.Clear(); + Sources.AfterEveryTestHooks.Clear(); + Sources.BeforeEveryClassHooks.Clear(); + Sources.AfterEveryClassHooks.Clear(); + Sources.BeforeEveryAssemblyHooks.Clear(); + Sources.AfterEveryAssemblyHooks.Clear(); + Sources.BeforeTestHooks.Clear(); + Sources.AfterTestHooks.Clear(); + Sources.BeforeClassHooks.Clear(); + Sources.AfterClassHooks.Clear(); + Sources.BeforeAssemblyHooks.Clear(); + Sources.AfterAssemblyHooks.Clear(); + } + + /// + /// Discovers and registers instance hooks for a specific closed generic type. + /// This is needed because closed generic types are created at runtime and don't appear in assembly.GetTypes(). + /// + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Hook discovery uses reflection on methods and attributes")] + [RequiresDynamicCode("Hook registration may involve dynamic delegate creation")] + #endif + public static void DiscoverInstanceHooksForType(Type closedGenericType) + { + if (SourceRegistrar.IsEnabled) + { + throw new InvalidOperationException("Cannot use reflection-based hook discovery when source generation is enabled"); + } + + if (closedGenericType == null || !closedGenericType.IsGenericType || closedGenericType.ContainsGenericParameters) + { + return; + } + // Check if we've already discovered hooks for this exact closed type + var methodKey = $"InstanceHooks:{closedGenericType.FullName}"; + if (!_registeredMethods.TryAdd(methodKey, true)) + { + return; // Already discovered + } + + // Build inheritance chain from base to derived to ensure hooks execute in correct order + var inheritanceChain = new List(); + var current = closedGenericType; + while (current != null && current != typeof(object)) + { + inheritanceChain.Insert(0, current); // Insert at front to get base-to-derived order + current = current.BaseType; + } + + // Discover hooks in each type in the inheritance chain, from base to derived + foreach (var typeInChain in inheritanceChain) + { + var methods = typeInChain.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .OrderBy(m => + { + // Get the minimum order from all hook attributes on this method + var beforeAttr = m.GetCustomAttribute(); + var afterAttr = m.GetCustomAttribute(); + var beforeEveryAttr = m.GetCustomAttribute(); + var afterEveryAttr = m.GetCustomAttribute(); + + var orders = new List(); + if (beforeAttr != null) orders.Add(beforeAttr.Order); + if (afterAttr != null) orders.Add(afterAttr.Order); + if (beforeEveryAttr != null) orders.Add(beforeEveryAttr.Order); + if (afterEveryAttr != null) orders.Add(afterEveryAttr.Order); + + return orders.Any() ? orders.Min() : 0; + }) + .ThenBy(m => m.MetadataToken) // Then sort by MetadataToken to preserve source file order + .ToArray(); + + foreach (var method in methods) + { + // Check for Before attributes + var beforeAttributes = method.GetCustomAttributes(false); + foreach (var attr in beforeAttributes) + { + if (attr.HookType == HookType.Test && !method.IsStatic) + { + RegisterInstanceBeforeHook(typeInChain, method, attr.Order); + } + } + + // Check for After attributes + var afterAttributes = method.GetCustomAttributes(false); + foreach (var attr in afterAttributes) + { + if (attr.HookType == HookType.Test && !method.IsStatic) + { + RegisterInstanceAfterHook(typeInChain, method, attr.Order); + } + } + } + } + } + + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Hook discovery scans assemblies and types using reflection")] + [RequiresDynamicCode("Hook delegate creation may require dynamic code generation")] + #endif public static void DiscoverHooks() { + // Prevent running hook discovery multiple times in the same process + // This can happen when both discovery and execution run in the same process + if (Interlocked.Increment(ref _discoveryRunCount) > 1) + { + return; + } + + // Clear source-generated hooks since we're discovering via reflection + // In reflection mode, source generation may have already populated Sources + // We need to clear them to avoid duplicates + ClearSourceGeneratedHooks(); + #if NET if (!RuntimeFeature.IsDynamicCodeSupported) { @@ -43,6 +171,9 @@ public static void DiscoverHooks() } } + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Assembly.GetReferencedAssemblies is reflection-based but safe for checking references")] + #endif private static bool ShouldScanAssembly(Assembly assembly) { if (_scannedAssemblies.ContainsKey(assembly)) @@ -95,6 +226,9 @@ private static bool ShouldScanAssembly(Assembly assembly) return referencesTUnit; } + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Types from Assembly.GetTypes() are used with appropriate annotations")] + #endif private static void DiscoverHooksInAssembly(Assembly assembly) { if (!_scannedAssemblies.TryAdd(assembly, true)) @@ -104,7 +238,13 @@ private static void DiscoverHooksInAssembly(Assembly assembly) try { - var types = assembly.GetTypes(); + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Assembly.GetTypes is reflection-based but required for hook discovery")] + [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Types from Assembly.GetTypes() are passed to annotated parameters")] + #endif + Type[] GetTypes() => assembly.GetTypes(); + + var types = GetTypes(); foreach (var type in types) { @@ -117,44 +257,92 @@ private static void DiscoverHooksInAssembly(Assembly assembly) } } - private static void DiscoverHooksInType(Type type, Assembly assembly) + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Types in inheritance chain preserve annotations from the annotated parameter")] + [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Types in inheritance chain preserve annotations from the annotated parameter")] + #endif + private static void DiscoverHooksInType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type, Assembly assembly) { - var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + // Build inheritance chain from base to derived to ensure hooks execute in correct order + var inheritanceChain = new List(); + Type? current = type; + while (current != null && current != typeof(object)) + { + inheritanceChain.Insert(0, current); // Insert at front to get base-to-derived order + current = current.BaseType; + } - foreach (var method in methods) + // Discover hooks in each type in the inheritance chain, from base to derived + foreach (var typeInChain in inheritanceChain) { - // Check for Before attributes - var beforeAttributes = method.GetCustomAttributes(false); - foreach (var attr in beforeAttributes) + // Use DeclaredOnly to get methods defined in this specific type, not inherited ones + var methods = typeInChain.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) + .OrderBy(m => + { + // Get the minimum order from all hook attributes on this method + var beforeAttr = m.GetCustomAttribute(); + var afterAttr = m.GetCustomAttribute(); + var beforeEveryAttr = m.GetCustomAttribute(); + var afterEveryAttr = m.GetCustomAttribute(); + + var orders = new List(); + if (beforeAttr != null) orders.Add(beforeAttr.Order); + if (afterAttr != null) orders.Add(afterAttr.Order); + if (beforeEveryAttr != null) orders.Add(beforeEveryAttr.Order); + if (afterEveryAttr != null) orders.Add(afterEveryAttr.Order); + + return orders.Any() ? orders.Min() : 0; + }) + .ThenBy(m => m.MetadataToken) // Then sort by MetadataToken to preserve source file order + .ToArray(); + + foreach (var method in methods) { - RegisterBeforeHook(type, method, attr, assembly); - } + // Check for Before attributes + var beforeAttributes = method.GetCustomAttributes(false); + foreach (var attr in beforeAttributes) + { + RegisterBeforeHook(typeInChain, method, attr, assembly); + } - // Check for After attributes - var afterAttributes = method.GetCustomAttributes(false); - foreach (var attr in afterAttributes) - { - RegisterAfterHook(type, method, attr, assembly); - } + // Check for After attributes + var afterAttributes = method.GetCustomAttributes(false); + foreach (var attr in afterAttributes) + { + RegisterAfterHook(typeInChain, method, attr, assembly); + } - // Check for BeforeEvery attributes - var beforeEveryAttributes = method.GetCustomAttributes(false); - foreach (var attr in beforeEveryAttributes) - { - RegisterBeforeEveryHook(type, method, attr, assembly); - } + // Check for BeforeEvery attributes + var beforeEveryAttributes = method.GetCustomAttributes(false); + foreach (var attr in beforeEveryAttributes) + { + RegisterBeforeEveryHook(typeInChain, method, attr, assembly); + } - // Check for AfterEvery attributes - var afterEveryAttributes = method.GetCustomAttributes(false); - foreach (var attr in afterEveryAttributes) - { - RegisterAfterEveryHook(type, method, attr, assembly); + // Check for AfterEvery attributes + var afterEveryAttributes = method.GetCustomAttributes(false); + foreach (var attr in afterEveryAttributes) + { + RegisterAfterEveryHook(typeInChain, method, attr, assembly); + } } } } - private static void RegisterBeforeHook(Type type, MethodInfo method, BeforeAttribute attr, Assembly assembly) + private static void RegisterBeforeHook( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type type, + MethodInfo method, + BeforeAttribute attr, + Assembly assembly) { + // Prevent duplicate registrations of the same method + var methodKey = GetMethodKey(method); + if (!_registeredMethods.TryAdd(methodKey, true)) + { + return; + } + var hookType = attr.HookType; var order = attr.Order; @@ -166,7 +354,7 @@ private static void RegisterBeforeHook(Type type, MethodInfo method, BeforeAttri var hook = new BeforeTestHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -190,7 +378,7 @@ private static void RegisterBeforeHook(Type type, MethodInfo method, BeforeAttri var sessionHook = new BeforeTestSessionHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -200,10 +388,13 @@ private static void RegisterBeforeHook(Type type, MethodInfo method, BeforeAttri Sources.BeforeTestSessionHooks.Add(sessionHook); break; case HookType.TestDiscovery: + // BeforeEvery(TestDiscovery) is treated the same as Before(TestDiscovery) + // The source generator ignores the "Every" suffix for TestDiscovery hooks + // Register it as a regular Before hook to match source-gen behavior var discoveryHook = new BeforeTestDiscoveryHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -215,8 +406,20 @@ private static void RegisterBeforeHook(Type type, MethodInfo method, BeforeAttri } } - private static void RegisterAfterHook(Type type, MethodInfo method, AfterAttribute attr, Assembly assembly) + private static void RegisterAfterHook( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type type, + MethodInfo method, + AfterAttribute attr, + Assembly assembly) { + // Prevent duplicate registrations of the same method + var methodKey = GetMethodKey(method); + if (!_registeredMethods.TryAdd(methodKey, true)) + { + return; + } + var hookType = attr.HookType; var order = attr.Order; @@ -228,7 +431,7 @@ private static void RegisterAfterHook(Type type, MethodInfo method, AfterAttribu var hook = new AfterTestHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -252,7 +455,7 @@ private static void RegisterAfterHook(Type type, MethodInfo method, AfterAttribu var sessionHook = new AfterTestSessionHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -262,23 +465,41 @@ private static void RegisterAfterHook(Type type, MethodInfo method, AfterAttribu Sources.AfterTestSessionHooks.Add(sessionHook); break; case HookType.TestDiscovery: - var discoveryHook = new AfterTestDiscoveryHookMethod + var discoveryMetadata = CreateMethodMetadata(type, method); + // Check if this hook is already registered (prevent duplicates) + if (!Sources.AfterTestDiscoveryHooks.Any(h => h.MethodInfo.Name == discoveryMetadata.Name && + h.MethodInfo.Type == discoveryMetadata.Type)) { - MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), - Order = order, - RegistrationIndex = Interlocked.Increment(ref _registrationIndex), - FilePath = "Unknown", - LineNumber = 0, - Body = CreateHookDelegate(type, method) - }; - Sources.AfterTestDiscoveryHooks.Add(discoveryHook); + var discoveryHook = new AfterTestDiscoveryHookMethod + { + MethodInfo = discoveryMetadata, + HookExecutor = GetHookExecutor(method), + Order = order, + RegistrationIndex = Interlocked.Increment(ref _registrationIndex), + FilePath = "Unknown", + LineNumber = 0, + Body = CreateHookDelegate(type, method) + }; + Sources.AfterTestDiscoveryHooks.Add(discoveryHook); + } break; } } - private static void RegisterBeforeEveryHook(Type type, MethodInfo method, BeforeEveryAttribute attr, Assembly assembly) + private static void RegisterBeforeEveryHook( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type type, + MethodInfo method, + BeforeEveryAttribute attr, + Assembly assembly) { + // Prevent duplicate registrations of the same method + var methodKey = GetMethodKey(method); + if (!_registeredMethods.TryAdd(methodKey, true)) + { + return; + } + var hookType = attr.HookType; var order = attr.Order; @@ -288,7 +509,7 @@ private static void RegisterBeforeEveryHook(Type type, MethodInfo method, Before var testHook = new BeforeTestHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -301,7 +522,7 @@ private static void RegisterBeforeEveryHook(Type type, MethodInfo method, Before var classHook = new BeforeClassHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -314,7 +535,7 @@ private static void RegisterBeforeEveryHook(Type type, MethodInfo method, Before var assemblyHook = new BeforeAssemblyHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -327,7 +548,7 @@ private static void RegisterBeforeEveryHook(Type type, MethodInfo method, Before var sessionHook = new BeforeTestSessionHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -340,7 +561,7 @@ private static void RegisterBeforeEveryHook(Type type, MethodInfo method, Before var discoveryHook = new BeforeTestDiscoveryHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -352,8 +573,20 @@ private static void RegisterBeforeEveryHook(Type type, MethodInfo method, Before } } - private static void RegisterAfterEveryHook(Type type, MethodInfo method, AfterEveryAttribute attr, Assembly assembly) + private static void RegisterAfterEveryHook( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type type, + MethodInfo method, + AfterEveryAttribute attr, + Assembly assembly) { + // Prevent duplicate registrations of the same method + var methodKey = GetMethodKey(method); + if (!_registeredMethods.TryAdd(methodKey, true)) + { + return; + } + var hookType = attr.HookType; var order = attr.Order; @@ -363,7 +596,7 @@ private static void RegisterAfterEveryHook(Type type, MethodInfo method, AfterEv var testHook = new AfterTestHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -376,7 +609,7 @@ private static void RegisterAfterEveryHook(Type type, MethodInfo method, AfterEv var classHook = new AfterClassHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -389,7 +622,7 @@ private static void RegisterAfterEveryHook(Type type, MethodInfo method, AfterEv var assemblyHook = new AfterAssemblyHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -402,7 +635,7 @@ private static void RegisterAfterEveryHook(Type type, MethodInfo method, AfterEv var sessionHook = new AfterTestSessionHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -412,29 +645,48 @@ private static void RegisterAfterEveryHook(Type type, MethodInfo method, AfterEv Sources.AfterTestSessionHooks.Add(sessionHook); break; case HookType.TestDiscovery: - var discoveryHook = new AfterTestDiscoveryHookMethod + // AfterEvery(TestDiscovery) is treated the same as After(TestDiscovery) + // The source generator ignores the "Every" suffix for TestDiscovery hooks + // Register it as a regular After hook to match source-gen behavior + var discoveryEveryMetadata = CreateMethodMetadata(type, method); + // Check if this hook is already registered (prevent duplicates) + if (!Sources.AfterTestDiscoveryHooks.Any(h => h.MethodInfo.Name == discoveryEveryMetadata.Name && + h.MethodInfo.Type == discoveryEveryMetadata.Type)) { - MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), - Order = order, - RegistrationIndex = Interlocked.Increment(ref _registrationIndex), - FilePath = "Unknown", - LineNumber = 0, - Body = CreateHookDelegate(type, method) - }; - Sources.AfterTestDiscoveryHooks.Add(discoveryHook); + var discoveryHook = new AfterTestDiscoveryHookMethod + { + MethodInfo = discoveryEveryMetadata, + HookExecutor = GetHookExecutor(method), + Order = order, + RegistrationIndex = Interlocked.Increment(ref _registrationIndex), + FilePath = "Unknown", + LineNumber = 0, + Body = CreateHookDelegate(type, method) + }; + Sources.AfterTestDiscoveryHooks.Add(discoveryHook); + } break; } } - private static void RegisterInstanceBeforeHook(Type type, MethodInfo method, int order) + private static void RegisterInstanceBeforeHook( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)] + Type type, + MethodInfo method, + int order) { + // Instance hooks on open generic types will be registered when closed types are discovered + if (type.ContainsGenericParameters) + { + return; + } + var bag = Sources.BeforeTestHooks.GetOrAdd(type, _ => new ConcurrentBag()); var hook = new InstanceHookMethod { InitClassType = type, MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), Body = CreateInstanceHookDelegate(type, method) @@ -442,14 +694,24 @@ private static void RegisterInstanceBeforeHook(Type type, MethodInfo method, int bag.Add(hook); } - private static void RegisterInstanceAfterHook(Type type, MethodInfo method, int order) + private static void RegisterInstanceAfterHook( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)] + Type type, + MethodInfo method, + int order) { + // Instance hooks on open generic types will be registered when closed types are discovered + if (type.ContainsGenericParameters) + { + return; + } + var bag = Sources.AfterTestHooks.GetOrAdd(type, _ => new ConcurrentBag()); var hook = new InstanceHookMethod { InitClassType = type, MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), Body = CreateInstanceHookDelegate(type, method) @@ -457,13 +719,17 @@ private static void RegisterInstanceAfterHook(Type type, MethodInfo method, int bag.Add(hook); } - private static void RegisterBeforeClassHook(Type type, MethodInfo method, int order) + private static void RegisterBeforeClassHook( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type type, + MethodInfo method, + int order) { var bag = Sources.BeforeClassHooks.GetOrAdd(type, _ => new ConcurrentBag()); var hook = new BeforeClassHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -473,13 +739,17 @@ private static void RegisterBeforeClassHook(Type type, MethodInfo method, int or bag.Add(hook); } - private static void RegisterAfterClassHook(Type type, MethodInfo method, int order) + private static void RegisterAfterClassHook( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type type, + MethodInfo method, + int order) { var bag = Sources.AfterClassHooks.GetOrAdd(type, _ => new ConcurrentBag()); var hook = new AfterClassHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -489,13 +759,18 @@ private static void RegisterAfterClassHook(Type type, MethodInfo method, int ord bag.Add(hook); } - private static void RegisterBeforeAssemblyHook(Assembly assembly, Type type, MethodInfo method, int order) + private static void RegisterBeforeAssemblyHook( + Assembly assembly, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type type, + MethodInfo method, + int order) { var bag = Sources.BeforeAssemblyHooks.GetOrAdd(assembly, _ => new ConcurrentBag()); var hook = new BeforeAssemblyHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -505,13 +780,18 @@ private static void RegisterBeforeAssemblyHook(Assembly assembly, Type type, Met bag.Add(hook); } - private static void RegisterAfterAssemblyHook(Assembly assembly, Type type, MethodInfo method, int order) + private static void RegisterAfterAssemblyHook( + Assembly assembly, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + Type type, + MethodInfo method, + int order) { var bag = Sources.AfterAssemblyHooks.GetOrAdd(assembly, _ => new ConcurrentBag()); var hook = new AfterAssemblyHookMethod { MethodInfo = CreateMethodMetadata(type, method), - HookExecutor = new DefaultHookExecutor(), + HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), FilePath = "Unknown", @@ -521,7 +801,13 @@ private static void RegisterAfterAssemblyHook(Assembly assembly, Type type, Meth bag.Add(hook); } - private static MethodMetadata CreateMethodMetadata(Type type, MethodInfo method) + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Parameter types in hooks are determined at runtime and cannot be statically analyzed")] + #endif + private static MethodMetadata CreateMethodMetadata( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)] + Type type, + MethodInfo method) { return new MethodMetadata { @@ -599,7 +885,7 @@ private static Func CreateIns }; } - private static Func CreateHookDelegate(Type type, MethodInfo method) + private static Func CreateHookDelegate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type, MethodInfo method) { return async (context, cancellationToken) => { @@ -643,9 +929,51 @@ private static Func CreateHookDelegate(Type } }; } + + /// + /// Extracts the HookExecutor from method attributes, or returns DefaultHookExecutor if not found + /// + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Attribute type reflection is required for hook executor discovery")] + [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Hook executor types are determined at runtime from attributes")] + #endif + private static IHookExecutor GetHookExecutor(MethodInfo method) + { + // Look for HookExecutorAttribute on the method + var hookExecutorAttr = method.GetCustomAttributes(true) + .FirstOrDefault(a => a.GetType().Name == "HookExecutorAttribute" || + a.GetType().BaseType?.Name == "HookExecutorAttribute"); + + if (hookExecutorAttr != null) + { + // Get the HookExecutorType property + var hookExecutorTypeProperty = hookExecutorAttr.GetType().GetProperty("HookExecutorType"); + if (hookExecutorTypeProperty != null) + { + var executorType = hookExecutorTypeProperty.GetValue(hookExecutorAttr) as Type; + if (executorType != null) + { + try + { + // Instantiate the executor + var executor = Activator.CreateInstance(executorType) as IHookExecutor; + if (executor != null) + { + return executor; + } + } + catch + { + // Fall back to default if instantiation fails + } + } + } + } + + return new DefaultHookExecutor(); + } } -// Default hook executor for reflection-discovered hooks internal class DefaultHookExecutor : IHookExecutor { public ValueTask ExecuteBeforeTestDiscoveryHook(MethodMetadata testMethod, BeforeTestDiscoveryContext context, Func action) diff --git a/TUnit.Engine/Discovery/ReflectionTestDataCollector.cs b/TUnit.Engine/Discovery/ReflectionTestDataCollector.cs index 4ed5ef2580..74cdcd195d 100644 --- a/TUnit.Engine/Discovery/ReflectionTestDataCollector.cs +++ b/TUnit.Engine/Discovery/ReflectionTestDataCollector.cs @@ -1,4 +1,4 @@ -using System.Buffers; +using System.Buffers; using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using System.Reflection; @@ -12,16 +12,13 @@ namespace TUnit.Engine.Discovery; /// Discovers tests at runtime using reflection with assembly scanning and caching -[UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "Reflection mode is not supported in single-file deployments")] -[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "Reflection mode cannot support trimming")] -[UnconditionalSuppressMessage("Trimming", "IL2055:Call to 'System.Type.MakeGenericType' can not be statically analyzed", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2060:Call to method can not be statically analyzed", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2067:Target parameter does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' requirements", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2075:'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("Trimming", "IL2077:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The source field does not have matching annotations.", Justification = "Reflection mode requires dynamic access")] -[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "Reflection mode cannot support AOT")] +[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Reflection mode isn't used in AOT scenarios")] +[UnconditionalSuppressMessage("Trimming", "IL2062", Justification = "Reflection mode isn't used in AOT scenarios")] +[UnconditionalSuppressMessage("Trimming", "IL2070", Justification = "Reflection mode isn't used in AOT scenarios")] +[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Reflection mode isn't used in AOT scenarios")] +[UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Reflection mode isn't used in AOT scenarios")] +[UnconditionalSuppressMessage("AOT", "IL3000", Justification = "Reflection mode isn't used in AOT scenarios")] +[UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Reflection mode isn't used in AOT scenarios")] internal sealed class ReflectionTestDataCollector : ITestDataCollector { private static readonly ConcurrentDictionary _scannedAssemblies = new(); @@ -53,6 +50,10 @@ public static void ClearCaches() } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Assembly scanning uses dynamic type discovery and reflection")] + [RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif private async Task> ProcessAssemblyAsync(Assembly assembly, SemaphoreSlim semaphore) { await semaphore.WaitAsync().ConfigureAwait(false); @@ -80,6 +81,10 @@ private async Task> ProcessAssemblyAsync(Assembly assembly, S } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Assembly scanning uses dynamic type discovery and reflection")] + [RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif public async Task> CollectTestsAsync(string testSessionId) { #if NET @@ -140,6 +145,10 @@ public async Task> CollectTestsAsync(string testSessio } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Reflection-based test discovery requires dynamic access to types, methods, and attributes")] + [RequiresDynamicCode("Test discovery uses MakeGenericType and dynamic code generation")] + #endif public async IAsyncEnumerable CollectTestsStreamingAsync( string testSessionId, [EnumeratorCancellation] CancellationToken cancellationToken = default) @@ -184,7 +193,7 @@ public async IAsyncEnumerable CollectTestsStreamingAsync( } } - private static IEnumerable GetAllTestMethods(Type type) + private static IEnumerable GetAllTestMethods([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { return _typeMethodsCache.GetOrAdd(type, static t => { @@ -327,6 +336,10 @@ private static bool ShouldScanAssembly(Assembly assembly) return true; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Assembly scanning uses dynamic type discovery and reflection")] + [RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif private static async Task> DiscoverTestsInAssembly(Assembly assembly) { var discoveredTests = new List(100); @@ -425,6 +438,10 @@ private static async Task> DiscoverTestsInAssembly(Assembly a return discoveredTests; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Assembly scanning uses dynamic type discovery and reflection")] + [RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif private static async IAsyncEnumerable DiscoverTestsInAssemblyStreamingAsync( Assembly assembly, [EnumeratorCancellation] CancellationToken cancellationToken = default) @@ -564,6 +581,10 @@ private static async IAsyncEnumerable DiscoverTestsInAssemblyStrea } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Generic type resolution requires reflection and dynamic type creation")] + [RequiresDynamicCode("Generic type instantiation uses MakeGenericType")] + #endif private static async Task> DiscoverGenericTests(Type genericTypeDefinition) { var discoveredTests = new List(100); @@ -653,6 +674,10 @@ private static async Task> DiscoverGenericTests(Type genericT return discoveredTests; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Generic type resolution requires reflection and dynamic type creation")] + [RequiresDynamicCode("Generic type instantiation uses MakeGenericType")] + #endif private static async IAsyncEnumerable DiscoverGenericTestsStreamingAsync( Type genericTypeDefinition, [EnumeratorCancellation] CancellationToken cancellationToken = default) @@ -837,7 +862,15 @@ private static int CalculateInheritanceDepth(Type testClass, MethodInfo testMeth return depth; } - private static Task BuildTestMetadata(Type testClass, MethodInfo testMethod, object?[]? classData = null) + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "BuildTestMetadata calls other reflection methods that are already annotated")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "BuildTestMetadata calls CreateInstanceFactory and CreateTestInvoker which are properly annotated")] + #endif + private static Task BuildTestMetadata( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] + Type testClass, + MethodInfo testMethod, + object?[]? classData = null) { var testName = GenerateTestName(testClass, testMethod); @@ -925,6 +958,10 @@ private static string GenerateTestName(Type testClass, MethodInfo testMethod) + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Instance creation uses reflection and Activator.CreateInstance")] + [RequiresDynamicCode("Generic type instantiation uses MakeGenericType and Activator")] + #endif private static Func CreateInstanceFactory([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type testClass) { // For generic types, we need to handle MakeGenericType @@ -984,6 +1021,10 @@ private static string GenerateTestName(Type testClass, MethodInfo testMethod) } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Test invocation uses reflection and MethodInfo.Invoke")] + [RequiresDynamicCode("Generic method instantiation uses MakeGenericMethod")] + #endif private static Func CreateTestInvoker(Type testClass, MethodInfo testMethod) { return CreateReflectionTestInvoker(testClass, testMethod); @@ -1000,7 +1041,7 @@ private static bool IsAsyncMethod(MethodInfo method) method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)); } - private static bool IsCompilerGenerated(Type type) + private static bool IsCompilerGenerated([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { // If the type is not marked as compiler-generated, it's not compiler-generated if (!type.IsDefined(typeof(CompilerGeneratedAttribute), inherit: false)) @@ -1013,7 +1054,7 @@ private static bool IsCompilerGenerated(Type type) return !HasTestMethods(type); } - private static bool HasTestMethods(Type type) + private static bool HasTestMethods([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { try { @@ -1060,6 +1101,10 @@ private static ParameterInfo[] GetParametersWithoutCancellationToken(MethodInfo return method.GetCustomAttribute()?.Line; } + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "This is only called in error cases for assembly scanning failures")] + [UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "Methods are called directly, not via reflection")] + #endif private static TestMetadata CreateFailedTestMetadataForAssembly(Assembly assembly, Exception ex) { var testName = $"[ASSEMBLY SCAN FAILED] {assembly.GetName().Name}"; @@ -1091,7 +1136,14 @@ private static TestMetadata CreateFailedTestMetadataForAssembly(Assembly assembl }; } - private static TestMetadata CreateFailedTestMetadata(Type type, MethodInfo method, Exception ex) + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Failed test metadata creation uses ReflectionMetadataBuilder")] + #endif + private static TestMetadata CreateFailedTestMetadata( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)] + Type type, + MethodInfo method, + Exception ex) { var testName = $"[DISCOVERY FAILED] {type.FullName}.{method.Name}"; var displayName = $"{testName} - {ex.Message}"; @@ -1120,7 +1172,10 @@ private static TestMetadata CreateFailedTestMetadata(Type type, MethodInfo metho } - private static MethodMetadata CreateDummyMethodMetadata(Type type, string methodName) + private static MethodMetadata CreateDummyMethodMetadata( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)] + Type type, + string methodName) { return new MethodMetadata { @@ -1182,6 +1237,10 @@ public override Func /// Creates a reflection-based instance factory with proper AOT attribution /// + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Reflection-based factory uses ConstructorInfo.Invoke")] + [RequiresDynamicCode("Dynamic constructor invocation may require runtime code generation")] + #endif private static Func CreateReflectionInstanceFactory(ConstructorInfo ctor) { var isPrepared = false; @@ -1244,7 +1303,7 @@ public override Func /// Infers generic type mappings from parameter and argument types /// - private static void InferGenericTypeMapping(Type paramType, Type argType, Dictionary typeMapping) + private static void InferGenericTypeMapping(Type paramType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type argType, Dictionary typeMapping) { // Direct generic parameter if (paramType.IsGenericParameter) @@ -1332,7 +1391,7 @@ private static void InferGenericTypeMapping(Type paramType, Type argType, Dictio /// /// Checks if the argument type is compatible with the parameter type through covariance /// - private static bool IsCovariantCompatible(Type paramType, Type argType) + private static bool IsCovariantCompatible(Type paramType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type argType) { // Only check for generic interface covariance if (!paramType.IsInterface || !paramType.IsGenericType) @@ -1382,6 +1441,9 @@ private static bool IsCovariantCompatible(Type paramType, Type argType) /// /// Creates a reflection-based test invoker with proper AOT attribution /// + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2060", Justification = "Reflection-based test invoker is only used in reflection mode, not in AOT")] + #endif private static Func CreateReflectionTestInvoker(Type testClass, MethodInfo testMethod) { var isPrepared = false; @@ -1590,6 +1652,10 @@ private static bool IsCovariantCompatible(Type paramType, Type argType) }; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dynamic test discovery uses reflection to scan assemblies and types")] + [RequiresDynamicCode("Dynamic test builders may use expression compilation")] + #endif private async Task> DiscoverDynamicTests(string testSessionId) { var dynamicTests = new List(50); @@ -1679,6 +1745,10 @@ private async Task> DiscoverDynamicTests(string testSessionId return dynamicTests; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dynamic test discovery uses reflection to scan assemblies and types")] + [RequiresDynamicCode("Dynamic test builders may use expression compilation")] + #endif private async IAsyncEnumerable DiscoverDynamicTestsStreamingAsync( string testSessionId, [EnumeratorCancellation] CancellationToken cancellationToken = default) @@ -1740,6 +1810,10 @@ private async IAsyncEnumerable DiscoverDynamicTestsStreamingAsync( } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dynamic test builder execution uses Activator.CreateInstance and MethodInfo.Invoke")] + [RequiresDynamicCode("Expression compilation is used for dynamic tests")] + #endif private async Task> ExecuteDynamicTestBuilder(Type testClass, MethodInfo builderMethod, string testSessionId) { var dynamicTests = new List(50); @@ -1771,6 +1845,10 @@ private async Task> ExecuteDynamicTestBuilder(Type testClass, return dynamicTests; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dynamic test metadata creation uses reflection")] + [RequiresDynamicCode("Expression compilation is used for dynamic test invocation")] + #endif private async Task> ConvertDynamicTestToMetadata(AbstractDynamicTest abstractDynamicTest) { var testMetadataList = new List(); @@ -1787,6 +1865,10 @@ private async Task> ConvertDynamicTestToMetadata(AbstractDyna return testMetadataList; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dynamic test builder execution uses Activator.CreateInstance and MethodInfo.Invoke")] + [RequiresDynamicCode("Expression compilation is used for dynamic tests")] + #endif private async IAsyncEnumerable ExecuteDynamicTestBuilderStreamingAsync( Type testClass, MethodInfo builderMethod, string testSessionId, [EnumeratorCancellation] CancellationToken cancellationToken = default) @@ -1868,6 +1950,10 @@ private async IAsyncEnumerable ExecuteDynamicTestBuilderStreamingA } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dynamic test metadata creation uses reflection")] + [RequiresDynamicCode("Expression compilation is used for dynamic test invocation")] + #endif private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult result) { if (result.TestClassType == null || result.TestMethod == null) @@ -1918,6 +2004,10 @@ private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDisco return Task.FromResult(metadata); } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dynamic instance factory uses Activator.CreateInstance")] + [RequiresDynamicCode("Generic type construction uses MakeGenericType")] + #endif private static Func CreateDynamicInstanceFactory(Type testClass, object?[]? predefinedClassArgs) { // For dynamic tests, we always use the predefined args (or empty array if null) @@ -1944,6 +2034,10 @@ private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDisco }; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Dynamic test invoker uses expression compilation and reflection")] + [RequiresDynamicCode("LambdaExpression.Compile requires dynamic code generation")] + #endif private static Func CreateDynamicTestInvoker(DynamicDiscoveryResult result) { return async (instance, args) => @@ -1987,6 +2081,10 @@ private Task CreateMetadataFromDynamicDiscoveryResult(DynamicDisco }; } + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2077", Justification = "This is only called in error cases for dynamic source failures")] + [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Object.GetType() doesn't preserve annotations, but this is for error reporting only")] + #endif private static TestMetadata CreateFailedTestMetadataForDynamicSource(IDynamicTestSource source, Exception ex) { var testName = $"[DYNAMIC SOURCE FAILED] {source.GetType().Name}"; @@ -2007,7 +2105,14 @@ private static TestMetadata CreateFailedTestMetadataForDynamicSource(IDynamicTes }; } - private static TestMetadata CreateFailedTestMetadataForDynamicBuilder(Type type, MethodInfo method, Exception ex) + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "This is only called in error cases for dynamic builder failures")] + #endif + private static TestMetadata CreateFailedTestMetadataForDynamicBuilder( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)] + Type type, + MethodInfo method, + Exception ex) { var testName = $"[DYNAMIC BUILDER FAILED] {type.FullName}.{method.Name}"; var displayName = $"{testName} - {ex.Message}"; @@ -2050,10 +2155,14 @@ private static TestMetadata CreateFailedTestMetadataForDynamicTest(DynamicDiscov private sealed class DynamicReflectionTestMetadata : TestMetadata, IDynamicTestMetadata { private readonly DynamicDiscoveryResult _dynamicResult; + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] private readonly Type _testClass; private readonly MethodInfo _testMethod; - public DynamicReflectionTestMetadata(Type testClass, MethodInfo testMethod, DynamicDiscoveryResult dynamicResult) + public DynamicReflectionTestMetadata( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type testClass, + MethodInfo testMethod, + DynamicDiscoveryResult dynamicResult) { _testClass = testClass; _testMethod = testMethod; diff --git a/TUnit.Engine/Discovery/SourceGenHookDiscoveryService.cs b/TUnit.Engine/Discovery/SourceGenHookDiscoveryService.cs new file mode 100644 index 0000000000..e237c8a5bf --- /dev/null +++ b/TUnit.Engine/Discovery/SourceGenHookDiscoveryService.cs @@ -0,0 +1,27 @@ +namespace TUnit.Engine.Discovery; + +/// +/// Hook discovery service for source generation mode. +/// In this mode, hooks are discovered at compile time via source generators, so no runtime discovery is needed. +/// This implementation is AOT-compatible and does not use reflection. +/// +internal sealed class SourceGenHookDiscoveryService : IHookDiscoveryService +{ + /// + /// No-op implementation. Hooks are already registered via source generation. + /// + public void DiscoverHooks() + { + // Hooks are already discovered and registered at compile time via source generation + // No runtime discovery needed + } + + /// + /// No-op implementation. Instance hooks for generic types are already registered via source generation. + /// + public void DiscoverInstanceHooksForType(Type type) + { + // Hooks are already discovered and registered at compile time via source generation + // No runtime discovery needed for closed generic types + } +} diff --git a/TUnit.Engine/Discovery/TestInstanceHelper.cs b/TUnit.Engine/Discovery/TestInstanceHelper.cs index 61f436433c..f4f33b9542 100644 --- a/TUnit.Engine/Discovery/TestInstanceHelper.cs +++ b/TUnit.Engine/Discovery/TestInstanceHelper.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using TUnit.Core; @@ -12,8 +12,9 @@ internal static class TestInstanceHelper /// /// Creates a test instance with data from class data sources /// - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] - [UnconditionalSuppressMessage("Trimming", "IL2067:Target type's member does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Test instance creation uses reflection on constructors and properties")] + #endif public static object? CreateTestInstanceWithData( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties)] Type testClass, IDataSourceAttribute[]? classDataSources) @@ -133,7 +134,9 @@ internal static class TestInstanceHelper /// /// Creates test instance for inherited test classes /// - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Inherited test instance creation uses reflection on type hierarchy")] + #endif public static object? CreateInheritedTestInstance( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties)] Type testClass) { @@ -182,9 +185,9 @@ private sealed class DiscoveryPlaceholderInstance public override string ToString() => ""; } - [UnconditionalSuppressMessage("Trimming", "IL2070:Target method does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] - [UnconditionalSuppressMessage("Trimming", "IL2067:Target type's member does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] - [UnconditionalSuppressMessage("Trimming", "IL2072:Target method return value does not satisfy annotation requirements", Justification = "Reflection mode requires dynamic access")] + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Property initialization traverses type hierarchy using reflection")] + #endif private static void InitializeInheritedRequiredProperties(object instance, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type) { var currentType = type; @@ -194,4 +197,4 @@ private static void InitializeInheritedRequiredProperties(object instance, [Dyna currentType = currentType.BaseType; } } -} \ No newline at end of file +} diff --git a/TUnit.Engine/Framework/IRequestHandler.cs b/TUnit.Engine/Framework/IRequestHandler.cs index ff653f3168..0a6f8cf4c4 100644 --- a/TUnit.Engine/Framework/IRequestHandler.cs +++ b/TUnit.Engine/Framework/IRequestHandler.cs @@ -8,5 +8,9 @@ namespace TUnit.Engine.Framework; /// internal interface IRequestHandler { + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif Task HandleRequestAsync(TestExecutionRequest request, TUnitServiceProvider serviceProvider, ExecuteRequestContext context, ITestExecutionFilter? testExecutionFilter); } diff --git a/TUnit.Engine/Framework/TUnitServiceProvider.cs b/TUnit.Engine/Framework/TUnitServiceProvider.cs index 7f7fefa267..23b0a2329d 100644 --- a/TUnit.Engine/Framework/TUnitServiceProvider.cs +++ b/TUnit.Engine/Framework/TUnitServiceProvider.cs @@ -1,3 +1,5 @@ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using Microsoft.Testing.Platform.Capabilities.TestFramework; using Microsoft.Testing.Platform.CommandLine; using Microsoft.Testing.Platform.Extensions; @@ -54,6 +56,8 @@ public ITestExecutionFilter? Filter public ObjectRegistrationService ObjectRegistrationService { get; } public bool AfterSessionHooksFailed { get; set; } + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Reflection mode is not used in AOT/trimmed scenarios")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Reflection mode is not used in AOT scenarios")] public TUnitServiceProvider(IExtension extension, ExecuteRequestContext context, ITestExecutionFilter? filter, @@ -74,7 +78,21 @@ public TUnitServiceProvider(IExtension extension, VerbosityService = Register(new VerbosityService(CommandLineOptions)); DiscoveryDiagnostics.Initialize(VerbosityService); - Initializer = new TUnitInitializer(CommandLineOptions); + // Determine execution mode early to create appropriate services + var useSourceGeneration = SourceRegistrar.IsEnabled = GetUseSourceGeneration(CommandLineOptions); + + // Create and register mode-specific hook discovery service + IHookDiscoveryService hookDiscoveryService; + if (useSourceGeneration) + { + hookDiscoveryService = Register(new SourceGenHookDiscoveryService()); + } + else + { + hookDiscoveryService = Register(new ReflectionBasedHookDiscoveryService()); + } + + Initializer = new TUnitInitializer(CommandLineOptions, hookDiscoveryService); Logger = Register(new TUnitFrameworkLogger( extension, @@ -131,17 +149,23 @@ public TUnitServiceProvider(IExtension extension, var testContextRestorer = Register(new TestContextRestorer()); var testMethodInvoker = Register(new TestMethodInvoker()); - var useSourceGeneration = GetUseSourceGeneration(CommandLineOptions); -#pragma warning disable IL2026 // Using member which has 'RequiresUnreferencedCodeAttribute' -#pragma warning disable IL3050 // Using member which has 'RequiresDynamicCodeAttribute' - ITestDataCollector dataCollector = useSourceGeneration - ? new AotTestDataCollector() - : new ReflectionTestDataCollector(); -#pragma warning restore IL3050 -#pragma warning restore IL2026 + // Use the mode already determined earlier + ITestDataCollector dataCollector; + IStaticPropertyInitializer staticPropertyInitializer; + + if (useSourceGeneration) + { + dataCollector = new AotTestDataCollector(); + staticPropertyInitializer = new SourceGenStaticPropertyInitializer(Logger); + } + else + { + dataCollector = new ReflectionTestDataCollector(); + staticPropertyInitializer = new ReflectionStaticPropertyInitializer(Logger); + } var testBuilder = Register( - new TestBuilder(TestSessionId, EventReceiverOrchestrator, ContextProvider, PropertyInjectionService, DataSourceInitializer)); + new TestBuilder(TestSessionId, EventReceiverOrchestrator, ContextProvider, PropertyInjectionService, DataSourceInitializer, hookDiscoveryService)); TestBuilderPipeline = Register( new TestBuilderPipeline( @@ -193,7 +217,7 @@ public TUnitServiceProvider(IExtension extension, Logger, ParallelLimitLockProvider)); - var staticPropertyInitializer = Register(new Services.StaticPropertyHandler(Logger, objectTracker, trackableObjectGraphProvider, disposer)); + var staticPropertyHandler = Register(new Services.StaticPropertyHandler(Logger, objectTracker, trackableObjectGraphProvider, disposer)); var testScheduler = Register(new TestScheduler( Logger, @@ -206,7 +230,7 @@ public TUnitServiceProvider(IExtension extension, circularDependencyDetector, constraintKeyScheduler, hookExecutor, - staticPropertyInitializer)); + staticPropertyHandler)); TestSessionCoordinator = Register(new TestSessionCoordinator(EventReceiverOrchestrator, Logger, @@ -214,7 +238,8 @@ public TUnitServiceProvider(IExtension extension, serviceProvider: this, ContextProvider, lifecycleCoordinator, - MessageBus)); + MessageBus, + staticPropertyInitializer)); Register(new TestRegistry(TestBuilderPipeline, testCoordinator, TestSessionId, CancellationToken.Token)); @@ -250,6 +275,13 @@ private T Register(T service) where T : class private static bool GetUseSourceGeneration(ICommandLineOptions commandLineOptions) { +#if NET + if (!RuntimeFeature.IsDynamicCodeSupported) + { + return true; // Force source generation on AOT platforms + } +#endif + if (commandLineOptions.TryGetOptionArgumentList(ReflectionModeCommandProvider.ReflectionMode, out _)) { return false; // Reflection mode explicitly requested diff --git a/TUnit.Engine/Framework/TUnitTestFramework.cs b/TUnit.Engine/Framework/TUnitTestFramework.cs index 71eafd8e8b..1a32e91018 100644 --- a/TUnit.Engine/Framework/TUnitTestFramework.cs +++ b/TUnit.Engine/Framework/TUnitTestFramework.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using Microsoft.Testing.Platform.Capabilities.TestFramework; using Microsoft.Testing.Platform.Extensions; using Microsoft.Testing.Platform.Extensions.Messages; @@ -41,6 +42,12 @@ public Task CreateTestSessionAsync(CreateTestSessionCon return Task.FromResult(new CreateTestSessionResult { IsSuccess = true }); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test data collector selection may use reflection-based discovery")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Reflection mode test discovery uses dynamic code generation")] + [UnconditionalSuppressMessage("Trimming", "IL2046", Justification = "Reflection mode is not used in AOT/trimmed scenarios")] + [UnconditionalSuppressMessage("AOT", "IL3051", Justification = "Reflection mode is not used in AOT scenarios")] + #endif public async Task ExecuteRequestAsync(ExecuteRequestContext context) { try @@ -104,6 +111,10 @@ public async Task CloseTestSessionAsync(CloseTestSession return new CloseTestSessionResult { IsSuccess = isSuccess }; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test data collector selection may use reflection-based discovery")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Reflection mode test discovery uses dynamic code generation")] + #endif private TUnitServiceProvider GetOrCreateServiceProvider(ExecuteRequestContext context) { return _serviceProvidersPerSession.GetOrAdd( diff --git a/TUnit.Engine/Framework/TestRequestHandler.cs b/TUnit.Engine/Framework/TestRequestHandler.cs index 38e447c779..5adc08ee29 100644 --- a/TUnit.Engine/Framework/TestRequestHandler.cs +++ b/TUnit.Engine/Framework/TestRequestHandler.cs @@ -7,6 +7,10 @@ namespace TUnit.Engine.Framework; internal sealed class TestRequestHandler : IRequestHandler { + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif public async Task HandleRequestAsync(TestExecutionRequest request, TUnitServiceProvider serviceProvider, ExecuteRequestContext context, ITestExecutionFilter? testExecutionFilter) { switch (request) @@ -27,6 +31,10 @@ public async Task HandleRequestAsync(TestExecutionRequest request, TUnitServiceP } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif private async Task HandleDiscoveryRequestAsync( TUnitServiceProvider serviceProvider, ExecuteRequestContext context, @@ -51,6 +59,10 @@ private async Task HandleDiscoveryRequestAsync( } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif private async Task HandleRunRequestAsync( TUnitServiceProvider serviceProvider, RunTestExecutionRequest request, diff --git a/TUnit.Engine/Helpers/DisplayNameBuilder.cs b/TUnit.Engine/Helpers/DisplayNameBuilder.cs index 05a373f87d..b3df683bc8 100644 --- a/TUnit.Engine/Helpers/DisplayNameBuilder.cs +++ b/TUnit.Engine/Helpers/DisplayNameBuilder.cs @@ -114,8 +114,9 @@ private static string GetSimpleTypeName(Type type) /// /// Resolves the actual value from a data source factory result /// - [UnconditionalSuppressMessage("AOT", "IL2075:Target method return value does not satisfy annotation requirements.", - Justification = "This is for reflection mode which doesn't support AOT")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Data source value resolution may use reflection")] +#endif public static async Task ResolveDataSourceValue(object? value) { if (value == null) diff --git a/TUnit.Engine/Interfaces/IHookCollectionService.cs b/TUnit.Engine/Interfaces/IHookCollectionService.cs index 3b9d4a96f8..589a9ceb54 100644 --- a/TUnit.Engine/Interfaces/IHookCollectionService.cs +++ b/TUnit.Engine/Interfaces/IHookCollectionService.cs @@ -5,9 +5,21 @@ namespace TUnit.Engine.Interfaces; internal interface IHookCollectionService { + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif ValueTask>> CollectBeforeTestHooksAsync(Type testClassType); + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif ValueTask>> CollectAfterTestHooksAsync(Type testClassType); + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif ValueTask>> CollectBeforeEveryTestHooksAsync(Type testClassType); + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif ValueTask>> CollectAfterEveryTestHooksAsync(Type testClassType); ValueTask>> CollectBeforeClassHooksAsync(Type testClassType); diff --git a/TUnit.Engine/Interfaces/ITestCoordinator.cs b/TUnit.Engine/Interfaces/ITestCoordinator.cs index 475c54edda..33200b7dc0 100644 --- a/TUnit.Engine/Interfaces/ITestCoordinator.cs +++ b/TUnit.Engine/Interfaces/ITestCoordinator.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Microsoft.Testing.Platform.Extensions.Messages; using TUnit.Core; @@ -8,5 +9,8 @@ namespace TUnit.Engine.Interfaces; /// internal interface ITestCoordinator { + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif Task ExecuteTestAsync(AbstractExecutableTest test, CancellationToken cancellationToken); } diff --git a/TUnit.Engine/Logging/StandardErrorConsoleInterceptor.cs b/TUnit.Engine/Logging/StandardErrorConsoleInterceptor.cs index 41b921f2cc..2d3080bcae 100644 --- a/TUnit.Engine/Logging/StandardErrorConsoleInterceptor.cs +++ b/TUnit.Engine/Logging/StandardErrorConsoleInterceptor.cs @@ -33,12 +33,12 @@ public void Initialize() Console.SetError(this); } - protected private override TextWriter GetOriginalOut() + private protected override TextWriter GetOriginalOut() { return DefaultError; } - protected private override void ResetDefault() + private protected override void ResetDefault() { Console.SetError(DefaultError); } diff --git a/TUnit.Engine/Logging/StandardOutConsoleInterceptor.cs b/TUnit.Engine/Logging/StandardOutConsoleInterceptor.cs index 9d981ceca8..d494fee6aa 100644 --- a/TUnit.Engine/Logging/StandardOutConsoleInterceptor.cs +++ b/TUnit.Engine/Logging/StandardOutConsoleInterceptor.cs @@ -33,12 +33,12 @@ public void Initialize() Console.SetOut(this); } - protected private override TextWriter GetOriginalOut() + private protected override TextWriter GetOriginalOut() { return DefaultOut; } - protected private override void ResetDefault() + private protected override void ResetDefault() { Console.SetOut(DefaultOut); } diff --git a/TUnit.Engine/Scheduling/ConstraintKeyScheduler.cs b/TUnit.Engine/Scheduling/ConstraintKeyScheduler.cs index 6ea17981cc..de540d98a2 100644 --- a/TUnit.Engine/Scheduling/ConstraintKeyScheduler.cs +++ b/TUnit.Engine/Scheduling/ConstraintKeyScheduler.cs @@ -22,6 +22,9 @@ public ConstraintKeyScheduler( _parallelLimitLockProvider = parallelLimitLockProvider; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif public async ValueTask ExecuteTestsWithConstraintsAsync( (AbstractExecutableTest Test, IReadOnlyList ConstraintKeys, int Priority)[] tests, CancellationToken cancellationToken) @@ -91,6 +94,9 @@ public async ValueTask ExecuteTestsWithConstraintsAsync( await Task.WhenAll(activeTasks).ConfigureAwait(false); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task WaitAndExecuteTestAsync( AbstractExecutableTest test, IReadOnlyList constraintKeys, @@ -108,6 +114,9 @@ private async Task WaitAndExecuteTestAsync( await ExecuteTestAndReleaseKeysAsync(test, constraintKeys, lockedKeys, lockObject, waitingTests, cancellationToken).ConfigureAwait(false); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task ExecuteTestAndReleaseKeysAsync( AbstractExecutableTest test, IReadOnlyList constraintKeys, diff --git a/TUnit.Engine/Scheduling/IConstraintKeyScheduler.cs b/TUnit.Engine/Scheduling/IConstraintKeyScheduler.cs index 0b98d503db..e9a3e7ebf5 100644 --- a/TUnit.Engine/Scheduling/IConstraintKeyScheduler.cs +++ b/TUnit.Engine/Scheduling/IConstraintKeyScheduler.cs @@ -1,9 +1,13 @@ +using System.Diagnostics.CodeAnalysis; using TUnit.Core; namespace TUnit.Engine.Scheduling; internal interface IConstraintKeyScheduler { + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif ValueTask ExecuteTestsWithConstraintsAsync( (AbstractExecutableTest Test, IReadOnlyList ConstraintKeys, int Priority)[] tests, CancellationToken cancellationToken); diff --git a/TUnit.Engine/Scheduling/ITestScheduler.cs b/TUnit.Engine/Scheduling/ITestScheduler.cs index 0abfdb55f9..42ff23527b 100644 --- a/TUnit.Engine/Scheduling/ITestScheduler.cs +++ b/TUnit.Engine/Scheduling/ITestScheduler.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using TUnit.Core; namespace TUnit.Engine.Scheduling; @@ -11,6 +12,9 @@ internal interface ITestScheduler /// Schedules and executes tests with optimal parallelization /// /// True if successful, false if After(TestSession) hooks failed + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif Task ScheduleAndExecuteAsync( List tests, CancellationToken cancellationToken); diff --git a/TUnit.Engine/Scheduling/TestRunner.cs b/TUnit.Engine/Scheduling/TestRunner.cs index 5dde86ed23..3e84f70d66 100644 --- a/TUnit.Engine/Scheduling/TestRunner.cs +++ b/TUnit.Engine/Scheduling/TestRunner.cs @@ -39,6 +39,9 @@ internal TestRunner( private readonly ThreadSafeDictionary _executingTests = new(); private Exception? _firstFailFastException; + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif public async Task ExecuteTestAsync(AbstractExecutableTest test, CancellationToken cancellationToken) { // Prevent double execution with a simple lock @@ -46,6 +49,9 @@ public async Task ExecuteTestAsync(AbstractExecutableTest test, CancellationToke await executionTask.ConfigureAwait(false); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task ExecuteTestInternalAsync(AbstractExecutableTest test, CancellationToken cancellationToken) { try diff --git a/TUnit.Engine/Scheduling/TestScheduler.cs b/TUnit.Engine/Scheduling/TestScheduler.cs index 3818275b3a..507dc9ca83 100644 --- a/TUnit.Engine/Scheduling/TestScheduler.cs +++ b/TUnit.Engine/Scheduling/TestScheduler.cs @@ -50,6 +50,9 @@ public TestScheduler( _staticPropertyHandler = staticPropertyHandler; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif public async Task ScheduleAndExecuteAsync( List testList, CancellationToken cancellationToken) @@ -130,6 +133,9 @@ public async Task ScheduleAndExecuteAsync( return true; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task ExecuteGroupedTestsAsync( GroupedTests groupedTests, CancellationToken cancellationToken) @@ -214,6 +220,9 @@ private async Task ExecuteGroupedTestsAsync( } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task ExecuteTestWithParallelLimitAsync( AbstractExecutableTest test, CancellationToken cancellationToken) @@ -238,6 +247,9 @@ private async Task ExecuteTestWithParallelLimitAsync( } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task ExecuteParallelGroupAsync( string groupName, AbstractExecutableTest[] orderedTests, @@ -265,6 +277,9 @@ private async Task ExecuteParallelGroupAsync( } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task ExecuteConstrainedParallelGroupAsync( string groupName, GroupedConstrainedTests constrainedTests, @@ -320,6 +335,9 @@ private async Task ExecuteConstrainedParallelGroupAsync( } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task ExecuteSequentiallyAsync( string groupName, AbstractExecutableTest[] tests, @@ -335,6 +353,9 @@ private async Task ExecuteSequentiallyAsync( } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task ExecuteParallelTestsWithLimitAsync( AbstractExecutableTest[] tests, int maxParallelism, diff --git a/TUnit.Engine/Services/DataSourceInitializer.cs b/TUnit.Engine/Services/DataSourceInitializer.cs index f8f3d459c4..f0dd58ec96 100644 --- a/TUnit.Engine/Services/DataSourceInitializer.cs +++ b/TUnit.Engine/Services/DataSourceInitializer.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using TUnit.Core; using TUnit.Core.Interfaces; using TUnit.Core.PropertyInjection; @@ -24,6 +25,9 @@ public void Initialize(PropertyInjectionService propertyInjectionService) /// Ensures a data source instance is fully initialized before use. /// This includes property injection and calling IAsyncInitializer if implemented. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public async Task EnsureInitializedAsync( T dataSource, Dictionary? objectBag = null, @@ -58,6 +62,9 @@ public async Task EnsureInitializedAsync( /// /// Initializes a data source instance with the complete lifecycle. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif private async Task InitializeDataSourceAsync( object dataSource, Dictionary? objectBag, @@ -78,7 +85,11 @@ await _propertyInjectionService.InjectPropertiesIntoObjectAsync( dataSource, objectBag, methodMetadata, events); } - // Step 2: IAsyncInitializer + // Step 2: Initialize nested property-injected objects (deepest first) + // This ensures that when the parent's IAsyncInitializer runs, all nested objects are already initialized + await InitializeNestedObjectsAsync(dataSource); + + // Step 3: IAsyncInitializer on the data source itself if (dataSource is IAsyncInitializer asyncInitializer) { await ObjectInitializer.InitializeAsync(asyncInitializer); @@ -91,6 +102,116 @@ await _propertyInjectionService.InjectPropertiesIntoObjectAsync( } } + /// + /// Initializes all nested property-injected objects in depth-first order. + /// This ensures that when the parent's IAsyncInitializer runs, all nested dependencies are already initialized. + /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif + private async Task InitializeNestedObjectsAsync(object rootObject) + { + var objectsByDepth = new Dictionary>(); + var visitedObjects = new HashSet(); + + // Collect all nested property-injected objects grouped by depth + CollectNestedObjects(rootObject, objectsByDepth, visitedObjects, currentDepth: 1); + + // Initialize objects deepest-first (highest depth to lowest) + var depths = objectsByDepth.Keys.OrderByDescending(depth => depth); + + foreach (var depth in depths) + { + var objectsAtDepth = objectsByDepth[depth]; + + // Initialize all objects at this depth in parallel + await Task.WhenAll(objectsAtDepth.Select(obj => ObjectInitializer.InitializeAsync(obj).AsTask())); + } + } + + /// + /// Recursively collects all nested property-injected objects grouped by depth. + /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif + private void CollectNestedObjects( + object obj, + Dictionary> objectsByDepth, + HashSet visitedObjects, + int currentDepth) + { + var plan = PropertyInjectionCache.GetOrCreatePlan(obj.GetType()); + + if (!SourceRegistrar.IsEnabled) + { + // Reflection mode + foreach (var prop in plan.ReflectionProperties) + { + var value = prop.Property.GetValue(obj); + + if (value == null || !visitedObjects.Add(value)) + { + continue; + } + + // Add to the current depth level if it has injectable properties or implements IAsyncInitializer + if (PropertyInjectionCache.HasInjectableProperties(value.GetType()) || value is IAsyncInitializer) + { + if (!objectsByDepth.ContainsKey(currentDepth)) + { + objectsByDepth[currentDepth] = []; + } + + objectsByDepth[currentDepth].Add(value); + } + + // Recursively collect nested objects + if (PropertyInjectionCache.HasInjectableProperties(value.GetType())) + { + CollectNestedObjects(value, objectsByDepth, visitedObjects, currentDepth + 1); + } + } + } + else + { + // Source-generated mode + foreach (var metadata in plan.SourceGeneratedProperties) + { + var property = metadata.ContainingType.GetProperty(metadata.PropertyName); + + if (property == null || !property.CanRead) + { + continue; + } + + var value = property.GetValue(obj); + + if (value == null || !visitedObjects.Add(value)) + { + continue; + } + + // Add to the current depth level if it has injectable properties or implements IAsyncInitializer + if (PropertyInjectionCache.HasInjectableProperties(value.GetType()) || value is IAsyncInitializer) + { + if (!objectsByDepth.ContainsKey(currentDepth)) + { + objectsByDepth[currentDepth] = []; + } + + objectsByDepth[currentDepth].Add(value); + } + + // Recursively collect nested objects + if (PropertyInjectionCache.HasInjectableProperties(value.GetType())) + { + CollectNestedObjects(value, objectsByDepth, visitedObjects, currentDepth + 1); + } + } + } + } + /// /// Clears the initialization cache. Should be called at the end of test sessions. /// diff --git a/TUnit.Engine/Services/EventReceiverOrchestrator.cs b/TUnit.Engine/Services/EventReceiverOrchestrator.cs index eebc31be2c..b26b433d2c 100644 --- a/TUnit.Engine/Services/EventReceiverOrchestrator.cs +++ b/TUnit.Engine/Services/EventReceiverOrchestrator.cs @@ -84,6 +84,9 @@ obj is IFirstTestInAssemblyEventReceiver || // Fast-path checks with inlining [MethodImpl(MethodImplOptions.AggressiveInlining)] + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async ValueTask InvokeTestStartEventReceiversAsync(TestContext context, CancellationToken cancellationToken) { // Fast path - no allocation if no receivers @@ -95,6 +98,9 @@ public async ValueTask InvokeTestStartEventReceiversAsync(TestContext context, C await InvokeTestStartEventReceiversCore(context, cancellationToken); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async ValueTask InvokeTestStartEventReceiversCore(TestContext context, CancellationToken cancellationToken) { var receivers = context.GetEligibleEventObjects() @@ -121,6 +127,9 @@ private async ValueTask InvokeTestStartEventReceiversCore(TestContext context, C } [MethodImpl(MethodImplOptions.AggressiveInlining)] + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async ValueTask InvokeTestEndEventReceiversAsync(TestContext context, CancellationToken cancellationToken) { if (!_registry.HasTestEndReceivers()) @@ -131,6 +140,9 @@ public async ValueTask InvokeTestEndEventReceiversAsync(TestContext context, Can await InvokeTestEndEventReceiversCore(context, cancellationToken); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async ValueTask InvokeTestEndEventReceiversCore(TestContext context, CancellationToken cancellationToken) { var receivers = context.GetEligibleEventObjects() @@ -155,6 +167,9 @@ private async ValueTask InvokeTestEndEventReceiversCore(TestContext context, Can } [MethodImpl(MethodImplOptions.AggressiveInlining)] + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async ValueTask InvokeTestSkippedEventReceiversAsync(TestContext context, CancellationToken cancellationToken) { if (!_registry.HasTestSkippedReceivers()) @@ -165,6 +180,9 @@ public async ValueTask InvokeTestSkippedEventReceiversAsync(TestContext context, await InvokeTestSkippedEventReceiversCore(context, cancellationToken); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async ValueTask InvokeTestSkippedEventReceiversCore(TestContext context, CancellationToken cancellationToken) { var receivers = context.GetEligibleEventObjects() @@ -181,6 +199,9 @@ private async ValueTask InvokeTestSkippedEventReceiversCore(TestContext context, } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async ValueTask InvokeTestDiscoveryEventReceiversAsync(TestContext context, DiscoveredTestContext discoveredContext, CancellationToken cancellationToken) { var eventReceivers = context.GetEligibleEventObjects() @@ -197,6 +218,9 @@ public async ValueTask InvokeTestDiscoveryEventReceiversAsync(TestContext contex } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async ValueTask InvokeHookRegistrationEventReceiversAsync(HookRegisteredContext hookContext, CancellationToken cancellationToken) { // Get event receivers from the hook method's attributes diff --git a/TUnit.Engine/Services/HookCollectionService.cs b/TUnit.Engine/Services/HookCollectionService.cs index 5ad471689b..f06c043756 100644 --- a/TUnit.Engine/Services/HookCollectionService.cs +++ b/TUnit.Engine/Services/HookCollectionService.cs @@ -25,6 +25,9 @@ public HookCollectionService(EventReceiverOrchestrator eventReceiverOrchestrator _eventReceiverOrchestrator = eventReceiverOrchestrator; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task ProcessHookRegistrationAsync(HookMethod hookMethod, CancellationToken cancellationToken = default) { // Only process each hook once @@ -45,6 +48,9 @@ private async Task ProcessHookRegistrationAsync(HookMethod hookMethod, Cancellat } } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async ValueTask>> CollectBeforeTestHooksAsync(Type testClassType) { if (_beforeTestHooksCache.TryGetValue(testClassType, out var cachedHooks)) @@ -57,6 +63,9 @@ public async ValueTask> return hooks; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task>> BuildBeforeTestHooksAsync(Type type) { var hooksByType = new List<(Type type, List<(int order, int registrationIndex, Func hook)> hooks)>(); @@ -112,6 +121,9 @@ private async Task>> Bu return finalHooks; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async ValueTask>> CollectAfterTestHooksAsync(Type testClassType) { if (_afterTestHooksCache.TryGetValue(testClassType, out var cachedHooks)) @@ -124,6 +136,9 @@ public async ValueTask> return hooks; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task>> BuildAfterTestHooksAsync(Type type) { var hooksByType = new List<(Type type, List<(int order, int registrationIndex, Func hook)> hooks)>(); @@ -178,6 +193,9 @@ private async Task>> Bu return finalHooks; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async ValueTask>> CollectBeforeEveryTestHooksAsync(Type testClassType) { if (_beforeEveryTestHooksCache.TryGetValue(testClassType, out var cachedHooks)) @@ -190,6 +208,9 @@ public async ValueTask> return hooks; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task>> BuildBeforeEveryTestHooksAsync(Type type) { var allHooks = new List<(int order, int registrationIndex, Func hook)>(); @@ -208,6 +229,9 @@ private async Task>> Bu .ToList(); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async ValueTask>> CollectAfterEveryTestHooksAsync(Type testClassType) { if (_afterEveryTestHooksCache.TryGetValue(testClassType, out var cachedHooks)) @@ -220,6 +244,9 @@ public async ValueTask> return hooks; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task>> BuildAfterEveryTestHooksAsync(Type type) { var allHooks = new List<(int order, int registrationIndex, Func hook)>(); @@ -551,6 +578,9 @@ public ValueTask>>(hooks); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task> CreateInstanceHookDelegateAsync(InstanceHookMethod hook) { // Process hook registration event receivers @@ -569,6 +599,9 @@ private async Task> CreateInstanceHoo }; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif private async Task> CreateStaticHookDelegateAsync(StaticHookMethod hook) { // Process hook registration event receivers diff --git a/TUnit.Engine/Services/HookExecutor.cs b/TUnit.Engine/Services/HookExecutor.cs index a30eb270ef..a483651f3c 100644 --- a/TUnit.Engine/Services/HookExecutor.cs +++ b/TUnit.Engine/Services/HookExecutor.cs @@ -156,6 +156,9 @@ public async Task> ExecuteAfterClassHooksAsync( return exceptions; } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Hook discovery uses reflection on methods and attributes")] + #endif public async Task ExecuteBeforeTestHooksAsync(AbstractExecutableTest test, CancellationToken cancellationToken) { var testClassType = test.Metadata.TestClassType; @@ -191,6 +194,9 @@ public async Task ExecuteBeforeTestHooksAsync(AbstractExecutableTest test, Cance } } + #if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Hook discovery uses reflection on methods and attributes")] + #endif public async Task ExecuteAfterTestHooksAsync(AbstractExecutableTest test, CancellationToken cancellationToken) { var testClassType = test.Metadata.TestClassType; diff --git a/TUnit.Engine/Services/IStaticPropertyInitializer.cs b/TUnit.Engine/Services/IStaticPropertyInitializer.cs new file mode 100644 index 0000000000..87c46d7bcb --- /dev/null +++ b/TUnit.Engine/Services/IStaticPropertyInitializer.cs @@ -0,0 +1,12 @@ +namespace TUnit.Engine.Services; + +/// +/// Initializes static properties for tests based on the execution mode. +/// +internal interface IStaticPropertyInitializer +{ + /// + /// Initializes all static properties. + /// + Task InitializeAsync(CancellationToken cancellationToken); +} diff --git a/TUnit.Engine/Services/ObjectRegistrationService.cs b/TUnit.Engine/Services/ObjectRegistrationService.cs index 55b45f8355..26b7a23041 100644 --- a/TUnit.Engine/Services/ObjectRegistrationService.cs +++ b/TUnit.Engine/Services/ObjectRegistrationService.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using TUnit.Core; using TUnit.Core.PropertyInjection; using TUnit.Core.Tracking; @@ -27,6 +28,9 @@ public ObjectRegistrationService( /// Shared object bag for the test context. Must not be null. /// Method metadata for the test. Can be null. /// Test context events for tracking. Must not be null and must be unique per test permutation. + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public async Task RegisterObjectAsync( object instance, Dictionary objectBag, @@ -62,6 +66,9 @@ await _propertyInjectionService.InjectPropertiesIntoObjectAsync( /// Registers multiple objects (e.g., constructor/method arguments) in parallel. /// Used during test registration to prepare arguments without executing expensive operations. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public async Task RegisterArgumentsAsync( object?[] arguments, Dictionary objectBag, @@ -89,6 +96,9 @@ public async Task RegisterArgumentsAsync( /// /// Determines if an object requires property injection. /// + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Property injection cache handles both AOT and reflection modes appropriately")] + #endif private bool RequiresPropertyInjection(object instance) { return PropertyInjectionCache.HasInjectableProperties(instance.GetType()); diff --git a/TUnit.Engine/Services/PropertyDataResolver.cs b/TUnit.Engine/Services/PropertyDataResolver.cs index df045a8a27..22fde98725 100644 --- a/TUnit.Engine/Services/PropertyDataResolver.cs +++ b/TUnit.Engine/Services/PropertyDataResolver.cs @@ -16,7 +16,9 @@ internal static class PropertyDataResolver /// /// Resolves data from a property's data source. /// - [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Property types handled dynamically")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Property data resolution uses reflection on property types")] +#endif public static async Task ResolvePropertyDataAsync(PropertyInitializationContext context, DataSourceInitializer dataSourceInitializer, ObjectRegistrationService objectRegistrationService) { var dataSource = await GetInitializedDataSourceAsync(context, dataSourceInitializer); @@ -72,6 +74,9 @@ await objectRegistrationService.RegisterObjectAsync( /// Gets an initialized data source from the context. /// Ensures the data source is fully initialized (including property injection) before returning it. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif private static async Task GetInitializedDataSourceAsync(PropertyInitializationContext context, DataSourceInitializer dataSourceInitializer) { IDataSourceAttribute? dataSource = null; @@ -103,7 +108,9 @@ await objectRegistrationService.RegisterObjectAsync( /// /// Creates data generator metadata for the property. /// - [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Property injection metadata")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Data generator metadata creation uses reflection on property types")] +#endif private static DataGeneratorMetadata CreateDataGeneratorMetadata( PropertyInitializationContext context, IDataSourceAttribute dataSource) @@ -158,10 +165,12 @@ private static DataGeneratorMetadata CreateDataGeneratorMetadata( /// /// Resolves value from data source arguments, handling tuples. /// - [UnconditionalSuppressMessage("Trimming", "IL2067", Justification = "Tuple types are created dynamically")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Value resolution may create tuple types dynamically")] +#endif private static object? ResolveValueFromArgs( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] - Type propertyType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] + Type propertyType, object?[]? args) { return TupleValueResolver.ResolveTupleValue(propertyType, args); diff --git a/TUnit.Engine/Services/PropertyInitialization/Strategies/NestedPropertyStrategy.cs b/TUnit.Engine/Services/PropertyInitialization/Strategies/NestedPropertyStrategy.cs index 45be31469d..e348526de7 100644 --- a/TUnit.Engine/Services/PropertyInitialization/Strategies/NestedPropertyStrategy.cs +++ b/TUnit.Engine/Services/PropertyInitialization/Strategies/NestedPropertyStrategy.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using TUnit.Core; using TUnit.Core.PropertyInjection; using TUnit.Core.PropertyInjection.Initialization; @@ -36,6 +37,9 @@ public bool CanHandle(PropertyInitializationContext context) /// /// Initializes nested properties within an already resolved property value. /// + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Property injection cache and setter factory handle both AOT and reflection modes appropriately")] + #endif public async Task InitializePropertyAsync(PropertyInitializationContext context) { if (context.ResolvedValue == null) @@ -143,6 +147,9 @@ private PropertyInitializationContext CreateNestedContext( /// /// Creates a nested context for reflection-based properties. /// + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Reflection-based property setter creation is only used in reflection mode, not in AOT")] + #endif private PropertyInitializationContext CreateNestedContext( PropertyInitializationContext parentContext, object instance, diff --git a/TUnit.Engine/Services/PropertyInitialization/Strategies/ReflectionPropertyStrategy.cs b/TUnit.Engine/Services/PropertyInitialization/Strategies/ReflectionPropertyStrategy.cs index 8c4799dd13..f5bb829bd9 100644 --- a/TUnit.Engine/Services/PropertyInitialization/Strategies/ReflectionPropertyStrategy.cs +++ b/TUnit.Engine/Services/PropertyInitialization/Strategies/ReflectionPropertyStrategy.cs @@ -30,7 +30,9 @@ public bool CanHandle(PropertyInitializationContext context) /// /// Initializes a property using reflection. /// - [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Reflection mode support")] + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Reflection mode throws at runtime if used in AOT, property data resolver handles reflection appropriately")] + #endif public async Task InitializePropertyAsync(PropertyInitializationContext context) { #if NET diff --git a/TUnit.Engine/Services/PropertyInitialization/Strategies/SourceGeneratedPropertyStrategy.cs b/TUnit.Engine/Services/PropertyInitialization/Strategies/SourceGeneratedPropertyStrategy.cs index 068470813a..42eb2828b8 100644 --- a/TUnit.Engine/Services/PropertyInitialization/Strategies/SourceGeneratedPropertyStrategy.cs +++ b/TUnit.Engine/Services/PropertyInitialization/Strategies/SourceGeneratedPropertyStrategy.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using TUnit.Core; using TUnit.Core.PropertyInjection.Initialization; @@ -28,6 +29,9 @@ public bool CanHandle(PropertyInitializationContext context) /// /// Initializes a property using source-generated metadata. /// + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Property data resolver handles both AOT and reflection modes appropriately")] + #endif public async Task InitializePropertyAsync(PropertyInitializationContext context) { if (context.SourceGeneratedMetadata == null) diff --git a/TUnit.Engine/Services/PropertyInitializationOrchestrator.cs b/TUnit.Engine/Services/PropertyInitializationOrchestrator.cs index 87f93e11b4..17c55a854d 100644 --- a/TUnit.Engine/Services/PropertyInitializationOrchestrator.cs +++ b/TUnit.Engine/Services/PropertyInitializationOrchestrator.cs @@ -63,7 +63,9 @@ public async Task InitializePropertiesAsync( /// /// Initializes all properties for an instance using reflection. /// - [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Reflection mode support")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Reflection-based property initialization uses PropertyInfo")] +#endif public async Task InitializePropertiesAsync( object instance, (PropertyInfo Property, IDataSourceAttribute DataSource)[] properties, @@ -86,6 +88,9 @@ public async Task InitializePropertiesAsync( /// /// Handles the complete initialization flow for an object with properties. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Reflection-based property initialization uses PropertyInfo")] + #endif public async Task InitializeObjectWithPropertiesAsync( object instance, PropertyInjectionPlan plan, @@ -139,6 +144,9 @@ private PropertyInitializationContext CreateContext( /// /// Creates initialization context for reflection-based properties. /// + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Reflection-based property setter creation is only used in reflection mode, not in AOT")] + #endif private PropertyInitializationContext CreateContext( object instance, PropertyInfo property, diff --git a/TUnit.Engine/Services/PropertyInjectionService.cs b/TUnit.Engine/Services/PropertyInjectionService.cs index 3c239b64ae..037f215234 100644 --- a/TUnit.Engine/Services/PropertyInjectionService.cs +++ b/TUnit.Engine/Services/PropertyInjectionService.cs @@ -28,6 +28,9 @@ public void Initialize(ObjectRegistrationService objectRegistrationService) /// This ensures properties are only initialized when the test is about to run. /// Arguments are processed in parallel for better performance. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public async Task InjectPropertiesIntoArgumentsAsync(object?[] arguments, Dictionary objectBag, MethodMetadata methodMetadata, TestContextEvents events) { if (arguments.Length == 0) @@ -63,6 +66,9 @@ public async Task InjectPropertiesIntoArgumentsAsync(object?[] arguments, Dictio /// Shared object bag for the test context. Must not be null. /// Method metadata for the test. Can be null. /// Test context events for tracking. Must not be null and must be unique per test permutation. + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public Task InjectPropertiesIntoObjectAsync(object instance, Dictionary objectBag, MethodMetadata? methodMetadata, TestContextEvents events) { if (objectBag == null) @@ -84,6 +90,9 @@ public Task InjectPropertiesIntoObjectAsync(object instance, Dictionary objectBag, MethodMetadata? methodMetadata, TestContextEvents events, ConcurrentDictionary visitedObjects) { if (instance == null) diff --git a/TUnit.Engine/Services/ReflectionStaticPropertyInitializer.cs b/TUnit.Engine/Services/ReflectionStaticPropertyInitializer.cs new file mode 100644 index 0000000000..bc652c4bd9 --- /dev/null +++ b/TUnit.Engine/Services/ReflectionStaticPropertyInitializer.cs @@ -0,0 +1,45 @@ +using System.Diagnostics.CodeAnalysis; +using TUnit.Core; +using TUnit.Core.Services; +using TUnit.Engine.Logging; + +namespace TUnit.Engine.Services; + +/// +/// Initializes static properties using both source-generated initializers and reflection-based discovery. +/// This implementation requires reflection and is NOT AOT-compatible. +/// +#if NET6_0_OR_GREATER +[RequiresUnreferencedCode("Uses reflection to discover and initialize static properties")] +[RequiresDynamicCode("Static property initialization may require dynamic code generation")] +#endif +internal sealed class ReflectionStaticPropertyInitializer : IStaticPropertyInitializer +{ + private readonly TUnitFrameworkLogger _logger; + + public ReflectionStaticPropertyInitializer(TUnitFrameworkLogger logger) + { + _logger = logger; + } + + public async Task InitializeAsync(CancellationToken cancellationToken) + { + try + { + // Execute all registered global initializers from source generation + while (Sources.GlobalInitializers.TryDequeue(out var initializer)) + { + cancellationToken.ThrowIfCancellationRequested(); + await initializer(); + } + + // Additionally, initialize static properties discovered via reflection + await StaticPropertyReflectionInitializer.InitializeAllStaticPropertiesAsync(); + } + catch (Exception ex) + { + await _logger.LogErrorAsync($"Error during static property initialization: {ex}"); + throw; + } + } +} diff --git a/TUnit.Engine/Services/SourceGenStaticPropertyInitializer.cs b/TUnit.Engine/Services/SourceGenStaticPropertyInitializer.cs new file mode 100644 index 0000000000..eb24ffb7fd --- /dev/null +++ b/TUnit.Engine/Services/SourceGenStaticPropertyInitializer.cs @@ -0,0 +1,36 @@ +using TUnit.Core; +using TUnit.Engine.Logging; + +namespace TUnit.Engine.Services; + +/// +/// Initializes static properties using source-generated initializers only. +/// This implementation does not use reflection and is AOT-compatible. +/// +internal sealed class SourceGenStaticPropertyInitializer : IStaticPropertyInitializer +{ + private readonly TUnitFrameworkLogger _logger; + + public SourceGenStaticPropertyInitializer(TUnitFrameworkLogger logger) + { + _logger = logger; + } + + public async Task InitializeAsync(CancellationToken cancellationToken) + { + try + { + // Execute all registered global initializers from source generation + while (Sources.GlobalInitializers.TryDequeue(out var initializer)) + { + cancellationToken.ThrowIfCancellationRequested(); + await initializer(); + } + } + catch (Exception ex) + { + await _logger.LogErrorAsync($"Error during static property initialization: {ex}"); + throw; + } + } +} diff --git a/TUnit.Engine/Services/TestArgumentRegistrationService.cs b/TUnit.Engine/Services/TestArgumentRegistrationService.cs index 5698233ef3..5b50965fb0 100644 --- a/TUnit.Engine/Services/TestArgumentRegistrationService.cs +++ b/TUnit.Engine/Services/TestArgumentRegistrationService.cs @@ -34,6 +34,9 @@ public TestArgumentRegistrationService(ObjectRegistrationService objectRegistrat /// Called when a test is registered. This is the correct time to register constructor and method arguments /// for proper reference counting and disposal tracking. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public async ValueTask OnTestRegistered(TestRegisteredContext context) { var testContext = context.TestContext; @@ -65,6 +68,9 @@ await _objectRegistrationService.RegisterArgumentsAsync( /// This ensures proper reference counting for all property-injected instances during discovery. /// Exceptions during data generation will be caught and associated with the test for reporting. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif private async ValueTask RegisterPropertiesAsync(TestContext testContext) { try diff --git a/TUnit.Engine/Services/TestExecution/RetryHelper.cs b/TUnit.Engine/Services/TestExecution/RetryHelper.cs index fa98a417ee..d9f7cb8919 100644 --- a/TUnit.Engine/Services/TestExecution/RetryHelper.cs +++ b/TUnit.Engine/Services/TestExecution/RetryHelper.cs @@ -10,6 +10,8 @@ public static async Task ExecuteWithRetry(TestContext testContext, Func ac for (var attempt = 0; attempt < maxRetries + 1; attempt++) { + testContext.CurrentRetryAttempt = attempt; + try { await action(); @@ -42,13 +44,13 @@ private static async Task ShouldRetry(TestContext testContext, Exception e { return false; } - + if (testContext.RetryFunc == null) { // Default behavior: retry on any exception if within retry limit return true; } - + return await testContext.RetryFunc(testContext, ex, attempt + 1).ConfigureAwait(false); } } diff --git a/TUnit.Engine/Services/TestExecution/TestCoordinator.cs b/TUnit.Engine/Services/TestExecution/TestCoordinator.cs index 3f87247b2a..4a79021c62 100644 --- a/TUnit.Engine/Services/TestExecution/TestCoordinator.cs +++ b/TUnit.Engine/Services/TestExecution/TestCoordinator.cs @@ -43,12 +43,18 @@ public TestCoordinator( _logger = logger; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif public async Task ExecuteTestAsync(AbstractExecutableTest test, CancellationToken cancellationToken) { await _executionGuard.TryStartExecutionAsync(test.TestId, () => ExecuteTestInternalAsync(test, cancellationToken)); } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Test execution involves reflection for hooks and initialization")] + #endif private async Task ExecuteTestInternalAsync(AbstractExecutableTest test, CancellationToken cancellationToken) { try diff --git a/TUnit.Engine/Services/TestFilterService.cs b/TUnit.Engine/Services/TestFilterService.cs index ab292e1c8d..df5d9678bb 100644 --- a/TUnit.Engine/Services/TestFilterService.cs +++ b/TUnit.Engine/Services/TestFilterService.cs @@ -62,6 +62,9 @@ public IReadOnlyCollection FilterTests(ITestExecutionFil return filteredTests; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif private async Task RegisterTest(AbstractExecutableTest test) { var discoveredTest = new DiscoveredTest @@ -96,6 +99,9 @@ private async Task RegisterTest(AbstractExecutableTest test) } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public async Task RegisterTestsAsync(IEnumerable tests) { foreach (var test in tests) diff --git a/TUnit.Engine/Services/TestGenericTypeResolver.cs b/TUnit.Engine/Services/TestGenericTypeResolver.cs index 7b5868a854..af6e7b56c0 100644 --- a/TUnit.Engine/Services/TestGenericTypeResolver.cs +++ b/TUnit.Engine/Services/TestGenericTypeResolver.cs @@ -18,6 +18,9 @@ internal sealed class TestGenericTypeResolver /// The test metadata containing generic type information /// The runtime test data containing actual arguments /// A result containing resolved generic types for both class and method + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type mapping inference uses Type.GetInterfaces and reflection")] + #endif public static TestGenericTypeResolution Resolve(TestMetadata metadata, TestBuilder.TestData testData) { var result = new TestGenericTypeResolution(); @@ -52,6 +55,9 @@ public static TestGenericTypeResolution Resolve(TestMetadata metadata, TestBuild return result; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type mapping inference uses Type.GetInterfaces and reflection")] + #endif private static Type[] ResolveClassGenericArguments( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type genericClassType, GenericTypeInfo genericTypeInfo, @@ -114,6 +120,9 @@ private static Type[] ResolveClassGenericArguments( return resolvedTypes; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type mapping inference uses Type.GetInterfaces and reflection")] + #endif private static Type[] ResolveMethodGenericArguments( MethodMetadata methodMetadata, GenericMethodInfo genericMethodInfo, @@ -406,6 +415,9 @@ private static Type[] ResolveMethodGenericArguments( return resolvedTypesFromMapping; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type mapping inference uses Type.GetInterfaces and reflection")] + #endif private static bool TryInferTypesFromArguments( ParameterInfo[] parameters, object?[] arguments, @@ -429,6 +441,9 @@ private static bool TryInferTypesFromArguments( return true; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type mapping inference uses Type.GetInterfaces and reflection")] + #endif private static void InferTypeMapping( Type parameterType, Type argumentType, @@ -442,9 +457,12 @@ private static void InferTypeMapping( } } +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Type mapping inference uses Type.GetInterfaces and reflection")] +#endif private static bool TryInferTypeMapping( - Type parameterType, - Type argumentType, + Type parameterType, + Type argumentType, Dictionary typeMapping) { // Direct generic parameter @@ -505,10 +523,7 @@ private static bool TryInferTypeMapping( if (parameterType is { IsGenericType: true, IsInterface: true }) { // Check if argument type implements the parameter interface - #pragma warning disable IL2070 // Type.GetInterfaces() requires preserved interfaces - // Note: Interface discovery for generic type resolution. AOT scenarios should use concrete types or source-generated type mappings. var implementedInterfaces = argumentType.GetInterfaces(); - #pragma warning restore IL2070 foreach (var implementedInterface in implementedInterfaces) { if (implementedInterface.IsGenericType) diff --git a/TUnit.Engine/Services/TestRegistry.cs b/TUnit.Engine/Services/TestRegistry.cs index 14ffac453c..87ed67508e 100644 --- a/TUnit.Engine/Services/TestRegistry.cs +++ b/TUnit.Engine/Services/TestRegistry.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Reflection; @@ -32,6 +32,7 @@ public TestRegistry(TestBuilderPipeline testBuilderPipeline, _sessionCancellationToken = sessionCancellationToken; } [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Adding dynamic tests requires runtime compilation and reflection which are not supported in native AOT scenarios.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Dynamic test metadata creation uses reflection")] public async Task AddDynamicTest<[DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors @@ -65,8 +66,10 @@ public TestRegistry(TestBuilderPipeline testBuilderPipeline, await ProcessPendingDynamicTests(); } - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", - Justification = "Dynamic tests are opt-in and users are warned via RequiresDynamicCode on AddDynamicTest method")] +#if NET6_0_OR_GREATER + [RequiresDynamicCode("Dynamic test processing uses expression compilation")] + [RequiresUnreferencedCode("Dynamic test metadata creation uses reflection")] +#endif private async Task ProcessPendingDynamicTests() { var testsToProcess = new List(); @@ -104,6 +107,7 @@ private async Task ProcessPendingDynamicTests() } [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Dynamic tests require runtime compilation of lambda expressions and are not supported in native AOT scenarios.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Method metadata creation uses reflection on parameters and types")] private async Task CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult result) { if (result.TestClassType == null || result.TestMethod == null) diff --git a/TUnit.Engine/TUnitInitializer.cs b/TUnit.Engine/TUnitInitializer.cs index 5732b88467..3eb47fb89b 100644 --- a/TUnit.Engine/TUnitInitializer.cs +++ b/TUnit.Engine/TUnitInitializer.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using Microsoft.Testing.Platform.CommandLine; using Microsoft.Testing.Platform.Extensions.TestFramework; using TUnit.Core; @@ -9,7 +8,7 @@ namespace TUnit.Engine; -internal class TUnitInitializer(ICommandLineOptions commandLineOptions) +internal class TUnitInitializer(ICommandLineOptions commandLineOptions, IHookDiscoveryService hookDiscoveryService) { public void Initialize(ExecuteRequestContext context) { @@ -17,11 +16,8 @@ public void Initialize(ExecuteRequestContext context) SetUpExceptionListeners(); ParseParameters(); - // Discover hooks via reflection if in reflection mode - if (IsReflectionMode()) - { - DiscoverHooksViaReflection(); - } + // Discover hooks using the mode-specific service + hookDiscoveryService.DiscoverHooks(); if (!string.IsNullOrEmpty(TestContext.OutputDirectory)) { @@ -29,18 +25,6 @@ public void Initialize(ExecuteRequestContext context) } } - private bool IsReflectionMode() - { - return !SourceRegistrar.IsEnabled; - } - - [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code")] - [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling")] - private void DiscoverHooksViaReflection() - { - ReflectionHookDiscoveryService.DiscoverHooks(); - } - private void SetUpExceptionListeners() { Trace.Listeners.Insert(0, new ThrowListener()); diff --git a/TUnit.Engine/TestDiscoveryService.cs b/TUnit.Engine/TestDiscoveryService.cs index bb707e77e8..ad230e3453 100644 --- a/TUnit.Engine/TestDiscoveryService.cs +++ b/TUnit.Engine/TestDiscoveryService.cs @@ -48,6 +48,10 @@ public TestDiscoveryService(TestExecutor testExecutor, TestBuilderPipeline testB _testFilterService = testFilterService; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif public async Task DiscoverTests(string testSessionId, ITestExecutionFilter? filter, CancellationToken cancellationToken, bool isForExecution) { await _testExecutor.ExecuteBeforeTestDiscoveryHooksAsync(cancellationToken).ConfigureAwait(false); @@ -130,6 +134,10 @@ public async Task DiscoverTests(string testSessionId, ITest } /// Streams test discovery for parallel discovery and execution + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Assembly scanning uses dynamic type discovery and reflection")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif private async IAsyncEnumerable DiscoverTestsStreamAsync( string testSessionId, [EnumeratorCancellation] CancellationToken cancellationToken = default) @@ -159,6 +167,10 @@ private async IAsyncEnumerable DiscoverTestsStreamAsync( /// /// Simplified streaming test discovery without channels - matches source generation approach /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Generic test instantiation requires MakeGenericType")] + #endif public async IAsyncEnumerable DiscoverTestsFullyStreamingAsync( string testSessionId, ITestExecutionFilter? filter, diff --git a/TUnit.Engine/TestExecutor.cs b/TUnit.Engine/TestExecutor.cs index f4749de64f..a539649bec 100644 --- a/TUnit.Engine/TestExecutor.cs +++ b/TUnit.Engine/TestExecutor.cs @@ -51,6 +51,9 @@ await _beforeHookTaskCache.GetOrCreateBeforeTestSessionTask(() => /// Creates a test executor delegate that wraps the provided executor with hook orchestration. /// Uses focused services that follow SRP to manage lifecycle and execution. /// + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] + #endif public async Task ExecuteAsync(AbstractExecutableTest executableTest, CancellationToken cancellationToken) { @@ -242,8 +245,9 @@ public IContextProvider GetContextProvider() return _contextProvider; } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2075:Type.GetProperty does not have matching annotations", - Justification = "Only used for specific test class DisposalRegressionTests")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Test disposal may use reflection on properties")] +#endif internal static async Task DisposeTestInstance(AbstractExecutableTest test) { // Dispose the test instance if it's disposable diff --git a/TUnit.Engine/TestInitializer.cs b/TUnit.Engine/TestInitializer.cs index 09e5859366..92e92f4c16 100644 --- a/TUnit.Engine/TestInitializer.cs +++ b/TUnit.Engine/TestInitializer.cs @@ -20,6 +20,9 @@ public TestInitializer(EventReceiverOrchestrator eventReceiverOrchestrator, _objectTracker = objectTracker; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Object tracking may use reflection on properties")] + #endif public async Task InitializeTest(AbstractExecutableTest test, CancellationToken cancellationToken) { var testClassInstance = test.Context.TestDetails.ClassInstance; diff --git a/TUnit.Engine/TestSessionCoordinator.cs b/TUnit.Engine/TestSessionCoordinator.cs index ecada84098..0f7602236f 100644 --- a/TUnit.Engine/TestSessionCoordinator.cs +++ b/TUnit.Engine/TestSessionCoordinator.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Microsoft.Testing.Platform.Messages; using Microsoft.Testing.Platform.Requests; using TUnit.Core; @@ -20,6 +21,7 @@ internal sealed class TestSessionCoordinator : ITestExecutor, IDisposable, IAsyn private readonly IContextProvider _contextProvider; private readonly TestLifecycleCoordinator _lifecycleCoordinator; private readonly ITUnitMessageBus _messageBus; + private readonly IStaticPropertyInitializer _staticPropertyInitializer; public TestSessionCoordinator(EventReceiverOrchestrator eventReceiverOrchestrator, TUnitFrameworkLogger logger, @@ -27,7 +29,8 @@ public TestSessionCoordinator(EventReceiverOrchestrator eventReceiverOrchestrato TUnitServiceProvider serviceProvider, IContextProvider contextProvider, TestLifecycleCoordinator lifecycleCoordinator, - ITUnitMessageBus messageBus) + ITUnitMessageBus messageBus, + IStaticPropertyInitializer staticPropertyInitializer) { _eventReceiverOrchestrator = eventReceiverOrchestrator; _logger = logger; @@ -36,6 +39,7 @@ public TestSessionCoordinator(EventReceiverOrchestrator eventReceiverOrchestrato _lifecycleCoordinator = lifecycleCoordinator; _messageBus = messageBus; _testScheduler = testScheduler; + _staticPropertyInitializer = staticPropertyInitializer; } public async Task ExecuteTests( @@ -73,34 +77,14 @@ private async Task PrepareTestOrchestrator(List testList // Register all tests upfront so orchestrator knows total counts per class/assembly for lifecycle management _lifecycleCoordinator.RegisterTests(testList); - await InitializeStaticPropertiesAsync(cancellationToken); - } - - private async Task InitializeStaticPropertiesAsync(CancellationToken cancellationToken) - { - try - { - // Execute all registered global initializers (including static property initialization from source generation) - while (Sources.GlobalInitializers.TryDequeue(out var initializer)) - { - cancellationToken.ThrowIfCancellationRequested(); - await initializer(); - } - - // For reflection mode, also initialize static properties dynamically - if (!SourceRegistrar.IsEnabled) - { - await StaticPropertyReflectionInitializer.InitializeAllStaticPropertiesAsync(); - } - } - catch (Exception ex) - { - await _logger.LogErrorAsync($"Error during static property initialization: {ex}"); - throw; - } + await _staticPropertyInitializer.InitializeAsync(cancellationToken); } + #if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Test scheduler uses mode-specific services that handle reflection properly")] + [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Test scheduler uses mode-specific services that handle dynamic code properly")] + #endif private async Task ExecuteTestsCore(List testList, CancellationToken cancellationToken) { // Combine cancellation tokens diff --git a/TUnit.Engine/Utilities/ScopedAttributeFilter.cs b/TUnit.Engine/Utilities/ScopedAttributeFilter.cs index f16a989a2d..d546ad4bd5 100644 --- a/TUnit.Engine/Utilities/ScopedAttributeFilter.cs +++ b/TUnit.Engine/Utilities/ScopedAttributeFilter.cs @@ -14,8 +14,9 @@ internal static class ScopedAttributeFilter /// The type of objects to filter /// The collection of items to filter /// A filtered collection with only one instance per scoped attribute type - [UnconditionalSuppressMessage("Trimming", "IL2075:UnrecognizedReflectionPattern", - Justification = "IScopedAttribute types are preserved by the source generator")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Scoped attribute filtering uses Type.GetInterfaces and reflection")] +#endif public static List FilterScopedAttributes(IEnumerable items) where T : class { var result = new List(); @@ -63,10 +64,9 @@ public static List FilterScopedAttributes(IEnumerable items) where T : /// /// Checks if a type implements IScopedAttribute /// - [UnconditionalSuppressMessage("Trimming", "IL2070:UnrecognizedReflectionPattern", - Justification = "IScopedAttribute types are preserved by the source generator")] - [UnconditionalSuppressMessage("Trimming", "IL2075:UnrecognizedReflectionPattern", - Justification = "IScopedAttribute types are preserved by the source generator")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Interface checking uses Type.GetInterfaces")] +#endif public static bool IsScopedAttribute(Type type) { return type.GetInterfaces() @@ -76,8 +76,9 @@ public static bool IsScopedAttribute(Type type) /// /// Gets the scoped attribute type from an object that implements IScopedAttribute /// - [UnconditionalSuppressMessage("Trimming", "IL2075:UnrecognizedReflectionPattern", - Justification = "IScopedAttribute types are preserved by the source generator")] +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Scoped attribute type extraction uses Type.GetInterfaces")] +#endif public static Type? GetScopedAttributeType(object? obj) { if (obj == null) diff --git a/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs b/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs new file mode 100644 index 0000000000..5bbb404429 --- /dev/null +++ b/TUnit.Pipeline/Modules/PublishNugetTesterAOTModule.cs @@ -0,0 +1,80 @@ +using System.Runtime.InteropServices; +using ModularPipelines.Attributes; +using ModularPipelines.Context; +using ModularPipelines.DotNet.Extensions; +using ModularPipelines.DotNet.Options; +using ModularPipelines.Enums; +using ModularPipelines.Extensions; +using ModularPipelines.Git.Extensions; +using ModularPipelines.Models; +using ModularPipelines.Modules; + +namespace TUnit.Pipeline.Modules; + +[DependsOn] +[DependsOn] +[DependsOn] +public class PublishNugetTesterAOTModule : Module> +{ + protected override Task ShouldSkip(IPipelineContext context) + { + return Task.FromResult(EnvironmentVariables.IsNetFramework); + } + + protected override async Task?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken) + { + var results = new List(); + var version = await GetModule(); + + var testProject = context.Git() + .RootDirectory + .AssertExists() + .FindFile(x => x.Name == "TUnit.NugetTester.csproj") + .AssertExists(); + + // Test AOT publishing for net8.0 and net9.0 + foreach (var framework in new[] { "net8.0", "net9.0" }) + { + var result = await SubModule($"AOT-{framework}", async () => + { + return await context.DotNet().Publish(new DotNetPublishOptions(testProject) + { + RuntimeIdentifier = GetRuntimeIdentifier(), + Configuration = Configuration.Release, + OutputDirectory = $"NUGETTESTER_AOT_{framework}", + Properties = + [ + new KeyValue("Aot", "true"), + new KeyValue("TUnitVersion", version.Value!.SemVer!) + ], + Framework = framework, + CommandLogging = CommandLogging.Input | CommandLogging.Error | CommandLogging.Duration | CommandLogging.ExitCode + }, cancellationToken); + }); + + results.Add(result); + } + + return results; + } + + private string GetRuntimeIdentifier() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return "linux-x64"; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return "win-x64"; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return "osx-arm64"; + } + + throw new ArgumentException("Unknown platform"); + } +} diff --git a/TUnit.Playwright/WorkerAwareTest.cs b/TUnit.Playwright/WorkerAwareTest.cs index 2291ce1616..9da66688bf 100644 --- a/TUnit.Playwright/WorkerAwareTest.cs +++ b/TUnit.Playwright/WorkerAwareTest.cs @@ -69,6 +69,9 @@ protected bool TestOk(TestContext testContext) return testContext.Result?.State is TestState.Passed or TestState.Skipped; } + #if NET6_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Type comes from runtime objects that cannot be annotated")] + #endif public ValueTask OnTestRegistered(TestRegisteredContext context) { if (UseDefaultParallelLimiter) diff --git a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt index 32ed0bae3c..8752db4b70 100644 --- a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt @@ -71,6 +71,7 @@ namespace public .<.> Satisfy(?> asyncMapper, <..IValueSource, .> assert, [.("asyncMapper")] string mapperExpression = "", [.("assert")] string assertionBuilderExpression = "") { } public .<.> Satisfy( mapper, <..IValueSource, .> assert, [.("mapper")] string mapperExpression = "", [.("assert")] string assertionBuilderExpression = "") { } } + [.("Trimming", "IL2075", Justification="AOT mode uses the attributed compiler type instead of the runtime GetType.")] public static class Compare { public static .<.ComparisonFailure> CheckEquivalent<[.(..None | ..PublicFields | ..NonPublicFields | ..PublicProperties | ..NonPublicProperties)] TActual, [.(..None | ..PublicFields | ..NonPublicFields | ..PublicProperties | ..NonPublicProperties)] TExpected>(TActual actual, TExpected expected, .CompareOptions options, int? index) { } @@ -326,8 +327,6 @@ namespace . { public PropertyEqualsExpectedValueAssertCondition(.<> propertySelector, TPropertyType expected, bool isEqual) { } protected override string GetExpectation() { } - [.("Expression compilation requires dynamic code generation")] - [.("Expression compilation requires unreferenced code")] protected override .<.> GetResult(TRootObjectType? actualValue, TPropertyType? expectedValue) { } } } diff --git a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt index 305f38c745..fc404b40de 100644 --- a/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt @@ -71,6 +71,7 @@ namespace public .<.> Satisfy(?> asyncMapper, <..IValueSource, .> assert, [.("asyncMapper")] string mapperExpression = "", [.("assert")] string assertionBuilderExpression = "") { } public .<.> Satisfy( mapper, <..IValueSource, .> assert, [.("mapper")] string mapperExpression = "", [.("assert")] string assertionBuilderExpression = "") { } } + [.("Trimming", "IL2075", Justification="AOT mode uses the attributed compiler type instead of the runtime GetType.")] public static class Compare { public static .<.ComparisonFailure> CheckEquivalent<[.(..None | ..PublicFields | ..NonPublicFields | ..PublicProperties | ..NonPublicProperties)] TActual, [.(..None | ..PublicFields | ..NonPublicFields | ..PublicProperties | ..NonPublicProperties)] TExpected>(TActual actual, TExpected expected, .CompareOptions options, int? index) { } @@ -326,8 +327,6 @@ namespace . { public PropertyEqualsExpectedValueAssertCondition(.<> propertySelector, TPropertyType expected, bool isEqual) { } protected override string GetExpectation() { } - [.("Expression compilation requires dynamic code generation")] - [.("Expression compilation requires unreferenced code")] protected override .<.> GetResult(TRootObjectType? actualValue, TPropertyType? expectedValue) { } } } diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt index 207dfba759..9309930a6b 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt @@ -66,19 +66,27 @@ namespace public override .ArgumentDisplayFormatter Formatter { get; } } [(.Class | .Method | .Property, AllowMultiple=true)] - public sealed class ArgumentsAttribute : , .IDataSourceAttribute + public sealed class ArgumentsAttribute : , .IDataSourceAttribute, ., . { public ArgumentsAttribute(params object?[]? values) { } + public int Order { get; } + public string? Skip { get; set; } public object?[] Values { get; } - [.(typeof(.ArgumentsAttribute.d__4))] + [.(typeof(.ArgumentsAttribute.d__8))] public .<<.>> GetDataRowsAsync(.DataGeneratorMetadata dataGeneratorMetadata) { } + [.("Type comes from runtime objects that cannot be annotated")] + public . OnTestRegistered(.TestRegisteredContext context) { } } [(.Class | .Method | .Property, AllowMultiple=true)] - public sealed class ArgumentsAttribute : .TypedDataSourceAttribute + public sealed class ArgumentsAttribute : .TypedDataSourceAttribute, ., . { public ArgumentsAttribute(T value) { } - [.(typeof(.ArgumentsAttribute.d__2))] + public int Order { get; } + public string? Skip { get; set; } + [.(typeof(.ArgumentsAttribute.d__6))] public override .<<.>> GetTypedDataRowsAsync(.DataGeneratorMetadata dataGeneratorMetadata) { } + [.("Type comes from runtime objects that cannot be annotated")] + public . OnTestRegistered(.TestRegisteredContext context) { } } public class Artifact { @@ -112,11 +120,15 @@ namespace public static . Convert( action) { } public static . Convert(<.> action) { } public static . Convert(<.> action) { } + [.("ConvertObject may require dynamic invocation for custom awaitable types. For AOT " + + "compatibility, use Task or ValueTask directly.")] + [.("ConvertObject uses reflection to handle custom awaitable types and F# async. For " + + "AOT compatibility, use Task or ValueTask directly.")] public static . ConvertObject(object? invoke) { } - [.("Trimming", "IL2075:\'this\' argument does not satisfy \'DynamicallyAccessedMembersAttribute\' in " + - "call to target method. The return value of the source method does not have match" + - "ing annotations.", Justification="GetAwaiter pattern detection for custom awaitables. For AOT, use standard Task/Va" + - "lueTask types or implement IAsyncEnumerable.")] + [.("Custom awaitable handling may require dynamic invocation. For AOT, use Task/Value" + + "Task.")] + [.("GetAwaiter pattern detection requires reflection for custom awaitable types. For " + + "AOT, use Task/ValueTask.")] public static bool TryGetAwaitableTask(object awaitable, [.(true)] out .? task) { } } [(.Class | .Method | .Property, AllowMultiple=true)] @@ -237,60 +249,50 @@ namespace public required string TestSessionId { get; init; } } [(.Class | .Method | .Property, AllowMultiple=true)] - [.("Trimming", "IL2109:Type derives from type with \'RequiresUnreferencedCodeAttribute\' which can " + - "break functionality when trimming application code", Justification="The specific constructors (1-5 parameters) are AOT-compatible when used with type" + - "of() expressions. Only the params constructor is incompatible.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public sealed class ClassDataSourceAttribute : .UntypedDataSourceGeneratorAttribute { - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type) { } [.("Reflection")] [.("Reflection")] public ClassDataSourceAttribute(params [] types) { } - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type2) { } - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type2, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type3) { } - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type2, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type3, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type4) { } - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type2, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type3, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type4, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type5) { } public string[] Keys { get; set; } public .SharedType[] Shared { get; set; } - [.("Trimming", "IL2062:The parameter of method has a DynamicallyAccessedMembersAttribute, but the" + - " value passed to it can not be statically analyzed.", Justification="The _types array is populated from constructor parameters that have DynamicallyAc" + - "cessedMembers attributes, ensuring the required members are preserved at the cal" + - "l site.")] + [.("Reflection")] + [.("Reflection")] protected override .<> GenerateDataSources(.DataGeneratorMetadata dataGeneratorMetadata) { } public . GetKeys() { } public .<.SharedType> GetSharedTypes() { } @@ -518,6 +520,7 @@ namespace protected virtual void ConfigureThread(.Thread thread) { } protected override sealed . ExecuteAsync(<.> action) { } protected virtual void Initialize() { } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } public class DefaultExecutor : .GenericAbstractExecutor @@ -896,12 +899,14 @@ namespace public MatrixAttribute(params T?[]? objects) { } } [(.Class | .Method)] - [.("AOT", "IL2109:Type \'MatrixDataSourceAttribute\' derives from base class with RequiresUnre" + - "ferencedCodeAttribute", Justification="Matrix data source implementation is AOT-compatible with proper enum field preser" + - "vation")] + [.("MatrixDataSource may process enum types dynamically")] + [.("MatrixDataSource uses reflection to access parameter attributes and test metadata" + + ". For AOT compatibility, consider using explicit data sources.")] public sealed class MatrixDataSourceAttribute : .UntypedDataSourceGeneratorAttribute, .IAccessesInstanceData { public MatrixDataSourceAttribute() { } + [.("Matrix generation may process enum types dynamically")] + [.("Matrix generation requires reflection")] protected override .<> GenerateDataSources(.DataGeneratorMetadata dataGeneratorMetadata) { } } [(.Class | .Method, AllowMultiple=true)] @@ -950,12 +955,10 @@ namespace public ? ClassProvidingDataSource { get; } public <.DataGeneratorMetadata, .<<.>>>? Factory { get; set; } public string MethodNameProvidingDataSource { get; } - [.("AOT", "IL2072:UnrecognizedReflectionPattern", Justification="Method data sources require runtime discovery and invocation of methods. The targ" + - "et type is determined dynamically from test metadata. For AOT scenarios, source " + - "generation should be used to pre-compile method references.")] - [.("AOT", "IL2075:UnrecognizedReflectionPattern", Justification="GetType() is called on runtime objects from test class instances. The actual type" + - "s cannot be statically determined. For AOT scenarios, source generation captures" + - " these types at compile time.")] + [.("Trimming", "IL2072", Justification="Method data sources require runtime discovery. AOT users should use Factory prope" + + "rty.")] + [.("Trimming", "IL2075", Justification="Method data sources require runtime discovery. AOT users should use Factory prope" + + "rty.")] [.(typeof(.MethodDataSourceAttribute.d__17))] public .<<.>> GetDataRowsAsync(.DataGeneratorMetadata dataGeneratorMetadata) { } } @@ -1027,12 +1030,13 @@ namespace { public ParallelLimiterAttribute() { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } [.DebuggerDisplay("{Type} {Name}")] public class ParameterMetadata : .MemberMetadata, <.ParameterMetadata> { - public ParameterMetadata([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] Type) { } + public ParameterMetadata([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicProperties)] Type) { } public object? CachedDefaultValue { get; init; } public bool? CachedIsOptional { get; init; } public bool? CachedIsParams { get; init; } @@ -1042,11 +1046,12 @@ namespace public bool IsParams { get; } public int Position { get; init; } public required .ParameterInfo ReflectionInfo { get; set; } + [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicProperties)] public override Type { get; init; } public required .TypeReference TypeReference { get; init; } } [.DebuggerDisplay("{Type} {Name}")] - public class ParameterMetadata<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] T> : .ParameterMetadata, <.ParameterMetadata> + public class ParameterMetadata<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicProperties)] T> : .ParameterMetadata, <.ParameterMetadata> { public ParameterMetadata() { } } @@ -1101,9 +1106,7 @@ namespace } public static class PropertySourceRegistry { - [.("Trimming", "IL2070", Justification="Reflection discovery is used when source-generated metadata is not available. Thi" + - "s supports dynamically loaded assemblies and runtime property injection. For AOT" + - " scenarios, the source generator pre-discovers all injectable properties.")] + [.("Reflection discovery is used when source-generated metadata is not available")] public static .PropertyInjectionData[] DiscoverInjectableProperties([.(..None | ..PublicFields | ..NonPublicFields | ..PublicProperties)] type) { } [return: .(new string[] { "Type", @@ -1175,6 +1178,7 @@ namespace public SkipAttribute(string reason) { } public int Order { get; } public string Reason { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } public virtual . ShouldSkip(.TestRegisteredContext context) { } } @@ -1214,16 +1218,12 @@ namespace public static readonly .<..IPropertySource> PropertySources; public static readonly .<, .<..ITestSource>> TestSources; } - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access", Justification="Reflection mode requires dynamic access")] - [.("Trimming", "IL2067:Target parameter argument does not satisfy annotation requirements", Justification="Reflection mode requires dynamic access")] - [.("Trimming", "IL2070:\'this\' argument does not satisfy \'" + - "perties\'", Justification="Reflection mode requires dynamic access")] - [.("Trimming", "IL2075:\'this\' argument does not satisfy \'" + - "perties\'", Justification="Reflection mode requires dynamic access")] + [.("Reflection mode requires dynamic access for static property initialization")] public static class StaticPropertyReflectionInitializer { + [.("Data source initialization may require dynamic code generation")] public static . InitializeAllStaticPropertiesAsync() { } + [.("Data source initialization may require dynamic code generation")] public static . InitializeStaticPropertiesForType( type) { } } public class TUnitAttribute : { } @@ -1269,6 +1269,7 @@ namespace public .<.Artifact> Artifacts { get; } public .CancellationToken CancellationToken { get; set; } public .ClassHookContext ClassContext { get; } + public int CurrentRetryAttempt { get; } public .<.TestDetails> Dependencies { get; } public ? DisplayNameFormatter { get; set; } public .TestContextEvents Events { get; } @@ -1294,7 +1295,6 @@ namespace public .<.Timing> Timings { get; } public static . Configuration { get; } public new static .TestContext? Current { get; } - [get: .("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification="Dynamic code check implemented")] public static string? OutputDirectory { get; } public static .> Parameters { get; } public static string WorkingDirectory { get; set; } @@ -1866,6 +1866,7 @@ namespace .Executors public CultureAttribute(.CultureInfo cultureInfo) { } public CultureAttribute(string cultureName) { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } public class HookExecutorAttribute : .TUnitAttribute @@ -1890,6 +1891,7 @@ namespace .Executors { public STAThreadExecutorAttribute() { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } [(.Assembly | .Class | .Method)] @@ -1897,6 +1899,7 @@ namespace .Executors { public TestExecutorAttribute([.(..PublicConstructors)] type) { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } [(.Assembly | .Class | .Method)] @@ -1905,6 +1908,7 @@ namespace .Executors { public TestExecutorAttribute() { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } } @@ -1929,6 +1933,7 @@ namespace .Extensions { [.("Adding dynamic tests requires reflection which is not supported in native AOT sce" + "narios.")] + [.("Dynamic test metadata creation uses reflection")] public static . AddDynamicTest<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicFields | ..NonPublicFields | ..PublicProperties)] T>(this .TestContext context, .DynamicTest dynamicTest) where T : class { } public static string GetClassTypeName(this .TestContext context) { } @@ -1946,15 +1951,11 @@ namespace .Helpers } public static class CastHelper { - [.("AOT", "IL3050", Justification="Reflection-based conversion is a fallback for runtime scenarios. AOT applications" + - " should use explicit conversions.")] - [.("Trimming", "IL2072", Justification="Type conversion uses DynamicallyAccessedMembers for known conversion patterns. Fo" + - "r AOT scenarios, use explicit type conversions.")] + [.("Dynamic type conversion may require runtime code generation")] + [.("Type conversion uses reflection for custom conversions")] public static object? Cast([.(..None | ..PublicMethods | ..NonPublicMethods)] type, object? value) { } - [.("AOT", "IL3050", Justification="Reflection-based conversion is a fallback for runtime scenarios. AOT applications" + - " should use explicit conversions.")] - [.("Trimming", "IL2072", Justification="Type conversion uses DynamicallyAccessedMembers for known conversion patterns. Fo" + - "r AOT scenarios, use explicit type conversions.")] + [.("Dynamic type conversion may require runtime code generation")] + [.("Type conversion uses reflection for custom conversions")] public static T? Cast<[.(..None | ..PublicMethods | ..NonPublicMethods)] T>(object? value) { } public static .MethodInfo? GetConversionMethod([.(..None | ..PublicMethods | ..NonPublicMethods)] baseType, [.(..None | ..PublicMethods | ..NonPublicMethods)] targetType) { } } @@ -2015,6 +2016,8 @@ namespace .Helpers public static <.>[] ProcessTestDataSource(T data, int expectedParameterCount = -1) { } public static void RegisterPropertyInitializer( initializer) { } public static void RegisterTypeCreator(<.MethodMetadata, string, .> creator) { } + [.("Data source resolution may require dynamic code generation")] + [.("Property types are resolved through reflection")] public static . ResolveDataSourceForPropertyAsync([.(..None | ..PublicParameterlessConstructor | ..PublicFields | ..NonPublicFields | ..PublicProperties)] containingType, string propertyName, .MethodMetadata testInformation, string testSessionId) { } public static . ResolveDataSourcePropertyAsync(object instance, string propertyName, .MethodMetadata testInformation, string testSessionId) { } public static object?[] ToObjectArray(this object? item) { } @@ -2030,8 +2033,6 @@ namespace .Helpers public static object?[] UnwrapTuple( tuple) { } public static object?[] UnwrapTuple( tuple) { } public static object?[] UnwrapTuple( tuple) { } - [.("Trimming", "IL2091:Target generic argument does not satisfy \'DynamicallyAccessedMembersAttrib" + - "ute\' in target method or type.", Justification="We handle specific known tuple types without reflection")] public static object?[] UnwrapTupleAot(object? value) { } } public static class DecimalParsingHelper @@ -2042,8 +2043,7 @@ namespace .Helpers { public static GetGenericTypeDefinition( type) { } public static bool IsConstructedGenericType( type) { } - [.("AOT", "IL2055:UnrecognizedReflectionPattern", Justification="MakeGenericType is used as a fallback. AOT analyzer warns at compile time.")] - [.("AOT", "IL3050:RequiresDynamicCode", Justification="MakeGenericType is used as a fallback. AOT analyzer warns at compile time.")] + [.("MakeGenericType requires runtime code generation")] public static MakeGenericTypeSafe( genericTypeDefinition, params [] typeArguments) { } } public class ProcessorCountParallelLimit : . @@ -2074,7 +2074,7 @@ namespace .Helpers } public static class TupleHelper { - [.("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", Justification="Reflection is used as a fallback. AOT analyzer warns at compile time.")] + [.("Tuple expansion uses reflection as fallback")] public static . ExpandTupleArray(object? value) { } public static bool IsTupleArrayType( type) { } public static bool IsTupleType(. tuple) { } @@ -2183,9 +2183,7 @@ namespace .Hooks public bool Execute(.AssemblyHookContext context, .CancellationToken cancellationToken) { } public . ExecuteAsync(.AssemblyHookContext context, .CancellationToken cancellationToken) { } } - [.("Trimming", "IL2111:Method with parameters or return value with `DynamicallyAccessedMembersAtt" + - "ribute` is accessed via reflection. Trimmer can\'t guarantee availability of the " + - "requirements of the method.")] + [.("Method with DynamicallyAccessedMembersAttribute accessed via reflection")] public class LastTestInClassAdapter : .<.ClassHookContext> { public LastTestInClassAdapter(. lastTestInClassEventReceiver, .TestContext testContext) { } @@ -2355,12 +2353,14 @@ namespace .Interfaces } public interface ITestRegisteredEventReceiver : . { + [.("Type comes from runtime objects that cannot be annotated")] . OnTestRegistered(.TestRegisteredContext context); } public interface ITestRegistry { [.("Adding dynamic tests requires runtime compilation and reflection which are not su" + "pported in native AOT scenarios.")] + [.("Dynamic test metadata creation uses reflection")] . AddDynamicTest<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicFields | ..NonPublicFields | ..PublicProperties)] T>(.TestContext context, .DynamicTest dynamicTest) where T : class; } diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt index 058df04e64..5c7f7cea65 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt @@ -66,19 +66,27 @@ namespace public override .ArgumentDisplayFormatter Formatter { get; } } [(.Class | .Method | .Property, AllowMultiple=true)] - public sealed class ArgumentsAttribute : , .IDataSourceAttribute + public sealed class ArgumentsAttribute : , .IDataSourceAttribute, ., . { public ArgumentsAttribute(params object?[]? values) { } + public int Order { get; } + public string? Skip { get; set; } public object?[] Values { get; } - [.(typeof(.ArgumentsAttribute.d__4))] + [.(typeof(.ArgumentsAttribute.d__8))] public .<<.>> GetDataRowsAsync(.DataGeneratorMetadata dataGeneratorMetadata) { } + [.("Type comes from runtime objects that cannot be annotated")] + public . OnTestRegistered(.TestRegisteredContext context) { } } [(.Class | .Method | .Property, AllowMultiple=true)] - public sealed class ArgumentsAttribute : .TypedDataSourceAttribute + public sealed class ArgumentsAttribute : .TypedDataSourceAttribute, ., . { public ArgumentsAttribute(T value) { } - [.(typeof(.ArgumentsAttribute.d__2))] + public int Order { get; } + public string? Skip { get; set; } + [.(typeof(.ArgumentsAttribute.d__6))] public override .<<.>> GetTypedDataRowsAsync(.DataGeneratorMetadata dataGeneratorMetadata) { } + [.("Type comes from runtime objects that cannot be annotated")] + public . OnTestRegistered(.TestRegisteredContext context) { } } public class Artifact { @@ -112,11 +120,15 @@ namespace public static . Convert( action) { } public static . Convert(<.> action) { } public static . Convert(<.> action) { } + [.("ConvertObject may require dynamic invocation for custom awaitable types. For AOT " + + "compatibility, use Task or ValueTask directly.")] + [.("ConvertObject uses reflection to handle custom awaitable types and F# async. For " + + "AOT compatibility, use Task or ValueTask directly.")] public static . ConvertObject(object? invoke) { } - [.("Trimming", "IL2075:\'this\' argument does not satisfy \'DynamicallyAccessedMembersAttribute\' in " + - "call to target method. The return value of the source method does not have match" + - "ing annotations.", Justification="GetAwaiter pattern detection for custom awaitables. For AOT, use standard Task/Va" + - "lueTask types or implement IAsyncEnumerable.")] + [.("Custom awaitable handling may require dynamic invocation. For AOT, use Task/Value" + + "Task.")] + [.("GetAwaiter pattern detection requires reflection for custom awaitable types. For " + + "AOT, use Task/ValueTask.")] public static bool TryGetAwaitableTask(object awaitable, [.(true)] out .? task) { } } [(.Class | .Method | .Property, AllowMultiple=true)] @@ -237,60 +249,50 @@ namespace public required string TestSessionId { get; init; } } [(.Class | .Method | .Property, AllowMultiple=true)] - [.("Trimming", "IL2109:Type derives from type with \'RequiresUnreferencedCodeAttribute\' which can " + - "break functionality when trimming application code", Justification="The specific constructors (1-5 parameters) are AOT-compatible when used with type" + - "of() expressions. Only the params constructor is incompatible.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public sealed class ClassDataSourceAttribute : .UntypedDataSourceGeneratorAttribute { - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type) { } [.("Reflection")] [.("Reflection")] public ClassDataSourceAttribute(params [] types) { } - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type2) { } - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type2, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type3) { } - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type2, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type3, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type4) { } - [.("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break fu" + - "nctionality when AOT compiling.", Justification="These constructors are AOT-compatible when types are specified using typeof() at " + - "compile time. Only the params constructor requires dynamic code.")] - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access otherwise can break functionality when trimming application code", Justification="These constructors delegate to the params constructor but are AOT-safe when used " + - "with typeof() expressions at compile time. The DynamicallyAccessedMembers annota" + - "tions ensure required members are preserved.")] + [.("ClassDataSourceAttribute may require runtime type generation. For AOT compatibili" + + "ty, use strongly-typed ClassDataSourceAttribute instead.")] + [.("ClassDataSourceAttribute uses reflection to instantiate and access test data clas" + + "ses. For AOT compatibility, use strongly-typed ClassDataSourceAttribute inste" + + "ad.")] public ClassDataSourceAttribute([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type2, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type3, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type4, [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] type5) { } public string[] Keys { get; set; } public .SharedType[] Shared { get; set; } - [.("Trimming", "IL2062:The parameter of method has a DynamicallyAccessedMembersAttribute, but the" + - " value passed to it can not be statically analyzed.", Justification="The _types array is populated from constructor parameters that have DynamicallyAc" + - "cessedMembers attributes, ensuring the required members are preserved at the cal" + - "l site.")] + [.("Reflection")] + [.("Reflection")] protected override .<> GenerateDataSources(.DataGeneratorMetadata dataGeneratorMetadata) { } public . GetKeys() { } public .<.SharedType> GetSharedTypes() { } @@ -518,6 +520,7 @@ namespace protected virtual void ConfigureThread(.Thread thread) { } protected override sealed . ExecuteAsync(<.> action) { } protected virtual void Initialize() { } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } public class DefaultExecutor : .GenericAbstractExecutor @@ -896,12 +899,14 @@ namespace public MatrixAttribute(params T?[]? objects) { } } [(.Class | .Method)] - [.("AOT", "IL2109:Type \'MatrixDataSourceAttribute\' derives from base class with RequiresUnre" + - "ferencedCodeAttribute", Justification="Matrix data source implementation is AOT-compatible with proper enum field preser" + - "vation")] + [.("MatrixDataSource may process enum types dynamically")] + [.("MatrixDataSource uses reflection to access parameter attributes and test metadata" + + ". For AOT compatibility, consider using explicit data sources.")] public sealed class MatrixDataSourceAttribute : .UntypedDataSourceGeneratorAttribute, .IAccessesInstanceData { public MatrixDataSourceAttribute() { } + [.("Matrix generation may process enum types dynamically")] + [.("Matrix generation requires reflection")] protected override .<> GenerateDataSources(.DataGeneratorMetadata dataGeneratorMetadata) { } } [(.Class | .Method, AllowMultiple=true)] @@ -950,12 +955,10 @@ namespace public ? ClassProvidingDataSource { get; } public <.DataGeneratorMetadata, .<<.>>>? Factory { get; set; } public string MethodNameProvidingDataSource { get; } - [.("AOT", "IL2072:UnrecognizedReflectionPattern", Justification="Method data sources require runtime discovery and invocation of methods. The targ" + - "et type is determined dynamically from test metadata. For AOT scenarios, source " + - "generation should be used to pre-compile method references.")] - [.("AOT", "IL2075:UnrecognizedReflectionPattern", Justification="GetType() is called on runtime objects from test class instances. The actual type" + - "s cannot be statically determined. For AOT scenarios, source generation captures" + - " these types at compile time.")] + [.("Trimming", "IL2072", Justification="Method data sources require runtime discovery. AOT users should use Factory prope" + + "rty.")] + [.("Trimming", "IL2075", Justification="Method data sources require runtime discovery. AOT users should use Factory prope" + + "rty.")] [.(typeof(.MethodDataSourceAttribute.d__17))] public .<<.>> GetDataRowsAsync(.DataGeneratorMetadata dataGeneratorMetadata) { } } @@ -1027,12 +1030,13 @@ namespace { public ParallelLimiterAttribute() { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } [.DebuggerDisplay("{Type} {Name}")] public class ParameterMetadata : .MemberMetadata, <.ParameterMetadata> { - public ParameterMetadata([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] Type) { } + public ParameterMetadata([.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicProperties)] Type) { } public object? CachedDefaultValue { get; init; } public bool? CachedIsOptional { get; init; } public bool? CachedIsParams { get; init; } @@ -1042,11 +1046,12 @@ namespace public bool IsParams { get; } public int Position { get; init; } public required .ParameterInfo ReflectionInfo { get; set; } + [.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicProperties)] public override Type { get; init; } public required .TypeReference TypeReference { get; init; } } [.DebuggerDisplay("{Type} {Name}")] - public class ParameterMetadata<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..PublicMethods | ..PublicProperties)] T> : .ParameterMetadata, <.ParameterMetadata> + public class ParameterMetadata<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicProperties)] T> : .ParameterMetadata, <.ParameterMetadata> { public ParameterMetadata() { } } @@ -1101,9 +1106,7 @@ namespace } public static class PropertySourceRegistry { - [.("Trimming", "IL2070", Justification="Reflection discovery is used when source-generated metadata is not available. Thi" + - "s supports dynamically loaded assemblies and runtime property injection. For AOT" + - " scenarios, the source generator pre-discovers all injectable properties.")] + [.("Reflection discovery is used when source-generated metadata is not available")] public static .PropertyInjectionData[] DiscoverInjectableProperties([.(..None | ..PublicFields | ..NonPublicFields | ..PublicProperties)] type) { } [return: .(new string[] { "Type", @@ -1175,6 +1178,7 @@ namespace public SkipAttribute(string reason) { } public int Order { get; } public string Reason { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } public virtual . ShouldSkip(.TestRegisteredContext context) { } } @@ -1214,16 +1218,12 @@ namespace public static readonly .<..IPropertySource> PropertySources; public static readonly .<, .<..ITestSource>> TestSources; } - [.("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic" + - " access", Justification="Reflection mode requires dynamic access")] - [.("Trimming", "IL2067:Target parameter argument does not satisfy annotation requirements", Justification="Reflection mode requires dynamic access")] - [.("Trimming", "IL2070:\'this\' argument does not satisfy \'" + - "perties\'", Justification="Reflection mode requires dynamic access")] - [.("Trimming", "IL2075:\'this\' argument does not satisfy \'" + - "perties\'", Justification="Reflection mode requires dynamic access")] + [.("Reflection mode requires dynamic access for static property initialization")] public static class StaticPropertyReflectionInitializer { + [.("Data source initialization may require dynamic code generation")] public static . InitializeAllStaticPropertiesAsync() { } + [.("Data source initialization may require dynamic code generation")] public static . InitializeStaticPropertiesForType( type) { } } public class TUnitAttribute : { } @@ -1269,6 +1269,7 @@ namespace public .<.Artifact> Artifacts { get; } public .CancellationToken CancellationToken { get; set; } public .ClassHookContext ClassContext { get; } + public int CurrentRetryAttempt { get; } public .<.TestDetails> Dependencies { get; } public ? DisplayNameFormatter { get; set; } public .TestContextEvents Events { get; } @@ -1294,7 +1295,6 @@ namespace public .<.Timing> Timings { get; } public static . Configuration { get; } public new static .TestContext? Current { get; } - [get: .("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification="Dynamic code check implemented")] public static string? OutputDirectory { get; } public static .> Parameters { get; } public static string WorkingDirectory { get; set; } @@ -1866,6 +1866,7 @@ namespace .Executors public CultureAttribute(.CultureInfo cultureInfo) { } public CultureAttribute(string cultureName) { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } public class HookExecutorAttribute : .TUnitAttribute @@ -1890,6 +1891,7 @@ namespace .Executors { public STAThreadExecutorAttribute() { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } [(.Assembly | .Class | .Method)] @@ -1897,6 +1899,7 @@ namespace .Executors { public TestExecutorAttribute([.(..PublicConstructors)] type) { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } [(.Assembly | .Class | .Method)] @@ -1905,6 +1908,7 @@ namespace .Executors { public TestExecutorAttribute() { } public int Order { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } } } @@ -1929,6 +1933,7 @@ namespace .Extensions { [.("Adding dynamic tests requires reflection which is not supported in native AOT sce" + "narios.")] + [.("Dynamic test metadata creation uses reflection")] public static . AddDynamicTest<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicFields | ..NonPublicFields | ..PublicProperties)] T>(this .TestContext context, .DynamicTest dynamicTest) where T : class { } public static string GetClassTypeName(this .TestContext context) { } @@ -1946,15 +1951,11 @@ namespace .Helpers } public static class CastHelper { - [.("AOT", "IL3050", Justification="Reflection-based conversion is a fallback for runtime scenarios. AOT applications" + - " should use explicit conversions.")] - [.("Trimming", "IL2072", Justification="Type conversion uses DynamicallyAccessedMembers for known conversion patterns. Fo" + - "r AOT scenarios, use explicit type conversions.")] + [.("Dynamic type conversion may require runtime code generation")] + [.("Type conversion uses reflection for custom conversions")] public static object? Cast([.(..None | ..PublicMethods | ..NonPublicMethods)] type, object? value) { } - [.("AOT", "IL3050", Justification="Reflection-based conversion is a fallback for runtime scenarios. AOT applications" + - " should use explicit conversions.")] - [.("Trimming", "IL2072", Justification="Type conversion uses DynamicallyAccessedMembers for known conversion patterns. Fo" + - "r AOT scenarios, use explicit type conversions.")] + [.("Dynamic type conversion may require runtime code generation")] + [.("Type conversion uses reflection for custom conversions")] public static T? Cast<[.(..None | ..PublicMethods | ..NonPublicMethods)] T>(object? value) { } public static .MethodInfo? GetConversionMethod([.(..None | ..PublicMethods | ..NonPublicMethods)] baseType, [.(..None | ..PublicMethods | ..NonPublicMethods)] targetType) { } } @@ -2015,6 +2016,8 @@ namespace .Helpers public static <.>[] ProcessTestDataSource(T data, int expectedParameterCount = -1) { } public static void RegisterPropertyInitializer( initializer) { } public static void RegisterTypeCreator(<.MethodMetadata, string, .> creator) { } + [.("Data source resolution may require dynamic code generation")] + [.("Property types are resolved through reflection")] public static . ResolveDataSourceForPropertyAsync([.(..None | ..PublicParameterlessConstructor | ..PublicFields | ..NonPublicFields | ..PublicProperties)] containingType, string propertyName, .MethodMetadata testInformation, string testSessionId) { } public static . ResolveDataSourcePropertyAsync(object instance, string propertyName, .MethodMetadata testInformation, string testSessionId) { } public static object?[] ToObjectArray(this object? item) { } @@ -2030,8 +2033,6 @@ namespace .Helpers public static object?[] UnwrapTuple( tuple) { } public static object?[] UnwrapTuple( tuple) { } public static object?[] UnwrapTuple( tuple) { } - [.("Trimming", "IL2091:Target generic argument does not satisfy \'DynamicallyAccessedMembersAttrib" + - "ute\' in target method or type.", Justification="We handle specific known tuple types without reflection")] public static object?[] UnwrapTupleAot(object? value) { } } public static class DecimalParsingHelper @@ -2042,8 +2043,7 @@ namespace .Helpers { public static GetGenericTypeDefinition( type) { } public static bool IsConstructedGenericType( type) { } - [.("AOT", "IL2055:UnrecognizedReflectionPattern", Justification="MakeGenericType is used as a fallback. AOT analyzer warns at compile time.")] - [.("AOT", "IL3050:RequiresDynamicCode", Justification="MakeGenericType is used as a fallback. AOT analyzer warns at compile time.")] + [.("MakeGenericType requires runtime code generation")] public static MakeGenericTypeSafe( genericTypeDefinition, params [] typeArguments) { } } public class ProcessorCountParallelLimit : . @@ -2074,7 +2074,7 @@ namespace .Helpers } public static class TupleHelper { - [.("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", Justification="Reflection is used as a fallback. AOT analyzer warns at compile time.")] + [.("Tuple expansion uses reflection as fallback")] public static . ExpandTupleArray(object? value) { } public static bool IsTupleArrayType( type) { } public static bool IsTupleType(. tuple) { } @@ -2183,9 +2183,7 @@ namespace .Hooks public bool Execute(.AssemblyHookContext context, .CancellationToken cancellationToken) { } public . ExecuteAsync(.AssemblyHookContext context, .CancellationToken cancellationToken) { } } - [.("Trimming", "IL2111:Method with parameters or return value with `DynamicallyAccessedMembersAtt" + - "ribute` is accessed via reflection. Trimmer can\'t guarantee availability of the " + - "requirements of the method.")] + [.("Method with DynamicallyAccessedMembersAttribute accessed via reflection")] public class LastTestInClassAdapter : .<.ClassHookContext> { public LastTestInClassAdapter(. lastTestInClassEventReceiver, .TestContext testContext) { } @@ -2355,12 +2353,14 @@ namespace .Interfaces } public interface ITestRegisteredEventReceiver : . { + [.("Type comes from runtime objects that cannot be annotated")] . OnTestRegistered(.TestRegisteredContext context); } public interface ITestRegistry { [.("Adding dynamic tests requires runtime compilation and reflection which are not su" + "pported in native AOT scenarios.")] + [.("Dynamic test metadata creation uses reflection")] . AddDynamicTest<[.(..None | ..PublicParameterlessConstructor | ..PublicConstructors | ..NonPublicConstructors | ..PublicMethods | ..NonPublicMethods | ..PublicFields | ..NonPublicFields | ..PublicProperties)] T>(.TestContext context, .DynamicTest dynamicTest) where T : class; } diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt index 0541337705..c50d5ed77e 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt @@ -66,19 +66,25 @@ namespace public override .ArgumentDisplayFormatter Formatter { get; } } [(.Class | .Method | .Property, AllowMultiple=true)] - public sealed class ArgumentsAttribute : , .IDataSourceAttribute + public sealed class ArgumentsAttribute : , .IDataSourceAttribute, ., . { public ArgumentsAttribute(params object?[]? values) { } + public int Order { get; } + public string? Skip { get; set; } public object?[] Values { get; } - [.(typeof(.ArgumentsAttribute.d__4))] + [.(typeof(.ArgumentsAttribute.d__8))] public .<<.>> GetDataRowsAsync(.DataGeneratorMetadata dataGeneratorMetadata) { } + public . OnTestRegistered(.TestRegisteredContext context) { } } [(.Class | .Method | .Property, AllowMultiple=true)] - public sealed class ArgumentsAttribute : .TypedDataSourceAttribute + public sealed class ArgumentsAttribute : .TypedDataSourceAttribute, ., . { public ArgumentsAttribute(T value) { } - [.(typeof(.ArgumentsAttribute.d__2))] + public int Order { get; } + public string? Skip { get; set; } + [.(typeof(.ArgumentsAttribute.d__6))] public override .<<.>> GetTypedDataRowsAsync(.DataGeneratorMetadata dataGeneratorMetadata) { } + public . OnTestRegistered(.TestRegisteredContext context) { } } public class Artifact { @@ -1170,6 +1176,7 @@ namespace public .<.Artifact> Artifacts { get; } public .CancellationToken CancellationToken { get; set; } public .ClassHookContext ClassContext { get; } + public int CurrentRetryAttempt { get; } public .<.TestDetails> Dependencies { get; } public ? DisplayNameFormatter { get; set; } public .TestContextEvents Events { get; } diff --git a/TUnit.PublicAPI/Tests.Playwright_Library_Has_No_API_Changes.DotNet8_0.verified.txt b/TUnit.PublicAPI/Tests.Playwright_Library_Has_No_API_Changes.DotNet8_0.verified.txt index 94c2ff3012..69e722819a 100644 --- a/TUnit.PublicAPI/Tests.Playwright_Library_Has_No_API_Changes.DotNet8_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Playwright_Library_Has_No_API_Changes.DotNet8_0.verified.txt @@ -122,6 +122,7 @@ namespace public WorkerAwareTest() { } public virtual bool UseDefaultParallelLimiter { get; } public int WorkerIndex { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } public . RegisterService(string name, <.> factory) where T : class, .IWorkerService { } diff --git a/TUnit.PublicAPI/Tests.Playwright_Library_Has_No_API_Changes.DotNet9_0.verified.txt b/TUnit.PublicAPI/Tests.Playwright_Library_Has_No_API_Changes.DotNet9_0.verified.txt index a87649c3cf..b42f2de81f 100644 --- a/TUnit.PublicAPI/Tests.Playwright_Library_Has_No_API_Changes.DotNet9_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Playwright_Library_Has_No_API_Changes.DotNet9_0.verified.txt @@ -116,6 +116,7 @@ namespace public WorkerAwareTest() { } public virtual bool UseDefaultParallelLimiter { get; } public int WorkerIndex { get; } + [.("Type comes from runtime objects that cannot be annotated")] public . OnTestRegistered(.TestRegisteredContext context) { } public . RegisterService(string name, <.> factory) where T : class, .IWorkerService { } diff --git a/TUnit.Templates/content/TUnit.AspNet.FSharp/TestProject/TestProject.fsproj b/TUnit.Templates/content/TUnit.AspNet.FSharp/TestProject/TestProject.fsproj index 8d0ba2641b..d72896eba0 100644 --- a/TUnit.Templates/content/TUnit.AspNet.FSharp/TestProject/TestProject.fsproj +++ b/TUnit.Templates/content/TUnit.AspNet.FSharp/TestProject/TestProject.fsproj @@ -10,8 +10,8 @@ - - + + diff --git a/TUnit.Templates/content/TUnit.AspNet/TestProject/TestProject.csproj b/TUnit.Templates/content/TUnit.AspNet/TestProject/TestProject.csproj index 85a9dfdbea..9a3763a78f 100644 --- a/TUnit.Templates/content/TUnit.AspNet/TestProject/TestProject.csproj +++ b/TUnit.Templates/content/TUnit.AspNet/TestProject/TestProject.csproj @@ -9,7 +9,7 @@ - + diff --git a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj index 93377bbb9d..822a5ce10d 100644 --- a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj +++ b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.AppHost/ExampleNamespace.AppHost.csproj @@ -1,6 +1,6 @@  - + Exe @@ -12,8 +12,8 @@ - - + + diff --git a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.ServiceDefaults/ExampleNamespace.ServiceDefaults.csproj b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.ServiceDefaults/ExampleNamespace.ServiceDefaults.csproj index 9e34897deb..a998227097 100644 --- a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.ServiceDefaults/ExampleNamespace.ServiceDefaults.csproj +++ b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.ServiceDefaults/ExampleNamespace.ServiceDefaults.csproj @@ -11,7 +11,7 @@ - + diff --git a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.TestProject/ExampleNamespace.TestProject.csproj b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.TestProject/ExampleNamespace.TestProject.csproj index 48061a6add..3f05bd2d2a 100644 --- a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.TestProject/ExampleNamespace.TestProject.csproj +++ b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.TestProject/ExampleNamespace.TestProject.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj index 57d9a8af66..e08376bd7d 100644 --- a/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj +++ b/TUnit.Templates/content/TUnit.Aspire.Starter/ExampleNamespace.WebApp/ExampleNamespace.WebApp.csproj @@ -7,7 +7,7 @@ - + diff --git a/TUnit.Templates/content/TUnit.Aspire.Test/ExampleNamespace.csproj b/TUnit.Templates/content/TUnit.Aspire.Test/ExampleNamespace.csproj index 8ae5e82fdb..61430c49f1 100644 --- a/TUnit.Templates/content/TUnit.Aspire.Test/ExampleNamespace.csproj +++ b/TUnit.Templates/content/TUnit.Aspire.Test/ExampleNamespace.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/TUnit.Templates/content/TUnit.FSharp/TestProject.fsproj b/TUnit.Templates/content/TUnit.FSharp/TestProject.fsproj index 385a7e8846..35547f1139 100644 --- a/TUnit.Templates/content/TUnit.FSharp/TestProject.fsproj +++ b/TUnit.Templates/content/TUnit.FSharp/TestProject.fsproj @@ -10,8 +10,8 @@ - - + + diff --git a/TUnit.Templates/content/TUnit.Playwright/TestProject.csproj b/TUnit.Templates/content/TUnit.Playwright/TestProject.csproj index 37c9e58391..cc57a7f34c 100644 --- a/TUnit.Templates/content/TUnit.Playwright/TestProject.csproj +++ b/TUnit.Templates/content/TUnit.Playwright/TestProject.csproj @@ -8,7 +8,7 @@ - + diff --git a/TUnit.Templates/content/TUnit.VB/TestProject.vbproj b/TUnit.Templates/content/TUnit.VB/TestProject.vbproj index 94e8a62e41..3f0be495f5 100644 --- a/TUnit.Templates/content/TUnit.VB/TestProject.vbproj +++ b/TUnit.Templates/content/TUnit.VB/TestProject.vbproj @@ -8,6 +8,6 @@ - + diff --git a/TUnit.Templates/content/TUnit/TestProject.csproj b/TUnit.Templates/content/TUnit/TestProject.csproj index 411128ae2e..36e67d1197 100644 --- a/TUnit.Templates/content/TUnit/TestProject.csproj +++ b/TUnit.Templates/content/TUnit/TestProject.csproj @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/TUnit.TestProject/Bugs/_2804/GlobalHooksExecutionTest.cs b/TUnit.TestProject/Bugs/_2804/GlobalHooksExecutionTest.cs index 7dd244c492..9ff96a5ce8 100644 --- a/TUnit.TestProject/Bugs/_2804/GlobalHooksExecutionTest.cs +++ b/TUnit.TestProject/Bugs/_2804/GlobalHooksExecutionTest.cs @@ -135,29 +135,29 @@ public static void BeforeEveryTestSession(TestSessionContext context) ExecutedHooks.Add("BeforeEvery(TestSession)"); // BeforeEvery(TestSession) executed } - + // TestDiscovery hooks [Before(TestDiscovery)] - public static void BeforeTestDiscovery(TestDiscoveryContext context) + public static void BeforeTestDiscovery(BeforeTestDiscoveryContext context) { ExecutedHooks.Add("Before(TestDiscovery)"); // Before(TestDiscovery) executed } - + [After(TestDiscovery)] public static void AfterTestDiscovery(TestDiscoveryContext context) { ExecutedHooks.Add("After(TestDiscovery)"); // After(TestDiscovery) executed } - + [BeforeEvery(TestDiscovery)] - public static void BeforeEveryTestDiscovery(TestDiscoveryContext context) + public static void BeforeEveryTestDiscovery(BeforeTestDiscoveryContext context) { ExecutedHooks.Add("BeforeEvery(TestDiscovery)"); // BeforeEvery(TestDiscovery) executed } - + [AfterEvery(TestDiscovery)] public static void AfterEveryTestDiscovery(TestDiscoveryContext context) { diff --git a/TUnit.TestProject/DecimalArgumentTests.cs b/TUnit.TestProject/DecimalArgumentTests.cs index 3b65c90119..5194dcd677 100644 --- a/TUnit.TestProject/DecimalArgumentTests.cs +++ b/TUnit.TestProject/DecimalArgumentTests.cs @@ -87,4 +87,30 @@ public void TransactionDiscountCalculations(decimal amountPaying, decimal invoic decimal invoiceBalanceDue, decimal discountAmount, decimal appliedDiscountAmount, bool discountAllowedForUser) { } + + [Test] + [Arguments(2_000.00000000000000001)] + public async Task Equality3(decimal credit) + { + if (!SourceRegistrar.IsEnabled) + { + // Skip this test if source generation is not enabled, as the precision can't be preserved without access to the original syntax + return; + } + + await Assert.That(credit).IsEqualTo(2_000.00000000000000001m); + } + + [Test] + [Arguments(123_999.00000000000000001)] + public async Task Equality4(decimal credit) + { + if (!SourceRegistrar.IsEnabled) + { + // Skip this test if source generation is not enabled, as the precision can't be preserved without access to the original syntax + return; + } + + await Assert.That(credit).IsEqualTo(123_999.00000000000000001m); + } } diff --git a/TUnit.TestProject/SkippableArgumentTests.cs b/TUnit.TestProject/SkippableArgumentTests.cs new file mode 100644 index 0000000000..45c10825cc --- /dev/null +++ b/TUnit.TestProject/SkippableArgumentTests.cs @@ -0,0 +1,16 @@ +using TUnit.TestProject.Attributes; + +namespace TUnit.TestProject; + +[EngineTest(ExpectedResult.Pass)] +public class SkippableArgumentTests +{ + [Test] + [Arguments(1)] + [Arguments(2, Skip = "Skipping value 2")] + [Arguments(3)] + public async Task Test1(int value) + { + await Assert.That(value).IsEqualTo(1).Or.IsEqualTo(3); + } +} diff --git a/build_output.txt b/build_output.txt index 66bebd3b99..6c5e557345 100644 --- a/build_output.txt +++ b/build_output.txt @@ -1,6 +1,355 @@ -MSBUILD : error MSB1008: Only one project can be specified. - Full command line: 'C:\Program Files\dotnet\sdk\9.0.302\MSBuild.dll -maxcpucount -verbosity:m -tlp:default=auto -nologo -restore -consoleloggerparameters:Summary -target:Rebuild p:TreatWarningsAsErrors=false 2 -distributedlogger:Microsoft.DotNet.Tools.MSBuild.MSBuildLogger,C:\Program Files\dotnet\sdk\9.0.302\dotnet.dll*Microsoft.DotNet.Tools.MSBuild.MSBuildForwardingLogger,C:\Program Files\dotnet\sdk\9.0.302\dotnet.dll' - Switches appended by response files: -Switch: 2 + Determining projects to restore... + All projects are up-to-date for restore. + TUnit.Core -> C:\git\TUnit\TUnit.Core\bin\Release\netstandard2.0\TUnit.Core.dll + TUnit.Core -> C:\git\TUnit\TUnit.Core\bin\Release\net8.0\TUnit.Core.dll + TUnit.Core -> C:\git\TUnit\TUnit.Core\bin\Release\net9.0\TUnit.Core.dll + TUnit.Engine -> C:\git\TUnit\TUnit.Engine\bin\Release\netstandard2.0\TUnit.Engine.dll +C:\git\TUnit\TUnit.Engine\Building\TestDataCollectorFactory.cs(48,30): error IL3050: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestDataCollectorFactory.cs(48,30): error IL2026: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(60,39): error IL3050: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(60,39): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(74,39): error IL3050: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(74,39): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(77,30): error IL2026: Using member 'TUnit.Engine.Building.TestBuilderPipeline.BuildTestsFromSingleMetadataAsync(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(99,38): error IL2026: Using member 'TUnit.Engine.Building.TestBuilderPipeline.GenerateDynamicTests(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(102,34): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestBuilder.BuildTestsFromMetadataAsync(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\Collectors\AotTestDataCollector.cs(100,42): error IL2026: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method extraction from expressions uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\TUnitInitializer.cs(23,13): error IL3050: Using member 'TUnit.Engine.TUnitInitializer.DiscoverHooksViaReflection()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Hook delegate creation requires dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\TUnitInitializer.cs(23,13): error IL2026: Using member 'TUnit.Engine.TUnitInitializer.DiscoverHooksViaReflection()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Hook discovery uses reflection to scan assemblies and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\TestSessionCoordinator.cs(76,15): error IL2026: Using member 'TUnit.Engine.TestSessionCoordinator.InitializeStaticPropertiesAsync(CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Static property initialization uses reflection in reflection mode. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\TestSessionCoordinator.cs(96,23): error IL3050: Using member 'TUnit.Core.StaticPropertyReflectionInitializer.InitializeAllStaticPropertiesAsync()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Data source initialization may require dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(652,13): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.DiscoverInstanceHooksForType(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Hook registration may involve dynamic delegate creation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(652,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.DiscoverInstanceHooksForType(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Hook discovery uses reflection on methods and attributes. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(148,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(153,34): error IL2026: Using member 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection discovery is used when source-generated metadata is not available. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(319,36): error IL2026: Using member 'System.Reflection.Assembly.GetReferencedAssemblies()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly references might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(1116,34): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(1258,41): error IL2026: Using member 'TUnit.Engine.Building.TestBuilder.TryInferClassGenericsFromDataSources(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic type inference uses reflection on data sources and parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic type instantiation uses MakeGenericType and Activator. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(905,31): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateTestInvoker(Type, MethodInfo)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic method instantiation uses MakeGenericMethod. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Instance creation uses reflection and Activator.CreateInstance. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(905,31): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateTestInvoker(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Test invocation uses reflection and MethodInfo.Invoke. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(908,34): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(909,35): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionGenericTypeResolver.ExtractGenericTypeInfo(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic type info extraction uses reflection on type parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(910,37): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionGenericTypeResolver.ExtractGenericMethodInfo(MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic method info extraction uses reflection on method parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(913,38): error IL2026: Using member 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection discovery is used when source-generated metadata is not available. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1139,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(65,15): error IL2026: Using member 'TUnit.Engine.Services.TestRegistry.ProcessPendingDynamicTests()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Dynamic test metadata creation uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestGenericTypeResolver.cs(422,22): error IL2026: Using member 'TUnit.Engine.Services.TestGenericTypeResolver.TryInferTypeMapping(Type, Type, Dictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type mapping inference uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestGenericTypeResolver.cs(438,14): error IL2026: Using member 'TUnit.Engine.Services.TestGenericTypeResolver.TryInferTypeMapping(Type, Type, Dictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type mapping inference uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1105,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1105,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CollectTestsStreamingAsync(String, CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection-based test discovery requires dynamic access to types, methods, and attributes. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1052,27): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.HasTestMethods(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1160,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.MethodMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateDummyMethodMetadata(Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(198,34): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The parameter 't' of method 'lambda expression' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(198,34): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The return value of method 'System.Type.BaseType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1164,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ClassMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateDummyMethodMetadata(Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1135,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadata(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1139,30): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadata(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1396,29): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.IsCovariantCompatible(Type, Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1324,39): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.InferGenericTypeMapping(Type, Type, Dictionary)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1345,35): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.InferGenericTypeMapping(Type, Type, Dictionary)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1834,42): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Expression compilation is used for dynamic test invocation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1834,42): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Dynamic test metadata creation uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(893,50): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Discovery.ReflectionTestMetadata.ReflectionTestMetadata(Type, MethodInfo)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(896,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(896,17): error IL2072: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The return value of method 'System.Type.BaseType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(903,39): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Discovery.ReflectionAttributeExtractor.ExtractPropertyDataSources(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(908,34): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(913,38): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicFields', 'DynamicallyAccessedMemberTypes.NonPublicFields', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2151,58): error IL2077: 'testClassType' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'TUnit.Core.Helpers.ClassConstructorHelper.TryCreateInstanceWithClassConstructor(IReadOnlyList, Type, String, TestContext)'. The field 'TUnit.Engine.Discovery.ReflectionTestDataCollector.DynamicReflectionTestMetadata._testClass' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2090,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2086,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadataForDynamicBuilder(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2090,30): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadataForDynamicBuilder(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(743,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.MethodMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateMethodMetadata(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(747,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ClassMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateMethodMetadata(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(758,61): error IL2072: 'Type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ParameterMetadata.ParameterMetadata(Type)'. The return value of method 'System.Reflection.ParameterInfo.ParameterType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(822,57): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateHookDelegate(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(883,40): error IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The return value of method 'System.Reflection.PropertyInfo.GetValue(Object)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(664,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'TUnit.Core.Hooks.InstanceHookMethod.InitClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.RegisterInstanceAfterHook(Type, MethodInfo, Int32)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(643,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'TUnit.Core.Hooks.InstanceHookMethod.InitClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.RegisterInstanceBeforeHook(Type, MethodInfo, Int32)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(208,36): error IL2026: Using member 'System.Reflection.Assembly.GetReferencedAssemblies()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly references might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(231,25): error IL2026: Using member 'System.Reflection.Assembly.GetTypes()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Framework\TUnitTestFramework.cs(111,18): error IL3050: Using member 'TUnit.Engine.Framework.TUnitServiceProvider.TUnitServiceProvider(IExtension, ExecuteRequestContext, ITestExecutionFilter, IMessageBus, IServiceProvider, ITestFrameworkCapabilities)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Reflection mode test discovery uses dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Framework\TUnitTestFramework.cs(111,18): error IL2026: Using member 'TUnit.Engine.Framework.TUnitServiceProvider.TUnitServiceProvider(IExtension, ExecuteRequestContext, ITestExecutionFilter, IMessageBus, IServiceProvider, ITestFrameworkCapabilities)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Test data collector selection may use reflection-based discovery. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(259,27): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The return value of method 'System.Collections.Generic.List.Enumerator.Current.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(76,54): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(78,23): error IL2026: Using member 'TUnit.Engine.Services.PropertyInjectionService.InjectPropertiesIntoObjectAsync(Object, Dictionary, MethodMetadata, TestContextEvents)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\ObjectRegistrationService.cs(53,19): error IL2026: Using member 'TUnit.Engine.Services.PropertyInjectionService.InjectPropertiesIntoObjectAsync(Object, Dictionary, MethodMetadata, TestContextEvents)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\HookCollectionService.cs(39,19): error IL2026: Using member 'TUnit.Engine.Services.EventReceiverOrchestrator.InvokeHookRegistrationEventReceiversAsync(HookRegisteredContext, CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(106,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(142,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\PropertyInitializationOrchestrator.cs(108,19): error IL2026: Using member 'TUnit.Engine.Services.PropertyInitializationOrchestrator.InitializePropertiesAsync(Object, (PropertyInfo Property, IDataSourceAttribute DataSource)[], Dictionary, MethodMetadata, TestContextEvents, ConcurrentDictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection-based property initialization uses PropertyInfo. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(176,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(132,20): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.GetOrCreatePlan(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(147,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(158,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(184,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(195,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(192,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestDataCollectorFactory.cs(48,30): error IL2026: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestDataCollectorFactory.cs(48,30): error IL3050: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(60,39): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(60,39): error IL3050: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(74,39): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(74,39): error IL3050: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(77,30): error IL2026: Using member 'TUnit.Engine.Building.TestBuilderPipeline.BuildTestsFromSingleMetadataAsync(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\Collectors\AotTestDataCollector.cs(100,42): error IL2026: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method extraction from expressions uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(99,38): error IL2026: Using member 'TUnit.Engine.Building.TestBuilderPipeline.GenerateDynamicTests(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(102,34): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestBuilder.BuildTestsFromMetadataAsync(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\TUnitInitializer.cs(23,13): error IL2026: Using member 'TUnit.Engine.TUnitInitializer.DiscoverHooksViaReflection()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Hook discovery uses reflection to scan assemblies and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\TUnitInitializer.cs(23,13): error IL3050: Using member 'TUnit.Engine.TUnitInitializer.DiscoverHooksViaReflection()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Hook delegate creation requires dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Framework\TUnitTestFramework.cs(111,18): error IL2026: Using member 'TUnit.Engine.Framework.TUnitServiceProvider.TUnitServiceProvider(IExtension, ExecuteRequestContext, ITestExecutionFilter, IMessageBus, IServiceProvider, ITestFrameworkCapabilities)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Test data collector selection may use reflection-based discovery. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Framework\TUnitTestFramework.cs(111,18): error IL3050: Using member 'TUnit.Engine.Framework.TUnitServiceProvider.TUnitServiceProvider(IExtension, ExecuteRequestContext, ITestExecutionFilter, IMessageBus, IServiceProvider, ITestFrameworkCapabilities)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Reflection mode test discovery uses dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\TestSessionCoordinator.cs(76,15): error IL2026: Using member 'TUnit.Engine.TestSessionCoordinator.InitializeStaticPropertiesAsync(CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Static property initialization uses reflection in reflection mode. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\TestSessionCoordinator.cs(96,23): error IL3050: Using member 'TUnit.Core.StaticPropertyReflectionInitializer.InitializeAllStaticPropertiesAsync()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Data source initialization may require dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(231,25): error IL2026: Using member 'System.Reflection.Assembly.GetTypes()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(208,36): error IL2026: Using member 'System.Reflection.Assembly.GetReferencedAssemblies()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly references might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(198,34): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The parameter 't' of method 'lambda expression' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(198,34): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The return value of method 'System.Type.BaseType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(652,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.DiscoverInstanceHooksForType(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Hook discovery uses reflection on methods and attributes. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(652,13): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.DiscoverInstanceHooksForType(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Hook registration may involve dynamic delegate creation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(65,15): error IL2026: Using member 'TUnit.Engine.Services.TestRegistry.ProcessPendingDynamicTests()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Dynamic test metadata creation uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(319,36): error IL2026: Using member 'System.Reflection.Assembly.GetReferencedAssemblies()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly references might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(76,54): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(78,23): error IL2026: Using member 'TUnit.Engine.Services.PropertyInjectionService.InjectPropertiesIntoObjectAsync(Object, Dictionary, MethodMetadata, TestContextEvents)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(148,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(153,34): error IL2026: Using member 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection discovery is used when source-generated metadata is not available. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(132,20): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.GetOrCreatePlan(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(147,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(158,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(184,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(195,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(643,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'TUnit.Core.Hooks.InstanceHookMethod.InitClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.RegisterInstanceBeforeHook(Type, MethodInfo, Int32)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(664,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'TUnit.Core.Hooks.InstanceHookMethod.InitClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.RegisterInstanceAfterHook(Type, MethodInfo, Int32)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(1258,41): error IL2026: Using member 'TUnit.Engine.Building.TestBuilder.TryInferClassGenericsFromDataSources(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic type inference uses reflection on data sources and parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(822,57): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateHookDelegate(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(743,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.MethodMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateMethodMetadata(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(747,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ClassMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateMethodMetadata(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(758,61): error IL2072: 'Type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ParameterMetadata.ParameterMetadata(Type)'. The return value of method 'System.Reflection.ParameterInfo.ParameterType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(874,44): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'System.Type.GetProperty(String)'. The return value of method 'System.Object.GetType()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(883,40): error IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The return value of method 'System.Reflection.PropertyInfo.GetValue(Object)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1052,27): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.HasTestMethods(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1105,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1105,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CollectTestsStreamingAsync(String, CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection-based test discovery requires dynamic access to types, methods, and attributes. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(893,50): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Discovery.ReflectionTestMetadata.ReflectionTestMetadata(Type, MethodInfo)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(896,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(896,17): error IL2072: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The return value of method 'System.Type.BaseType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(903,39): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Discovery.ReflectionAttributeExtractor.ExtractPropertyDataSources(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1160,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.MethodMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateDummyMethodMetadata(Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1164,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ClassMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateDummyMethodMetadata(Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Instance creation uses reflection and Activator.CreateInstance. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic type instantiation uses MakeGenericType and Activator. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(905,31): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateTestInvoker(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Test invocation uses reflection and MethodInfo.Invoke. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(905,31): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateTestInvoker(Type, MethodInfo)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic method instantiation uses MakeGenericMethod. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(106,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(908,34): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(908,34): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(909,35): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionGenericTypeResolver.ExtractGenericTypeInfo(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic type info extraction uses reflection on type parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(910,37): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionGenericTypeResolver.ExtractGenericMethodInfo(MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic method info extraction uses reflection on method parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(913,38): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicFields', 'DynamicallyAccessedMemberTypes.NonPublicFields', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(913,38): error IL2026: Using member 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection discovery is used when source-generated metadata is not available. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1135,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadata(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1139,30): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadata(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1139,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(142,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(259,27): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The return value of method 'System.Collections.Generic.List.Enumerator.Current.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1324,39): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.InferGenericTypeMapping(Type, Type, Dictionary)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1345,35): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.InferGenericTypeMapping(Type, Type, Dictionary)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(176,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1396,29): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.IsCovariantCompatible(Type, Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestGenericTypeResolver.cs(438,14): error IL2026: Using member 'TUnit.Engine.Services.TestGenericTypeResolver.TryInferTypeMapping(Type, Type, Dictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type mapping inference uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestGenericTypeResolver.cs(422,22): error IL2026: Using member 'TUnit.Engine.Services.TestGenericTypeResolver.TryInferTypeMapping(Type, Type, Dictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type mapping inference uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(192,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1834,42): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Dynamic test metadata creation uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1834,42): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Expression compilation is used for dynamic test invocation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2066,13): error IL2072: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The return value of method 'System.Object.GetType()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2086,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadataForDynamicBuilder(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2090,30): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadataForDynamicBuilder(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2090,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2151,58): error IL2077: 'testClassType' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'TUnit.Core.Helpers.ClassConstructorHelper.TryCreateInstanceWithClassConstructor(IReadOnlyList, Type, String, TestContext)'. The field 'TUnit.Engine.Discovery.ReflectionTestDataCollector.DynamicReflectionTestMetadata._testClass' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\HookCollectionService.cs(39,19): error IL2026: Using member 'TUnit.Engine.Services.EventReceiverOrchestrator.InvokeHookRegistrationEventReceiversAsync(HookRegisteredContext, CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\ObjectRegistrationService.cs(53,19): error IL2026: Using member 'TUnit.Engine.Services.PropertyInjectionService.InjectPropertiesIntoObjectAsync(Object, Dictionary, MethodMetadata, TestContextEvents)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\PropertyInitializationOrchestrator.cs(108,19): error IL2026: Using member 'TUnit.Engine.Services.PropertyInitializationOrchestrator.InitializePropertiesAsync(Object, (PropertyInfo Property, IDataSourceAttribute DataSource)[], Dictionary, MethodMetadata, TestContextEvents, ConcurrentDictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection-based property initialization uses PropertyInfo. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(1116,34): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] -For switch syntax, type "MSBuild -help" +Build FAILED. + +C:\git\TUnit\TUnit.Engine\Building\TestDataCollectorFactory.cs(48,30): error IL3050: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestDataCollectorFactory.cs(48,30): error IL2026: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(60,39): error IL3050: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(60,39): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(74,39): error IL3050: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(74,39): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(77,30): error IL2026: Using member 'TUnit.Engine.Building.TestBuilderPipeline.BuildTestsFromSingleMetadataAsync(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(99,38): error IL2026: Using member 'TUnit.Engine.Building.TestBuilderPipeline.GenerateDynamicTests(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(102,34): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestBuilder.BuildTestsFromMetadataAsync(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\Collectors\AotTestDataCollector.cs(100,42): error IL2026: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method extraction from expressions uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\TUnitInitializer.cs(23,13): error IL3050: Using member 'TUnit.Engine.TUnitInitializer.DiscoverHooksViaReflection()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Hook delegate creation requires dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\TUnitInitializer.cs(23,13): error IL2026: Using member 'TUnit.Engine.TUnitInitializer.DiscoverHooksViaReflection()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Hook discovery uses reflection to scan assemblies and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\TestSessionCoordinator.cs(76,15): error IL2026: Using member 'TUnit.Engine.TestSessionCoordinator.InitializeStaticPropertiesAsync(CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Static property initialization uses reflection in reflection mode. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\TestSessionCoordinator.cs(96,23): error IL3050: Using member 'TUnit.Core.StaticPropertyReflectionInitializer.InitializeAllStaticPropertiesAsync()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Data source initialization may require dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(652,13): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.DiscoverInstanceHooksForType(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Hook registration may involve dynamic delegate creation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(652,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.DiscoverInstanceHooksForType(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Hook discovery uses reflection on methods and attributes. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(148,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(153,34): error IL2026: Using member 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection discovery is used when source-generated metadata is not available. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(319,36): error IL2026: Using member 'System.Reflection.Assembly.GetReferencedAssemblies()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly references might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(1116,34): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(1258,41): error IL2026: Using member 'TUnit.Engine.Building.TestBuilder.TryInferClassGenericsFromDataSources(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic type inference uses reflection on data sources and parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic type instantiation uses MakeGenericType and Activator. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(905,31): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateTestInvoker(Type, MethodInfo)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic method instantiation uses MakeGenericMethod. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Instance creation uses reflection and Activator.CreateInstance. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(905,31): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateTestInvoker(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Test invocation uses reflection and MethodInfo.Invoke. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(908,34): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(909,35): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionGenericTypeResolver.ExtractGenericTypeInfo(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic type info extraction uses reflection on type parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(910,37): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionGenericTypeResolver.ExtractGenericMethodInfo(MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic method info extraction uses reflection on method parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(913,38): error IL2026: Using member 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection discovery is used when source-generated metadata is not available. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1139,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(65,15): error IL2026: Using member 'TUnit.Engine.Services.TestRegistry.ProcessPendingDynamicTests()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Dynamic test metadata creation uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestGenericTypeResolver.cs(422,22): error IL2026: Using member 'TUnit.Engine.Services.TestGenericTypeResolver.TryInferTypeMapping(Type, Type, Dictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type mapping inference uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\TestGenericTypeResolver.cs(438,14): error IL2026: Using member 'TUnit.Engine.Services.TestGenericTypeResolver.TryInferTypeMapping(Type, Type, Dictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type mapping inference uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1105,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1105,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CollectTestsStreamingAsync(String, CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection-based test discovery requires dynamic access to types, methods, and attributes. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1052,27): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.HasTestMethods(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1160,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.MethodMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateDummyMethodMetadata(Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(198,34): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The parameter 't' of method 'lambda expression' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(198,34): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The return value of method 'System.Type.BaseType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1164,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ClassMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateDummyMethodMetadata(Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1135,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadata(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1139,30): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadata(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1396,29): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.IsCovariantCompatible(Type, Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1324,39): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.InferGenericTypeMapping(Type, Type, Dictionary)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1345,35): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.InferGenericTypeMapping(Type, Type, Dictionary)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1834,42): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Expression compilation is used for dynamic test invocation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1834,42): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Dynamic test metadata creation uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(893,50): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Discovery.ReflectionTestMetadata.ReflectionTestMetadata(Type, MethodInfo)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(896,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(896,17): error IL2072: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The return value of method 'System.Type.BaseType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(903,39): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Discovery.ReflectionAttributeExtractor.ExtractPropertyDataSources(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(908,34): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(913,38): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicFields', 'DynamicallyAccessedMemberTypes.NonPublicFields', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2151,58): error IL2077: 'testClassType' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'TUnit.Core.Helpers.ClassConstructorHelper.TryCreateInstanceWithClassConstructor(IReadOnlyList, Type, String, TestContext)'. The field 'TUnit.Engine.Discovery.ReflectionTestDataCollector.DynamicReflectionTestMetadata._testClass' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2090,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2086,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadataForDynamicBuilder(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2090,30): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadataForDynamicBuilder(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(743,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.MethodMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateMethodMetadata(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(747,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ClassMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateMethodMetadata(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(758,61): error IL2072: 'Type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ParameterMetadata.ParameterMetadata(Type)'. The return value of method 'System.Reflection.ParameterInfo.ParameterType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(822,57): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateHookDelegate(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(883,40): error IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The return value of method 'System.Reflection.PropertyInfo.GetValue(Object)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(664,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'TUnit.Core.Hooks.InstanceHookMethod.InitClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.RegisterInstanceAfterHook(Type, MethodInfo, Int32)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(643,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'TUnit.Core.Hooks.InstanceHookMethod.InitClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.RegisterInstanceBeforeHook(Type, MethodInfo, Int32)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(208,36): error IL2026: Using member 'System.Reflection.Assembly.GetReferencedAssemblies()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly references might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(231,25): error IL2026: Using member 'System.Reflection.Assembly.GetTypes()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Framework\TUnitTestFramework.cs(111,18): error IL3050: Using member 'TUnit.Engine.Framework.TUnitServiceProvider.TUnitServiceProvider(IExtension, ExecuteRequestContext, ITestExecutionFilter, IMessageBus, IServiceProvider, ITestFrameworkCapabilities)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Reflection mode test discovery uses dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Framework\TUnitTestFramework.cs(111,18): error IL2026: Using member 'TUnit.Engine.Framework.TUnitServiceProvider.TUnitServiceProvider(IExtension, ExecuteRequestContext, ITestExecutionFilter, IMessageBus, IServiceProvider, ITestFrameworkCapabilities)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Test data collector selection may use reflection-based discovery. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(259,27): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The return value of method 'System.Collections.Generic.List.Enumerator.Current.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(76,54): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(78,23): error IL2026: Using member 'TUnit.Engine.Services.PropertyInjectionService.InjectPropertiesIntoObjectAsync(Object, Dictionary, MethodMetadata, TestContextEvents)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\ObjectRegistrationService.cs(53,19): error IL2026: Using member 'TUnit.Engine.Services.PropertyInjectionService.InjectPropertiesIntoObjectAsync(Object, Dictionary, MethodMetadata, TestContextEvents)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\HookCollectionService.cs(39,19): error IL2026: Using member 'TUnit.Engine.Services.EventReceiverOrchestrator.InvokeHookRegistrationEventReceiversAsync(HookRegisteredContext, CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(106,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(142,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\PropertyInitializationOrchestrator.cs(108,19): error IL2026: Using member 'TUnit.Engine.Services.PropertyInitializationOrchestrator.InitializePropertiesAsync(Object, (PropertyInfo Property, IDataSourceAttribute DataSource)[], Dictionary, MethodMetadata, TestContextEvents, ConcurrentDictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection-based property initialization uses PropertyInfo. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(176,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(132,20): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.GetOrCreatePlan(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(147,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(158,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(184,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(195,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(192,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net8.0] +C:\git\TUnit\TUnit.Engine\Building\TestDataCollectorFactory.cs(48,30): error IL2026: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestDataCollectorFactory.cs(48,30): error IL3050: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(60,39): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(60,39): error IL3050: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(74,39): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(74,39): error IL3050: Using member 'TUnit.Engine.Building.Interfaces.ITestDataCollector.CollectTestsAsync(String)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic test instantiation requires MakeGenericType. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(77,30): error IL2026: Using member 'TUnit.Engine.Building.TestBuilderPipeline.BuildTestsFromSingleMetadataAsync(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\Collectors\AotTestDataCollector.cs(100,42): error IL2026: Using member 'TUnit.Engine.Building.Collectors.AotTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method extraction from expressions uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(99,38): error IL2026: Using member 'TUnit.Engine.Building.TestBuilderPipeline.GenerateDynamicTests(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilderPipeline.cs(102,34): error IL2026: Using member 'TUnit.Engine.Building.Interfaces.ITestBuilder.BuildTestsFromMetadataAsync(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\TUnitInitializer.cs(23,13): error IL2026: Using member 'TUnit.Engine.TUnitInitializer.DiscoverHooksViaReflection()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Hook discovery uses reflection to scan assemblies and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\TUnitInitializer.cs(23,13): error IL3050: Using member 'TUnit.Engine.TUnitInitializer.DiscoverHooksViaReflection()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Hook delegate creation requires dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Framework\TUnitTestFramework.cs(111,18): error IL2026: Using member 'TUnit.Engine.Framework.TUnitServiceProvider.TUnitServiceProvider(IExtension, ExecuteRequestContext, ITestExecutionFilter, IMessageBus, IServiceProvider, ITestFrameworkCapabilities)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Test data collector selection may use reflection-based discovery. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Framework\TUnitTestFramework.cs(111,18): error IL3050: Using member 'TUnit.Engine.Framework.TUnitServiceProvider.TUnitServiceProvider(IExtension, ExecuteRequestContext, ITestExecutionFilter, IMessageBus, IServiceProvider, ITestFrameworkCapabilities)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Reflection mode test discovery uses dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\TestSessionCoordinator.cs(76,15): error IL2026: Using member 'TUnit.Engine.TestSessionCoordinator.InitializeStaticPropertiesAsync(CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Static property initialization uses reflection in reflection mode. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\TestSessionCoordinator.cs(96,23): error IL3050: Using member 'TUnit.Core.StaticPropertyReflectionInitializer.InitializeAllStaticPropertiesAsync()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Data source initialization may require dynamic code generation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(231,25): error IL2026: Using member 'System.Reflection.Assembly.GetTypes()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Types might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(208,36): error IL2026: Using member 'System.Reflection.Assembly.GetReferencedAssemblies()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly references might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(198,34): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The parameter 't' of method 'lambda expression' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(198,34): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The return value of method 'System.Type.BaseType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(652,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.DiscoverInstanceHooksForType(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Hook discovery uses reflection on methods and attributes. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(652,13): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.DiscoverInstanceHooksForType(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Hook registration may involve dynamic delegate creation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(65,15): error IL2026: Using member 'TUnit.Engine.Services.TestRegistry.ProcessPendingDynamicTests()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Dynamic test metadata creation uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(319,36): error IL2026: Using member 'System.Reflection.Assembly.GetReferencedAssemblies()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly references might be removed. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(76,54): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(78,23): error IL2026: Using member 'TUnit.Engine.Services.PropertyInjectionService.InjectPropertiesIntoObjectAsync(Object, Dictionary, MethodMetadata, TestContextEvents)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(148,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestRegistry.cs(153,34): error IL2026: Using member 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection discovery is used when source-generated metadata is not available. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(132,20): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.GetOrCreatePlan(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(147,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(158,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(184,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\DataSourceInitializer.cs(195,21): error IL2026: Using member 'TUnit.Core.PropertyInjection.PropertyInjectionCache.HasInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(643,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'TUnit.Core.Hooks.InstanceHookMethod.InitClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.RegisterInstanceBeforeHook(Type, MethodInfo, Int32)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(664,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'TUnit.Core.Hooks.InstanceHookMethod.InitClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.RegisterInstanceAfterHook(Type, MethodInfo, Int32)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(1258,41): error IL2026: Using member 'TUnit.Engine.Building.TestBuilder.TryInferClassGenericsFromDataSources(TestMetadata)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic type inference uses reflection on data sources and parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(822,57): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateHookDelegate(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(743,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.MethodMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateMethodMetadata(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(747,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ClassMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionHookDiscoveryService.CreateMethodMetadata(Type, MethodInfo)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(758,61): error IL2072: 'Type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ParameterMetadata.ParameterMetadata(Type)'. The return value of method 'System.Reflection.ParameterInfo.ParameterType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(874,44): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'System.Type.GetProperty(String)'. The return value of method 'System.Object.GetType()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(883,40): error IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Activator.CreateInstance(Type)'. The return value of method 'System.Reflection.PropertyInfo.GetValue(Object)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1052,27): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.HasTestMethods(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1105,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CollectTestsAsync(String)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Assembly scanning uses dynamic type discovery and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1105,13): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CollectTestsStreamingAsync(String, CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection-based test discovery requires dynamic access to types, methods, and attributes. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(893,50): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Discovery.ReflectionTestMetadata.ReflectionTestMetadata(Type, MethodInfo)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(896,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(896,17): error IL2072: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The return value of method 'System.Type.BaseType.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(903,39): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Discovery.ReflectionAttributeExtractor.ExtractPropertyDataSources(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1160,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.MethodMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateDummyMethodMetadata(Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL2067: 'testClass' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1164,17): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.ClassMetadata.Type.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateDummyMethodMetadata(Type, String)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Instance creation uses reflection and Activator.CreateInstance. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(904,35): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateInstanceFactory(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic type instantiation uses MakeGenericType and Activator. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(905,31): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateTestInvoker(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Test invocation uses reflection and MethodInfo.Invoke. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(905,31): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateTestInvoker(Type, MethodInfo)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Generic method instantiation uses MakeGenericMethod. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(106,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(908,34): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(908,34): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(909,35): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionGenericTypeResolver.ExtractGenericTypeInfo(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic type info extraction uses reflection on type parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(910,37): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionGenericTypeResolver.ExtractGenericMethodInfo(MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Generic method info extraction uses reflection on method parameters. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(913,38): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicFields', 'DynamicallyAccessedMemberTypes.NonPublicFields', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)'. The parameter 'testClass' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.BuildTestMetadata(Type, MethodInfo, Object[])' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(913,38): error IL2026: Using member 'TUnit.Core.PropertySourceRegistry.DiscoverInjectableProperties(Type)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection discovery is used when source-generated metadata is not available. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1135,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadata(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1139,30): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadata(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1139,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(142,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionHookDiscoveryService.cs(259,27): error IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods(BindingFlags)'. The return value of method 'System.Collections.Generic.List.Enumerator.Current.get' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1324,39): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.InferGenericTypeMapping(Type, Type, Dictionary)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1345,35): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.InferGenericTypeMapping(Type, Type, Dictionary)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(176,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1396,29): error IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.Interfaces' in call to 'System.Type.GetInterfaces()'. The parameter 'argType' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.IsCovariantCompatible(Type, Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestGenericTypeResolver.cs(438,14): error IL2026: Using member 'TUnit.Engine.Services.TestGenericTypeResolver.TryInferTypeMapping(Type, Type, Dictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type mapping inference uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\TestGenericTypeResolver.cs(422,22): error IL2026: Using member 'TUnit.Engine.Services.TestGenericTypeResolver.TryInferTypeMapping(Type, Type, Dictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type mapping inference uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\EventReceiverOrchestrator.cs(192,33): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1834,42): error IL2026: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Dynamic test metadata creation uses reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(1834,42): error IL3050: Using member 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateMetadataFromDynamicDiscoveryResult(DynamicDiscoveryResult)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Expression compilation is used for dynamic test invocation. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2066,13): error IL2072: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The return value of method 'System.Object.GetType()' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2086,13): error IL2067: 'value' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Core.TestMetadata.TestClassType.init'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadataForDynamicBuilder(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2090,30): error IL2067: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors', 'DynamicallyAccessedMemberTypes.PublicMethods', 'DynamicallyAccessedMemberTypes.NonPublicMethods', 'DynamicallyAccessedMemberTypes.PublicProperties' in call to 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)'. The parameter 'type' of method 'TUnit.Engine.Discovery.ReflectionTestDataCollector.CreateFailedTestMetadataForDynamicBuilder(Type, MethodInfo, Exception)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2090,30): error IL2026: Using member 'TUnit.Engine.Building.ReflectionMetadataBuilder.CreateMethodMetadata(Type, MethodInfo)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Method metadata creation uses reflection on parameters and types. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Discovery\ReflectionTestDataCollector.cs(2151,58): error IL2077: 'testClassType' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'TUnit.Core.Helpers.ClassConstructorHelper.TryCreateInstanceWithClassConstructor(IReadOnlyList, Type, String, TestContext)'. The field 'TUnit.Engine.Discovery.ReflectionTestDataCollector.DynamicReflectionTestMetadata._testClass' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\HookCollectionService.cs(39,19): error IL2026: Using member 'TUnit.Engine.Services.EventReceiverOrchestrator.InvokeHookRegistrationEventReceiversAsync(HookRegisteredContext, CancellationToken)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\ObjectRegistrationService.cs(53,19): error IL2026: Using member 'TUnit.Engine.Services.PropertyInjectionService.InjectPropertiesIntoObjectAsync(Object, Dictionary, MethodMetadata, TestContextEvents)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Type comes from runtime objects that cannot be annotated. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Services\PropertyInitializationOrchestrator.cs(108,19): error IL2026: Using member 'TUnit.Engine.Services.PropertyInitializationOrchestrator.InitializePropertiesAsync(Object, (PropertyInfo Property, IDataSourceAttribute DataSource)[], Dictionary, MethodMetadata, TestContextEvents, ConcurrentDictionary)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Reflection-based property initialization uses PropertyInfo. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] +C:\git\TUnit\TUnit.Engine\Building\TestBuilder.cs(1116,34): error IL2026: Using member 'TUnit.Engine.Utilities.ScopedAttributeFilter.FilterScopedAttributes(IEnumerable)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Scoped attribute filtering uses Type.GetInterfaces and reflection. [C:\git\TUnit\TUnit.Engine\TUnit.Engine.csproj::TargetFramework=net9.0] + 0 Warning(s) + 170 Error(s) + +Time Elapsed 00:00:04.07 + +Workload updates are available. Run `dotnet workload list` for more information. diff --git a/docs/docs/test-authoring/aot-compatibility.md b/docs/docs/test-authoring/aot-compatibility.md index 27015b1458..f7adbd0359 100644 --- a/docs/docs/test-authoring/aot-compatibility.md +++ b/docs/docs/test-authoring/aot-compatibility.md @@ -173,10 +173,10 @@ namespace MyTestProject; public class ServiceInjectionTests { - [DataSourceForProperty(Shared = SharedType.Globally)] + [ClassDataSource(Shared = SharedType.Globally)] public required DatabaseService Database { get; init; } - [DataSourceForProperty] + [ClassDataSource] public required LoggingService Logger { get; init; } [Test] @@ -223,7 +223,7 @@ namespace MyTestProject; public class AsyncInitializationTests { - [DataSourceForProperty] + [ClassDataSource] public required AsyncContainer Container { get; init; } [Test] diff --git a/docs/docs/test-lifecycle/property-injection.md b/docs/docs/test-lifecycle/property-injection.md index 6b748f4902..8c51c0436c 100644 --- a/docs/docs/test-lifecycle/property-injection.md +++ b/docs/docs/test-lifecycle/property-injection.md @@ -12,7 +12,7 @@ Supported attributes for properties in AOT mode: - **MethodDataSource** - Static method data sources - **ClassDataSource** - Static class-based data sources - **DataSourceGeneratorAttribute** - Source-generated data (first item only) -- **DataSourceForProperty** - Dependency injection with service provider +- **ClassDataSource** - Dependency injection with service provider The AOT system generates strongly-typed property setters at compile time, eliminating reflection overhead and ensuring full Native AOT compatibility. @@ -68,11 +68,11 @@ public class PropertySetterTests public required InnerModel Property3 { get; init; } // Globally shared data source - [ClassDataSource(Shared = SharedType.Globally)] + [ClassDataSource(Shared = SharedType.PerTestSession)] public required InnerModel Property4 { get; init; } // Class-scoped shared data source - [ClassDataSource(Shared = SharedType.ForClass)] + [ClassDataSource(Shared = SharedType.PerClass)] public required InnerModel Property5 { get; init; } // Keyed shared data source @@ -84,7 +84,7 @@ public class PropertySetterTests public required string Property7 { get; init; } // Service provider dependency injection - [DataSourceForProperty] + [ClassDataSource] public required AsyncPropertyExample AsyncService { get; init; } [Test] diff --git a/tools/speed-comparison/Tests.Benchmark/RuntimeBenchmarks.cs b/tools/speed-comparison/Tests.Benchmark/RuntimeBenchmarks.cs index 05e10e9d92..f6e0d580b8 100644 --- a/tools/speed-comparison/Tests.Benchmark/RuntimeBenchmarks.cs +++ b/tools/speed-comparison/Tests.Benchmark/RuntimeBenchmarks.cs @@ -1,6 +1,7 @@ using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; using CliWrap; +using CliWrap.Buffered; namespace Tests.Benchmark; @@ -9,80 +10,61 @@ public class RuntimeBenchmarks : BenchmarkBase { private static readonly string? ClassName = Environment.GetEnvironmentVariable("CLASS_NAME"); - [GlobalSetup] - public async Task Setup() - { - // Build all framework configurations - await Cli.Wrap("dotnet") - .WithArguments(["build", UnifiedPath, "-c", "Release", "-p:TestFramework=TUNIT", "--framework", Framework]) - .ExecuteAsync(); - await Cli.Wrap("dotnet") - .WithArguments(["build", UnifiedPath, "-c", "Release", "-p:TestFramework=XUNIT", "--framework", Framework]) - .ExecuteAsync(); - await Cli.Wrap("dotnet") - .WithArguments(["build", UnifiedPath, "-c", "Release", "-p:TestFramework=NUNIT", "--framework", Framework]) - .ExecuteAsync(); - await Cli.Wrap("dotnet") - .WithArguments(["build", UnifiedPath, "-c", "Release", "-p:TestFramework=MSTEST", "--framework", Framework]) - .ExecuteAsync(); - - // Publish AOT configuration - await Cli.Wrap("dotnet") - .WithArguments(["publish", UnifiedPath, "-c", "Release", "-p:TestFramework=TUNIT", "-p:Aot=true", "--framework", Framework]) - .ExecuteAsync(); - } - [Benchmark] [BenchmarkCategory("Runtime", "AOT")] public async Task TUnit_AOT() { - // Note: AOT build must be done separately with: dotnet publish -c Release -p:TestFramework=TUNIT -p:PublishAot=true - var aotPath = Path.Combine(UnifiedPath, "bin", "Release", Framework, "publish"); + var aotPath = Path.Combine(UnifiedPath, "bin", "Release-TUNIT-AOT", Framework); var exeName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "UnifiedTests.exe" : "UnifiedTests"; - + await Cli.Wrap(Path.Combine(aotPath, exeName)) .WithArguments(["--treenode-filter", $"/*/*/{ClassName}/*"]) .WithStandardOutputPipe(PipeTarget.ToStream(OutputStream)) - .ExecuteAsync(); + .ExecuteBufferedAsync(); } [Benchmark] public async Task TUnit() { - await Cli.Wrap("dotnet") - .WithArguments(["run", "--no-build", "-c", "Release", "-p:TestFramework=TUNIT", "--treenode-filter", $"/*/*/{ClassName}/*", "--framework", Framework]) - .WithWorkingDirectory(UnifiedPath) + var binPath = Path.Combine(UnifiedPath, "bin", "Release-TUNIT", Framework); + var exeName = GetExecutableFileName(); + + await Cli.Wrap(Path.Combine(binPath, exeName)) + .WithArguments(["--treenode-filter", $"/*/*/{ClassName}/*"]) .WithStandardOutputPipe(PipeTarget.ToStream(OutputStream)) - .ExecuteAsync(); + .ExecuteBufferedAsync(); } [Benchmark] public async Task NUnit() { + var dllPath = Path.Combine(UnifiedPath, "bin", "Release-NUNIT", Framework, "UnifiedTests.dll"); + await Cli.Wrap("dotnet") - .WithArguments(["test", "--no-build", "-c", "Release", "-p:TestFramework=NUNIT", "--filter", $"FullyQualifiedName~{ClassName}", "--framework", Framework]) - .WithWorkingDirectory(UnifiedPath) + .WithArguments(["test", dllPath, "--filter", $"FullyQualifiedName~{ClassName}"]) .WithStandardOutputPipe(PipeTarget.ToStream(OutputStream)) - .ExecuteAsync(); + .ExecuteBufferedAsync(); } [Benchmark] public async Task xUnit() { + var dllPath = Path.Combine(UnifiedPath, "bin", "Release-XUNIT", Framework, "UnifiedTests.dll"); + await Cli.Wrap("dotnet") - .WithArguments(["test", "--no-build", "-c", "Release", "-p:TestFramework=XUNIT", "--filter", $"FullyQualifiedName~{ClassName}", "--framework", Framework]) - .WithWorkingDirectory(UnifiedPath) + .WithArguments(["test", dllPath, "--filter", $"FullyQualifiedName~{ClassName}"]) .WithStandardOutputPipe(PipeTarget.ToStream(OutputStream)) - .ExecuteAsync(); + .ExecuteBufferedAsync(); } [Benchmark] public async Task MSTest() { + var dllPath = Path.Combine(UnifiedPath, "bin", "Release-MSTEST", Framework, "UnifiedTests.dll"); + await Cli.Wrap("dotnet") - .WithArguments(["test", "--no-build", "-c", "Release", "-p:TestFramework=MSTEST", "--filter", $"FullyQualifiedName~{ClassName}", "--framework", Framework]) - .WithWorkingDirectory(UnifiedPath) + .WithArguments(["test", dllPath, "--filter", $"FullyQualifiedName~{ClassName}"]) .WithStandardOutputPipe(PipeTarget.ToStream(OutputStream)) - .ExecuteAsync(); + .ExecuteBufferedAsync(); } } diff --git a/tools/speed-comparison/UnifiedTests/UnifiedTests.csproj b/tools/speed-comparison/UnifiedTests/UnifiedTests.csproj index c08597248e..5adb86e020 100644 --- a/tools/speed-comparison/UnifiedTests/UnifiedTests.csproj +++ b/tools/speed-comparison/UnifiedTests/UnifiedTests.csproj @@ -1,5 +1,9 @@ + + TUNIT + + net8.0;net9.0 enable @@ -7,11 +11,12 @@ false true Exe + true - $(DefineConstants);TUNIT + $(DefineConstants);TUNIT $(DefineConstants);XUNIT $(DefineConstants);NUNIT $(DefineConstants);MSTEST @@ -57,4 +62,4 @@ true - \ No newline at end of file + diff --git a/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.FSharp/TUnit.NugetTester.FSharp.fsproj b/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.FSharp/TUnit.NugetTester.FSharp.fsproj index 0d8573d8c6..979822dc00 100644 --- a/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.FSharp/TUnit.NugetTester.FSharp.fsproj +++ b/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.FSharp/TUnit.NugetTester.FSharp.fsproj @@ -7,6 +7,14 @@ enable exe enable + true + $(NoWarn);NU1504 + + + + true + true + true diff --git a/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.Library/TUnit.NugetTester.Library.csproj b/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.Library/TUnit.NugetTester.Library.csproj index 6eb0069425..7c48f5920d 100644 --- a/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.Library/TUnit.NugetTester.Library.csproj +++ b/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.Library/TUnit.NugetTester.Library.csproj @@ -6,6 +6,8 @@ true enable enable + true + $(NoWarn);NU1504 diff --git a/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.VB/TUnit.NugetTester.VB.vbproj b/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.VB/TUnit.NugetTester.VB.vbproj index 645022e2d8..6c00b40ee1 100644 --- a/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.VB/TUnit.NugetTester.VB.vbproj +++ b/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester.VB/TUnit.NugetTester.VB.vbproj @@ -7,6 +7,14 @@ enable exe enable + true + $(NoWarn);NU1504 + + + + true + true + true diff --git a/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester/TUnit.NugetTester.csproj b/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester/TUnit.NugetTester.csproj index 7891fa6078..42163c3879 100644 --- a/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester/TUnit.NugetTester.csproj +++ b/tools/tunit-nuget-tester/TUnit.NugetTester/TUnit.NugetTester/TUnit.NugetTester.csproj @@ -7,13 +7,23 @@ enable exe enable + true + $(NoWarn);NU1504 + + + + true + true + true + false + false $(TUnitVersion) - +