From 89558d0b8d53009328e51db2d1e4f2a33199409f Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Thu, 5 Nov 2026 01:52:10 +0000 Subject: [PATCH 1/2] Add null-row generic class inference coverage for #7360 --- tests/TUnit.Engine.Tests/Issue7210Tests.cs | 18 +++++ .../Bugs/_7210/MixedClassSourceRowTests.cs | 80 +++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/tests/TUnit.Engine.Tests/Issue7210Tests.cs b/tests/TUnit.Engine.Tests/Issue7210Tests.cs index 36614478cd4..905e5614120 100644 --- a/tests/TUnit.Engine.Tests/Issue7210Tests.cs +++ b/tests/TUnit.Engine.Tests/Issue7210Tests.cs @@ -16,6 +16,9 @@ public class Issue7210Tests(TestMode testMode) : InvokableTestBase(testMode) [Arguments("WrappedRowInfersItsValue", 2)] [Arguments("WrappedFactoryInvokedOnce", 1)] [Arguments("WrappedFactoryFreshPerTest", 3)] + [Arguments("NullLeadingRowInfersFirstNonNull", 1)] + [Arguments("AllNullRowsUseAllRowsFallback", 1)] + [Arguments("NullLeadingTwoParameterRowUsesFallback", 1)] public async Task Rows_Run_On_The_Instantiation_They_Infer(string className, int expectedTests) { await RunTestsWithFilter( @@ -44,6 +47,21 @@ await RunTestsWithFilter( ]); } + [Test] + public async Task All_Null_Rows_Do_Not_Infer_An_Unmatched_Instantiation() + { + await RunTestsWithFilter( + "/*/TUnit.TestProject.Bugs._7210/AllNullRowsUseNoClassRowFallback*/*", + [ + result => result.ResultSummary.Outcome.ShouldBe("Failed"), + result => result.ResultSummary.Counters.Total.ShouldBe(2), + result => result.ResultSummary.Counters.Passed.ShouldBe(1), + result => result.ResultSummary.Counters.Failed.ShouldBe(1), + result => result.Results.Single(x => x.Outcome == "Failed") + .Output?.ErrorInfo?.Message.ShouldContain("none of the class-level data rows infer") + ]); + } + [Test] public async Task Method_Row_Type_That_No_Class_Row_Infers_Fails() { diff --git a/tests/TUnit.TestProject/Bugs/_7210/MixedClassSourceRowTests.cs b/tests/TUnit.TestProject/Bugs/_7210/MixedClassSourceRowTests.cs index d82aea9ccb9..852b36f49ae 100644 --- a/tests/TUnit.TestProject/Bugs/_7210/MixedClassSourceRowTests.cs +++ b/tests/TUnit.TestProject/Bugs/_7210/MixedClassSourceRowTests.cs @@ -201,3 +201,83 @@ public async Task Test(T arg) await Assert.That(arg).IsTypeOf(); } } + +// Custom untyped sources keep the nulls as constructor positions rather than treating an array as one value. +public sealed class NullLeadingRowAttribute : UntypedDataSourceGeneratorAttribute +{ + protected override IEnumerable> GenerateDataSources(DataGeneratorMetadata metadata) + { + yield return () => [null, 5]; + } +} + +public sealed class AllNullRowAttribute : UntypedDataSourceGeneratorAttribute +{ + protected override IEnumerable> GenerateDataSources(DataGeneratorMetadata metadata) + { + yield return () => [null, null]; + } +} + +[EngineTest(ExpectedResult.Pass)] +[NullLeadingRow] +public class NullLeadingRowInfersFirstNonNull(T? value, int number) where T : struct +{ + [Test] + [Arguments(1)] + public async Task Test(T arg) + { + await Assert.That(typeof(T)).IsEqualTo(typeof(int)); + await Assert.That(value).IsNull(); + await Assert.That(number).IsEqualTo(5); + await Assert.That((int)(object)arg).IsEqualTo(1); + } +} + +// Neither null supplies a type: the method supplies T and AllRows retains both constructor positions. +[EngineTest(ExpectedResult.Pass)] +[AllNullRow] +public class AllNullRowsUseAllRowsFallback(T? first, T? second) where T : class +{ + [Test] + [Arguments("method")] + public async Task Test(T arg) + { + await Assert.That(first).IsNull(); + await Assert.That(second).IsNull(); + await Assert.That(typeof(T)).IsEqualTo(typeof(string)); + } +} + +// A later non-null value cannot infer both type parameters, so method inference uses AllRows. +[EngineTest(ExpectedResult.Pass)] +[NullLeadingRow] +public class NullLeadingTwoParameterRowUsesFallback(TFirst? first, TSecond second) + where TFirst : class +{ + [Test] + [Arguments("method", 1)] + public async Task Test(TFirst firstArg, TSecond secondArg) + { + await Assert.That(first).IsNull(); + await Assert.That(typeof(TFirst)).IsEqualTo(typeof(string)); + await Assert.That(typeof(TSecond)).IsEqualTo(typeof(int)); + await Assert.That((int)(object)second!).IsEqualTo(5); + } +} + +// With an Arguments row, null source values cannot supply the unmatched int instantiation (NoClassRow). +[EngineTest(ExpectedResult.Failure)] +[Arguments("class", "class")] +[AllNullRow] +public class AllNullRowsUseNoClassRowFallback(T? first, T? second) +{ + [Test] + [Arguments("method")] + [Arguments(1)] + public async Task Test(T arg) + { + await Assert.That(first).IsEqualTo((T)(object)"class"); + await Assert.That(second).IsEqualTo((T)(object)"class"); + } +} From 8ac99379437976da3433a8df4c9c4fd3d38975d5 Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Thu, 5 Nov 2026 01:58:19 +0000 Subject: [PATCH 2/2] Strengthen null-row regression coverage and update snapshot (#7360) --- .../Tests7210.Test.verified.txt | 393 ++++++++++++++++++ tests/TUnit.Engine.Tests/Issue7210Tests.cs | 5 +- .../Bugs/_7210/MixedClassSourceRowTests.cs | 10 +- 3 files changed, 401 insertions(+), 7 deletions(-) diff --git a/tests/TUnit.Core.SourceGenerator.Tests/Tests7210.Test.verified.txt b/tests/TUnit.Core.SourceGenerator.Tests/Tests7210.Test.verified.txt index a0ebd0dbbc2..e91049b1ed4 100644 --- a/tests/TUnit.Core.SourceGenerator.Tests/Tests7210.Test.verified.txt +++ b/tests/TUnit.Core.SourceGenerator.Tests/Tests7210.Test.verified.txt @@ -1081,3 +1081,396 @@ internal static partial class TUnit_TestRegistration { static readonly int _r_TUnit_TestProject_Bugs__7210_MethodRowTypeNoClassRowInfers_T_Test__T_TestSource_1 = global::TUnit.Core.SourceRegistrar.RegisterEntries>(static () => TUnit_TestProject_Bugs__7210_MethodRowTypeNoClassRowInfers_T_Test__T_TestSource.Entries_1); } + + +// ===== FILE SEPARATOR ===== + +// +#pragma warning disable + +#nullable enable +namespace TUnit.Generated; +[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] +[global::System.CodeDom.Compiler.GeneratedCode("TUnit", "VERSION_SCRUBBED")] +internal static class TUnit_TestProject_Bugs__7210_NullLeadingRowInfersFirstNonNull_T_Test_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7210.NullLeadingRowInfersFirstNonNull<>", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7210.NullLeadingRowInfersFirstNonNull<>), + TypeInfo = new global::TUnit.Core.ConstructedGeneric(typeof(global::TUnit.TestProject.Bugs._7210.NullLeadingRowInfersFirstNonNull<>), [new global::TUnit.Core.GenericParameter(0, false, "T")]), + Name = "NullLeadingRowInfersFirstNonNull", + Namespace = "TUnit.TestProject.Bugs._7210", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::TUnit.Core.ParameterMetadataFactory.ForConstructor(typeof(global::TUnit.TestProject.Bugs._7210.NullLeadingRowInfersFirstNonNull<>), true, new global::TUnit.Core.ParameterMetadata[] + { + global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "value", new global::TUnit.Core.ConstructedGeneric(typeof(global::System.Nullable<>), [new global::TUnit.Core.GenericParameter(0, false, "T")]), true), + global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "number", new global::TUnit.Core.GenericParameter(0, false, "T"), false) + }), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7210.NullLeadingRowInfersFirstNonNull<>); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Test", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata); + private static global::TUnit.TestProject.Bugs._7210.NullLeadingRowInfersFirstNonNull __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7210.NullLeadingRowInfersFirstNonNull(global::TUnit.Core.Helpers.CastHelper.Cast(args[0]), global::TUnit.Core.Helpers.CastHelper.Cast(args[1])); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7210.NullLeadingRowInfersFirstNonNull instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + try + { + return new global::System.Threading.Tasks.ValueTask(instance.Test()); + } + catch (global::System.Exception ex) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(ex)); + } + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute(), + new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), + new global::TUnit.Core.ArgumentsAttribute(null, 7), + new global::TUnit.TestProject.Bugs._7210.NullLeadingRowAttribute() + }; + } + public static readonly global::TUnit.Core.TestEntry>[] Entries_0 = new global::TUnit.Core.TestEntry>[] + { + global::TUnit.Core.TestEntryFactory.Create>( + methodName: "Test", + fullyQualifiedName: "TUnit.TestProject.Bugs._7210.NullLeadingRowInfersFirstNonNull.Test", + filePath: "", + lineNumber: 228, + hasDataSource: true, + classDataSources: global::TUnit.Core.GenericClassRowPartition.Create(new global::System.Type[] { typeof(int) }, global::TUnit.Core.GenericClassRowFallback.None, new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.ArgumentsAttribute(null, 7), + new global::TUnit.TestProject.Bugs._7210.NullLeadingRowAttribute(), +}, 1), + methodMetadata: __mm_0, + createInstance: __CreateInstance_0, + invokeBody: __Invoke_0, + methodIndex: 0, + createAttributes: __Attributes_0, + attributeGroupIndex: 0), + }; +} +internal static partial class TUnit_TestRegistration +{ + static readonly int _r_TUnit_TestProject_Bugs__7210_NullLeadingRowInfersFirstNonNull_T_Test_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries>(static () => TUnit_TestProject_Bugs__7210_NullLeadingRowInfersFirstNonNull_T_Test_TestSource.Entries_0); +} + + +// ===== FILE SEPARATOR ===== + +// +#pragma warning disable + +#nullable enable +namespace TUnit.Generated; +[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] +[global::System.CodeDom.Compiler.GeneratedCode("TUnit", "VERSION_SCRUBBED")] +internal static class TUnit_TestProject_Bugs__7210_AllNullRowsUseAllRowsFallback_T_Test__T_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback<>", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback<>), + TypeInfo = new global::TUnit.Core.ConstructedGeneric(typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback<>), [new global::TUnit.Core.GenericParameter(0, false, "T")]), + Name = "AllNullRowsUseAllRowsFallback", + Namespace = "TUnit.TestProject.Bugs._7210", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::TUnit.Core.ParameterMetadataFactory.ForConstructor(typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback<>), true, new global::TUnit.Core.ParameterMetadata[] + { + global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "first", new global::TUnit.Core.GenericParameter(0, false, "T"), true), + global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "second", new global::TUnit.Core.GenericParameter(0, false, "T"), true) + }), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback<>); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Test", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, parameters: global::TUnit.Core.ParameterMetadataFactory.ForGenericMethod(typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback<>), "Test", false, 0, new global::TUnit.Core.ParameterMetadata[] +{ +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "arg", new global::TUnit.Core.GenericParameter(0, false, "T"), false) +})); + private static global::TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback(global::TUnit.Core.Helpers.CastHelper.Cast(args[0]), global::TUnit.Core.Helpers.CastHelper.Cast(args[1])); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + try + { + return new global::System.Threading.Tasks.ValueTask(instance.Test(global::TUnit.Core.Helpers.CastHelper.Cast(args[0]))); + } + catch (global::System.Exception ex) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(ex)); + } + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute(), + new global::TUnit.Core.ArgumentsAttribute("method"), + new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), + new global::TUnit.TestProject.Bugs._7210.AllNullRowAttribute() + }; + } + public static readonly global::TUnit.Core.TestEntry>[] Entries_0 = new global::TUnit.Core.TestEntry>[] + { + global::TUnit.Core.TestEntryFactory.Create>( + methodName: "Test", + fullyQualifiedName: "TUnit.TestProject.Bugs._7210.AllNullRowsUseAllRowsFallback.Test", + filePath: "", + lineNumber: 242, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.ArgumentsAttribute("method"), +}, + classDataSources: global::TUnit.Core.GenericClassRowPartition.Create(new global::System.Type[] { typeof(string) }, global::TUnit.Core.GenericClassRowFallback.AllRows, new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.TestProject.Bugs._7210.AllNullRowAttribute(), +}, 0), + methodMetadata: __mm_0, + createInstance: __CreateInstance_0, + invokeBody: __Invoke_0, + methodIndex: 0, + createAttributes: __Attributes_0, + attributeGroupIndex: 0), + }; +} +internal static partial class TUnit_TestRegistration +{ + static readonly int _r_TUnit_TestProject_Bugs__7210_AllNullRowsUseAllRowsFallback_T_Test__T_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries>(static () => TUnit_TestProject_Bugs__7210_AllNullRowsUseAllRowsFallback_T_Test__T_TestSource.Entries_0); +} + + +// ===== FILE SEPARATOR ===== + +// +#pragma warning disable + +#nullable enable +namespace TUnit.Generated; +[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] +[global::System.CodeDom.Compiler.GeneratedCode("TUnit", "VERSION_SCRUBBED")] +internal static class TUnit_TestProject_Bugs__7210_NullLeadingTwoParameterRowUsesFallback_TFirst_TSecond_Tes_50264156_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback<,>", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback<,>), + TypeInfo = new global::TUnit.Core.ConstructedGeneric(typeof(global::TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback<,>), [new global::TUnit.Core.GenericParameter(0, false, "TFirst"), new global::TUnit.Core.GenericParameter(1, false, "TSecond")]), + Name = "NullLeadingTwoParameterRowUsesFallback", + Namespace = "TUnit.TestProject.Bugs._7210", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::TUnit.Core.ParameterMetadataFactory.ForConstructor(typeof(global::TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback<,>), true, new global::TUnit.Core.ParameterMetadata[] + { + global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "first", new global::TUnit.Core.GenericParameter(0, false, "TFirst"), true), + global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "second", new global::TUnit.Core.GenericParameter(1, false, "TSecond"), false) + }), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback<,>); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Test", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, parameters: global::TUnit.Core.ParameterMetadataFactory.ForGenericMethod(typeof(global::TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback<,>), "Test", false, 0, new global::TUnit.Core.ParameterMetadata[] +{ +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "firstArg", new global::TUnit.Core.GenericParameter(0, false, "TFirst"), false), +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "secondArg", new global::TUnit.Core.GenericParameter(1, false, "TSecond"), false) +})); + private static global::TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback(global::TUnit.Core.Helpers.CastHelper.Cast(args[0]), global::TUnit.Core.Helpers.CastHelper.Cast(args[1])); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + try + { + return new global::System.Threading.Tasks.ValueTask(instance.Test(global::TUnit.Core.Helpers.CastHelper.Cast(args[0]), global::TUnit.Core.Helpers.CastHelper.Cast(args[1]))); + } + catch (global::System.Exception ex) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(ex)); + } + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute(), + new global::TUnit.Core.ArgumentsAttribute("method", 1), + new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Pass), + new global::TUnit.TestProject.Bugs._7210.NullLeadingRowAttribute() + }; + } + public static readonly global::TUnit.Core.TestEntry>[] Entries_0 = new global::TUnit.Core.TestEntry>[] + { + global::TUnit.Core.TestEntryFactory.Create>( + methodName: "Test", + fullyQualifiedName: "TUnit.TestProject.Bugs._7210.NullLeadingTwoParameterRowUsesFallback.Test", + filePath: "", + lineNumber: 258, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.ArgumentsAttribute("method", 1), +}, + classDataSources: global::TUnit.Core.GenericClassRowPartition.Create(new global::System.Type[] { typeof(string), typeof(int) }, global::TUnit.Core.GenericClassRowFallback.AllRows, new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.TestProject.Bugs._7210.NullLeadingRowAttribute(), +}, 0), + methodMetadata: __mm_0, + createInstance: __CreateInstance_0, + invokeBody: __Invoke_0, + methodIndex: 0, + createAttributes: __Attributes_0, + attributeGroupIndex: 0), + }; +} +internal static partial class TUnit_TestRegistration +{ + static readonly int _r_TUnit_TestProject_Bugs__7210_NullLeadingTwoParameterRowUsesFallback_TFirst_TSecond_Tes_50264156_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries>(static () => TUnit_TestProject_Bugs__7210_NullLeadingTwoParameterRowUsesFallback_TFirst_TSecond_Tes_50264156_TestSource.Entries_0); +} + + +// ===== FILE SEPARATOR ===== + +// +#pragma warning disable + +#nullable enable +namespace TUnit.Generated; +[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] +[global::System.CodeDom.Compiler.GeneratedCode("TUnit", "VERSION_SCRUBBED")] +internal static class TUnit_TestProject_Bugs__7210_AllNullRowsUseNoClassRowFallback_T_Test__T_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback<>", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback<>), + TypeInfo = new global::TUnit.Core.ConstructedGeneric(typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback<>), [new global::TUnit.Core.GenericParameter(0, false, "T")]), + Name = "AllNullRowsUseNoClassRowFallback", + Namespace = "TUnit.TestProject.Bugs._7210", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::TUnit.Core.ParameterMetadataFactory.ForConstructor(typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback<>), true, new global::TUnit.Core.ParameterMetadata[] + { + global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "first", new global::TUnit.Core.GenericParameter(0, false, "T"), true), + global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "second", new global::TUnit.Core.GenericParameter(0, false, "T"), true) + }), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback<>); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Test", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, parameters: global::TUnit.Core.ParameterMetadataFactory.ForGenericMethod(typeof(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback<>), "Test", false, 0, new global::TUnit.Core.ParameterMetadata[] +{ +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "arg", new global::TUnit.Core.GenericParameter(0, false, "T"), false) +})); + private static global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback(global::TUnit.Core.Helpers.CastHelper.Cast(args[0]), global::TUnit.Core.Helpers.CastHelper.Cast(args[1])); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + try + { + return new global::System.Threading.Tasks.ValueTask(instance.Test(global::TUnit.Core.Helpers.CastHelper.Cast(args[0]))); + } + catch (global::System.Exception ex) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(ex)); + } + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute(), + new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Failure), + new global::TUnit.Core.ArgumentsAttribute("class", "class"), + new global::TUnit.TestProject.Bugs._7210.AllNullRowAttribute() + }; + } + public static readonly global::TUnit.Core.TestEntry>[] Entries_0 = new global::TUnit.Core.TestEntry>[] + { + global::TUnit.Core.TestEntryFactory.Create>( + methodName: "Test", + fullyQualifiedName: "TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback.Test", + filePath: "", + lineNumber: 275, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.ArgumentsAttribute("method"), +}, + classDataSources: global::TUnit.Core.GenericClassRowPartition.Create(new global::System.Type[] { typeof(string) }, global::TUnit.Core.GenericClassRowFallback.None, new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.ArgumentsAttribute("class", "class"), + new global::TUnit.TestProject.Bugs._7210.AllNullRowAttribute(), +}, 1), + methodMetadata: __mm_0, + createInstance: __CreateInstance_0, + invokeBody: __Invoke_0, + methodIndex: 0, + createAttributes: __Attributes_0, + attributeGroupIndex: 0), + }; + private static global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback __CreateInstance_1(global::System.Type[] typeArgs, object?[] args) + { + if (args.Length == 0) throw new global::System.InvalidOperationException("This method-level [Arguments] row infers class type arguments that none of the class-level data rows infer, so no class row supplies the constructor arguments for this instantiation. Add a class-level row with matching types, or change the method row to match an existing class row."); + return new global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback(global::TUnit.Core.Helpers.CastHelper.Cast(args[0]), global::TUnit.Core.Helpers.CastHelper.Cast(args[1])); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_1(global::TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + try + { + return new global::System.Threading.Tasks.ValueTask(instance.Test(global::TUnit.Core.Helpers.CastHelper.Cast(args[0]))); + } + catch (global::System.Exception ex) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(ex)); + } + } + private static global::System.Attribute[] __Attributes_1(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute(), + new global::TUnit.TestProject.Attributes.EngineTest(global::TUnit.TestProject.Attributes.ExpectedResult.Failure), + new global::TUnit.Core.ArgumentsAttribute("class", "class"), + new global::TUnit.TestProject.Bugs._7210.AllNullRowAttribute() + }; + } + public static readonly global::TUnit.Core.TestEntry>[] Entries_1 = new global::TUnit.Core.TestEntry>[] + { + global::TUnit.Core.TestEntryFactory.Create>( + methodName: "Test", + fullyQualifiedName: "TUnit.TestProject.Bugs._7210.AllNullRowsUseNoClassRowFallback.Test", + filePath: "", + lineNumber: 275, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.ArgumentsAttribute(1), +}, + classDataSources: global::TUnit.Core.GenericClassRowPartition.Create(new global::System.Type[] { typeof(int) }, global::TUnit.Core.GenericClassRowFallback.NoClassRow, new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.TestProject.Bugs._7210.AllNullRowAttribute(), +}, 0), + methodMetadata: __mm_0, + createInstance: __CreateInstance_1, + invokeBody: __Invoke_1, + methodIndex: 0, + createAttributes: __Attributes_1, + attributeGroupIndex: 0), + }; +} +internal static partial class TUnit_TestRegistration +{ + static readonly int _r_TUnit_TestProject_Bugs__7210_AllNullRowsUseNoClassRowFallback_T_Test__T_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries>(static () => TUnit_TestProject_Bugs__7210_AllNullRowsUseNoClassRowFallback_T_Test__T_TestSource.Entries_0); +} +internal static partial class TUnit_TestRegistration +{ + static readonly int _r_TUnit_TestProject_Bugs__7210_AllNullRowsUseNoClassRowFallback_T_Test__T_TestSource_1 = global::TUnit.Core.SourceRegistrar.RegisterEntries>(static () => TUnit_TestProject_Bugs__7210_AllNullRowsUseNoClassRowFallback_T_Test__T_TestSource.Entries_1); +} diff --git a/tests/TUnit.Engine.Tests/Issue7210Tests.cs b/tests/TUnit.Engine.Tests/Issue7210Tests.cs index 905e5614120..a0e34492dc1 100644 --- a/tests/TUnit.Engine.Tests/Issue7210Tests.cs +++ b/tests/TUnit.Engine.Tests/Issue7210Tests.cs @@ -16,7 +16,7 @@ public class Issue7210Tests(TestMode testMode) : InvokableTestBase(testMode) [Arguments("WrappedRowInfersItsValue", 2)] [Arguments("WrappedFactoryInvokedOnce", 1)] [Arguments("WrappedFactoryFreshPerTest", 3)] - [Arguments("NullLeadingRowInfersFirstNonNull", 1)] + [Arguments("NullLeadingRowInfersFirstNonNull", 2)] [Arguments("AllNullRowsUseAllRowsFallback", 1)] [Arguments("NullLeadingTwoParameterRowUsesFallback", 1)] public async Task Rows_Run_On_The_Instantiation_They_Infer(string className, int expectedTests) @@ -58,7 +58,8 @@ await RunTestsWithFilter( result => result.ResultSummary.Counters.Passed.ShouldBe(1), result => result.ResultSummary.Counters.Failed.ShouldBe(1), result => result.Results.Single(x => x.Outcome == "Failed") - .Output?.ErrorInfo?.Message.ShouldContain("none of the class-level data rows infer") + .Output.ShouldNotBeNull().ErrorInfo.ShouldNotBeNull().Message + .ShouldContain("none of the class-level data rows infer") ]); } diff --git a/tests/TUnit.TestProject/Bugs/_7210/MixedClassSourceRowTests.cs b/tests/TUnit.TestProject/Bugs/_7210/MixedClassSourceRowTests.cs index 852b36f49ae..b61e952f407 100644 --- a/tests/TUnit.TestProject/Bugs/_7210/MixedClassSourceRowTests.cs +++ b/tests/TUnit.TestProject/Bugs/_7210/MixedClassSourceRowTests.cs @@ -219,18 +219,18 @@ public sealed class AllNullRowAttribute : UntypedDataSourceGeneratorAttribute } } +// The typed row seeds the AOT instantiation and disables AllRows fallback. Both rows must run. [EngineTest(ExpectedResult.Pass)] +[Arguments(null, 7)] [NullLeadingRow] -public class NullLeadingRowInfersFirstNonNull(T? value, int number) where T : struct +public class NullLeadingRowInfersFirstNonNull(T? value, T number) where T : struct { [Test] - [Arguments(1)] - public async Task Test(T arg) + public async Task Test() { await Assert.That(typeof(T)).IsEqualTo(typeof(int)); await Assert.That(value).IsNull(); - await Assert.That(number).IsEqualTo(5); - await Assert.That((int)(object)arg).IsEqualTo(1); + await Assert.That((int)(object)number).IsIn(5, 7); } }