diff --git a/src/TUnit.Core.SourceGenerator/Generators/TestMetadataGenerator.cs b/src/TUnit.Core.SourceGenerator/Generators/TestMetadataGenerator.cs index c56c76268b9..0124d98b172 100644 --- a/src/TUnit.Core.SourceGenerator/Generators/TestMetadataGenerator.cs +++ b/src/TUnit.Core.SourceGenerator/Generators/TestMetadataGenerator.cs @@ -499,9 +499,9 @@ private static void GenerateTestMetadata(CodeWriter writer, TestMethodMetadata t if (concreteInstantiations.Count == 0 && classConstraintViolations.Count == 0) { - // No concrete types could be resolved — skip this method. - // The test won't be discovered, which matches the behavior of - // not having any data to resolve type arguments. + // No concrete types could be resolved for a generic class — skip this method. A + // generic method on a non-generic class always gets an entry: rows whose type + // arguments cannot be inferred fail instead (#7163). return; } } @@ -819,6 +819,12 @@ private static List CollectConcreteInstantiations(TestMet // every instantiation a class row establishes, since reflection mode runs them there too. List? uninferredMethodDataSources = null; + // A generic method on a non-generic class without [GenerateGenericTest]: every method data source + // that infers an existing instantiation's types joins it (#7163). With [GenerateGenericTest], a later + // non-[Arguments] source inferring the same types is dropped, as reflection mode does (#7092). + var joinsDuplicateMethodSources = testMethod is { IsGenericMethod: true, IsGenericType: false } + && !testMethod.MethodAttributes.Any(static a => a.AttributeClass?.IsOrInherits("global::TUnit.Core.GenerateGenericTestAttribute") is true); + var classTypeArgCount = testMethod.IsGenericType ? testMethod.TypeSymbol.TypeParameters.Length : 0; var methodTypeArgCount = testMethod.IsGenericMethod ? testMethod.MethodSymbol.TypeParameters.Length : 0; @@ -896,7 +902,13 @@ void TryAddInstantiation( } } - if (specificAttr?.AttributeClass?.Name == "ArgumentsAttribute") + // A generic method on a non-generic class runs only the sources scoped to its + // instantiation, so any method data source that infers the same types as an earlier + // one (a second [MethodDataSource] declared like the first, say) joins it too. + // Otherwise its rows would be reported as uninferable (#7163). Reflection mode drops + // such a source when the method has [GenerateGenericTest], so it is dropped here too. + if (specificAttr?.AttributeClass?.Name == "ArgumentsAttribute" + || (specificAttr is not null && !isClassRow && joinsDuplicateMethodSources)) { existing.AddRow(specificAttr, isClassRow); } @@ -1300,9 +1312,159 @@ a.AttributeClass is { } attributeClass .Select(v => v.Message) .ToList(); + if (testMethod is { IsGenericMethod: true, IsGenericType: false }) + { + AddUninferredTypeArgumentFailures(testMethod, className, results); + } + return results; } + /// + /// Reports the data sources of a generic test method whose rows no instantiation runs, because + /// their declared type does not determine the method's type arguments (an object or + /// object[] row, say). Reflection mode infers the type arguments from each row's run-time + /// values, which source-generated mode cannot do. Rather than dropping the rows silently, each of + /// them fails with a message that says how to fix it. A method with no data source at all fails + /// once, as it does in reflection mode (#7163). + /// + private static void AddUninferredTypeArgumentFailures(TestMethodMetadata testMethod, string className, List results) + { + List? uncovered = null; + var hasDataSource = false; + + foreach (var attribute in testMethod.MethodAttributes) + { + // [GenerateGenericTest] lists the type arguments, so its types run every data source + // (or fail their constraints) and no data source has to infer them. + if (attribute.AttributeClass?.IsOrInherits("global::TUnit.Core.GenerateGenericTestAttribute") is true) + { + return; + } + } + + foreach (var attribute in testMethod.MethodAttributes) + { + if (!DataSourceAttributeHelper.IsDataSourceAttribute(attribute.AttributeClass)) + { + continue; + } + + hasDataSource = true; + if (!IsRunByAnyInstantiation(testMethod, results, attribute)) + { + (uncovered ??= []).Add(attribute); + } + } + + if (hasDataSource && uncovered is null) + { + return; + } + + if (!hasDataSource && results.Count > 0) + { + return; + } + + var methodName = testMethod.MethodSymbol.Name; + var violations = new List(); + if (uncovered is null) + { + violations.Add(new MethodConstraintViolation( + $"Could not infer the type arguments of generic test method '{methodName}': it has no data source to infer them from. List the type arguments with [GenerateGenericTest].", + RowSource: null, + AllMethodDataSources: false)); + } + else + { + foreach (var attribute in uncovered) + { + violations.Add(new MethodConstraintViolation( + $"Could not infer the type arguments of generic test method '{methodName}' from data source [{DescribeDataSource(attribute)}]. " + + "Source-generated mode infers type arguments at compile time from the data source's declared type, not from the run-time type of its values, and that declared type does not determine them. " + + "Declare the data source with a type that does (for example IEnumerable> rather than IEnumerable), or list the type arguments with [GenerateGenericTest].", + RowSource: attribute, + AllMethodDataSources: false)); + } + } + + // All failures of one concrete class share one entry, as constraint violations do, so each + // failing row gets its own data source index and so its own test id. + var existing = results.FirstOrDefault(r => r.MethodConstraintViolations != null && r.ConcreteClassName == className); + if (existing != null) + { + existing.MethodConstraintViolations!.AddRange(violations); + return; + } + + results.Add(new ConcreteInstantiation + { + ConcreteClassName = className, + TypeArguments = [], + ClassTypeArgs = [], + MethodTypeArgs = [], + TestName = methodName, + MethodName = methodName, + MethodConstraintViolations = violations, + }); + + static string DescribeDataSource(AttributeData attribute) + { + if (attribute.ApplicationSyntaxReference?.GetSyntax() is { } syntax) + { + return syntax.ToString(); + } + + var name = attribute.AttributeClass?.Name ?? "DataSource"; + return name.EndsWith("Attribute", StringComparison.Ordinal) ? name.Substring(0, name.Length - "Attribute".Length) : name; + } + } + + /// + /// Whether the rows of run, or are reported, on at least one of the + /// instantiations of a generic method on a non-generic class. This mirrors the data source + /// selection in . + /// + private static bool IsRunByAnyInstantiation(TestMethodMetadata testMethod, List results, AttributeData dataSource) + { + if (results.Count == 0) + { + return false; + } + + // When the parameters do not use the type arguments, every instantiation runs every data source. + if (!MethodParametersReferenceTypeParameters(testMethod)) + { + return true; + } + + foreach (var instantiation in results) + { + if (instantiation.MethodConstraintViolations is { } violations) + { + foreach (var violation in violations) + { + if (violation.AllMethodDataSources + || (violation.RowSource is { } rowSource && AreSameAttribute(rowSource, dataSource))) + { + return true; + } + } + + continue; + } + + // [GenerateGenericTest] and IInfersType instantiations run every method data source. + if (instantiation.SpecificArgumentsAttribute is null || instantiation.IsSpecificMethodDataSource(dataSource)) + { + return true; + } + } + + return false; + } + /// /// Extracts type arguments from a GenerateGenericTestAttribute's constructor arguments. /// The attribute takes params Type[] in its constructor. @@ -3838,7 +4000,7 @@ private static string PreGenerateMethodMetadataArguments(IMethodSymbol methodSym if (!methodSymbol.ReturnsVoid) { - writer.AppendLine($"returnType: typeof({methodSymbol.ReturnType.GloballyQualified()}),"); + writer.AppendLine($"returnType: typeof({ReturnTypeForTypeOf(methodSymbol.ReturnType)}),"); } if (methodSymbol.TypeParameters.Length > 0) @@ -3858,12 +4020,68 @@ private static string PreGenerateMethodMetadataArguments(IMethodSymbol methodSym return writer.ToString(); } + /// + /// The type to name in typeof(...) for a test method's return type. The metadata is emitted + /// outside the method and its class, so a return type that uses a type parameter cannot name it. + /// opens a generic type whose arguments are type + /// parameters (Task<T> becomes Task<>), but not one that nests them + /// (Task<T[]>) or takes them from a containing type (Outer<T>.Inner), and a + /// bare T or T[] has no open form. Those become the open generic type and + /// object, as parameter metadata does. + /// + private static string ReturnTypeForTypeOf(ITypeSymbol returnType) + { + if (!ReferencesTypeParameter(returnType)) + { + return returnType.GloballyQualified(); + } + + if (returnType is INamedTypeSymbol namedType) + { + return OpenGenericTypeOf(namedType); + } + + return "object"; + + // Unlike CodeGenerationHelpers.ContainsTypeParameter, this also looks at containing types: + // Outer.Inner has no type arguments of its own, but still mentions T. + static bool ReferencesTypeParameter(ITypeSymbol type) => type switch + { + ITypeParameterSymbol => true, + IArrayTypeSymbol arrayType => ReferencesTypeParameter(arrayType.ElementType), + INamedTypeSymbol named => named.TypeArguments.Any(ReferencesTypeParameter) + || (named.ContainingType is { } containingType && ReferencesTypeParameter(containingType)), + _ => false, + }; + + // The unbound form of the type and every type that contains it, such as + // global::Outer<>.Inner<,>. C# only accepts an unbound generic name in typeof when every + // generic level is unbound. Roslyn displays Nullable as `T?`, so the name is built from + // the definition's parts rather than from its display string. + static string OpenGenericTypeOf(INamedTypeSymbol type) + { + var definition = type.OriginalDefinition; + var name = definition.Arity > 0 + ? $"{definition.Name}<{new string(',', definition.Arity - 1)}>" + : definition.Name; + + if (definition.ContainingType is { } containingType) + { + return $"{OpenGenericTypeOf(containingType)}.{name}"; + } + + return definition.ContainingNamespace is { IsGlobalNamespace: false } containingNamespace + ? $"{containingNamespace.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}.{name}" + : $"global::{name}"; + } + } + /// /// Generates a MethodMetadataFactory.Create(...) call expression referencing __classType and __classMetadata. /// private static string GenerateMethodMetadataFactoryCall(IMethodSymbol methodSymbol) { - var returnType = methodSymbol.ReturnType.GloballyQualified(); + var returnType = ReturnTypeForTypeOf(methodSymbol.ReturnType); var sb = new System.Text.StringBuilder(); sb.Append($"global::TUnit.Core.MethodMetadataFactory.Create(\"{methodSymbol.Name}\", __classType, typeof({returnType}), __classMetadata"); diff --git a/tests/TUnit.Core.SourceGenerator.Tests/Bugs/7163/Tests7163.cs b/tests/TUnit.Core.SourceGenerator.Tests/Bugs/7163/Tests7163.cs new file mode 100644 index 00000000000..c338e4b2a0c --- /dev/null +++ b/tests/TUnit.Core.SourceGenerator.Tests/Bugs/7163/Tests7163.cs @@ -0,0 +1,65 @@ +namespace TUnit.Core.SourceGenerator.Tests; + +/// +/// A generic test method whose type arguments its data source's declared type cannot determine must +/// be emitted as an entry whose rows fail with an explanation, instead of being dropped (#7163). +/// +internal class Tests7163 : TestsBase +{ + [Test] + public Task Test() => RunTest(Path.Combine( + Git.TestsDirectory.FullName, + "TUnit.TestProject", + "Bugs", + "_7163", + "UninferableGenericMethodTests.cs"), + async generatedFiles => + { + const string cannotInfer = "Could not infer the type arguments of generic test method 'Generic' from data source [MethodDataSource(nameof(Rows))]"; + + string SourceFor(string className) => generatedFiles.Single(f => + f.Contains($"typeof(global::TUnit.TestProject.Bugs._7163.{className})")); + + // Uninferable rows: the data source is wrapped so each of its rows fails. + foreach (var className in new[] { "ObjectRowsTests", "ObjectArrayRowsTests" }) + { + var source = SourceFor(className); + await Assert.That(source).Contains($"global::TUnit.Core.GenericConstraintViolationDataSource.Create(\"{cannotInfer}"); + await Assert.That(source).DoesNotContain("instance.Generic<"); + } + + // The inferable row still runs, beside the failing source. + var partly = SourceFor("PartlyInferableTests"); + await Assert.That(partly).Contains("instance.Generic("); + await Assert.That(partly).Contains($"global::TUnit.Core.GenericConstraintViolationDataSource.Create(\"{cannotInfer}"); + + // [GenerateGenericTest] lists the type arguments, so nothing is reported. + var generateGeneric = SourceFor("GenerateGenericTestWithObjectRowsTests"); + await Assert.That(generateGeneric).Contains("instance.Generic("); + await Assert.That(generateGeneric).DoesNotContain("GenericConstraintViolationDataSource"); + + // No data source: a single failing row. + var noDataSource = SourceFor("NoDataSourceTests"); + await Assert.That(noDataSource).Contains("global::TUnit.Core.GenericConstraintViolationDataSource.Create(\"Could not infer the type arguments of generic test method 'Generic': it has no data source to infer them from."); + + // Data sources that infer the same type arguments as an earlier one join its instantiation. + foreach (var className in new[] { "ArgumentsAndDataSourceWithSameTypesTests", "TwoDataSourcesWithSameTypesTests" }) + { + var source = SourceFor(className); + await Assert.That(source).Contains("instance.Generic("); + await Assert.That(source).DoesNotContain("GenericConstraintViolationDataSource"); + } + + // A return type that nests T is named by its open generic type, since T does not exist there. + var nestedReturnType = SourceFor("NestedGenericReturnTypeTests"); + await Assert.That(nestedReturnType).Contains("typeof(global::System.Threading.Tasks.Task<>)"); + await Assert.That(nestedReturnType).DoesNotContain("Task"); + + var nullableReturnType = SourceFor("NullableGenericReturnTypeTests"); + await Assert.That(nullableReturnType).Contains("typeof(global::System.Nullable<>)"); + await Assert.That(nullableReturnType).DoesNotContain("T?<>"); + + var containingReturnType = SourceFor("ContainingGenericReturnTypeTests"); + await Assert.That(containingReturnType).Contains("typeof(global::TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests.Outer<>.Inner)"); + }); +} diff --git a/tests/TUnit.Core.SourceGenerator.Tests/Tests7163.Test.verified.txt b/tests/TUnit.Core.SourceGenerator.Tests/Tests7163.Test.verified.txt new file mode 100644 index 00000000000..f042e6289d2 --- /dev/null +++ b/tests/TUnit.Core.SourceGenerator.Tests/Tests7163.Test.verified.txt @@ -0,0 +1,777 @@ +// +#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__7163_ObjectRowsTests_Generic__T_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.ObjectRowsTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.ObjectRowsTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.ObjectRowsTests)), + Name = "ObjectRowsTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.ObjectRowsTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, genericTypeCount: 1, parameters: global::TUnit.Core.ParameterMetadataFactory.ForGenericMethod(typeof(global::TUnit.TestProject.Bugs._7163.ObjectRowsTests), "Generic", false, 1, new global::TUnit.Core.ParameterMetadata[] +{ +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "value", new global::TUnit.Core.GenericParameter(0, true, "T"), false) +})); + private static global::TUnit.TestProject.Bugs._7163.ObjectRowsTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.ObjectRowsTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.ObjectRowsTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(new global::TUnit.Core.Exceptions.GenericTypeResolutionException("Could not infer the type arguments of generic test method 'Generic' from data source [MethodDataSource(nameof(Rows))]. Source-generated mode infers type arguments at compile time from the data source's declared type, not from the run-time type of its values, and that declared type does not determine them. Declare the data source with a type that does (for example IEnumerable> rather than IEnumerable), or list the type arguments with [GenerateGenericTest]."))); + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute(), + new global::TUnit.Core.MethodDataSourceAttribute("Rows") + }; + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.ObjectRowsTests.Generic", + filePath: "", + lineNumber: 20, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + global::TUnit.Core.GenericConstraintViolationDataSource.Create("Could not infer the type arguments of generic test method 'Generic' from data source [MethodDataSource(nameof(Rows))]. Source-generated mode infers type arguments at compile time from the data source's declared type, not from the run-time type of its values, and that declared type does not determine them. Declare the data source with a type that does (for example IEnumerable> rather than IEnumerable), or list the type arguments with [GenerateGenericTest].", new global::TUnit.Core.MethodDataSourceAttribute("Rows") +{ + Factory = static dataGeneratorMetadata => global::TUnit.Core.Helpers.DataSourceFactories.FromEnumerable(static () => global::TUnit.TestProject.Bugs._7163.ObjectRowsTests.Rows()), +}), +}, + 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__7163_ObjectRowsTests_Generic__T_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_ObjectRowsTests_Generic__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__7163_ObjectArrayRowsTests_Generic__T1_T2_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests)), + Name = "ObjectArrayRowsTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, genericTypeCount: 2, parameters: global::TUnit.Core.ParameterMetadataFactory.ForGenericMethod(typeof(global::TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests), "Generic", false, 2, new global::TUnit.Core.ParameterMetadata[] +{ +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "first", new global::TUnit.Core.GenericParameter(0, true, "T1"), false), +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "second", new global::TUnit.Core.GenericParameter(1, true, "T2"), false) +})); + private static global::TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(new global::TUnit.Core.Exceptions.GenericTypeResolutionException("Could not infer the type arguments of generic test method 'Generic' from data source [MethodDataSource(nameof(Rows))]. Source-generated mode infers type arguments at compile time from the data source's declared type, not from the run-time type of its values, and that declared type does not determine them. Declare the data source with a type that does (for example IEnumerable> rather than IEnumerable), or list the type arguments with [GenerateGenericTest]."))); + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute(), + new global::TUnit.Core.MethodDataSourceAttribute("Rows") + }; + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests.Generic", + filePath: "", + lineNumber: 33, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + global::TUnit.Core.GenericConstraintViolationDataSource.Create("Could not infer the type arguments of generic test method 'Generic' from data source [MethodDataSource(nameof(Rows))]. Source-generated mode infers type arguments at compile time from the data source's declared type, not from the run-time type of its values, and that declared type does not determine them. Declare the data source with a type that does (for example IEnumerable> rather than IEnumerable), or list the type arguments with [GenerateGenericTest].", new global::TUnit.Core.MethodDataSourceAttribute("Rows") +{ + Factory = static dataGeneratorMetadata => global::TUnit.Core.Helpers.DataSourceFactories.FromEnumerable(static () => global::TUnit.TestProject.Bugs._7163.ObjectArrayRowsTests.Rows()), +}), +}, + 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__7163_ObjectArrayRowsTests_Generic__T1_T2_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_ObjectArrayRowsTests_Generic__T1_T2_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__7163_PartlyInferableTests_Generic__T_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.PartlyInferableTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.PartlyInferableTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.PartlyInferableTests)), + Name = "PartlyInferableTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.PartlyInferableTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, genericTypeCount: 1, parameters: global::TUnit.Core.ParameterMetadataFactory.ForGenericMethod(typeof(global::TUnit.TestProject.Bugs._7163.PartlyInferableTests), "Generic", false, 1, new global::TUnit.Core.ParameterMetadata[] +{ +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "value", new global::TUnit.Core.GenericParameter(0, true, "T"), false) +})); + private static global::TUnit.TestProject.Bugs._7163.PartlyInferableTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.PartlyInferableTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.PartlyInferableTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + switch (methodIndex) + { + case 0: + { + try + { + return new global::System.Threading.Tasks.ValueTask(instance.Generic(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)); + } + } + case 1: + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(new global::TUnit.Core.Exceptions.GenericTypeResolutionException("Could not infer the type arguments of generic test method 'Generic' from data source [MethodDataSource(nameof(Rows))]. Source-generated mode infers type arguments at compile time from the data source's declared type, not from the run-time type of its values, and that declared type does not determine them. Declare the data source with a type that does (for example IEnumerable> rather than IEnumerable), or list the type arguments with [GenerateGenericTest]."))); + } + default: + throw new global::System.ArgumentOutOfRangeException(nameof(methodIndex)); + } + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + switch (groupIndex) + { + case 0: + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute(), + new global::TUnit.Core.ArgumentsAttribute(5), + new global::TUnit.Core.MethodDataSourceAttribute("Rows") + }; + } + case 1: + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute(), + new global::TUnit.Core.ArgumentsAttribute(5), + new global::TUnit.Core.MethodDataSourceAttribute("Rows") + }; + } + default: + throw new global::System.ArgumentOutOfRangeException(nameof(groupIndex)); + } + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.PartlyInferableTests.Generic", + methodTypeArgumentsIdentity: "", + filePath: "", + lineNumber: 51, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.ArgumentsAttribute(5), +}, + methodMetadata: __mm_0, + createInstance: __CreateInstance_0, + invokeBody: __Invoke_0, + methodIndex: 0, + createAttributes: __Attributes_0, + attributeGroupIndex: 0), + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.PartlyInferableTests.Generic", + filePath: "", + lineNumber: 51, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + global::TUnit.Core.GenericConstraintViolationDataSource.Create("Could not infer the type arguments of generic test method 'Generic' from data source [MethodDataSource(nameof(Rows))]. Source-generated mode infers type arguments at compile time from the data source's declared type, not from the run-time type of its values, and that declared type does not determine them. Declare the data source with a type that does (for example IEnumerable> rather than IEnumerable), or list the type arguments with [GenerateGenericTest].", new global::TUnit.Core.MethodDataSourceAttribute("Rows") +{ + Factory = static dataGeneratorMetadata => global::TUnit.Core.Helpers.DataSourceFactories.FromEnumerable(static () => global::TUnit.TestProject.Bugs._7163.PartlyInferableTests.Rows()), +}), +}, + methodMetadata: __mm_0, + createInstance: __CreateInstance_0, + invokeBody: __Invoke_0, + methodIndex: 1, + createAttributes: __Attributes_0, + attributeGroupIndex: 1), + }; +} +internal static partial class TUnit_TestRegistration +{ + static readonly int _r_TUnit_TestProject_Bugs__7163_PartlyInferableTests_Generic__T_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_PartlyInferableTests_Generic__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__7163_GenerateGenericTestWithObjectRowsTests_Generic__T_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests)), + Name = "GenerateGenericTestWithObjectRowsTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, genericTypeCount: 1, parameters: global::TUnit.Core.ParameterMetadataFactory.ForGenericMethod(typeof(global::TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests), "Generic", false, 1, new global::TUnit.Core.ParameterMetadata[] +{ +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "value", new global::TUnit.Core.GenericParameter(0, true, "T"), false) +})); + private static global::TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + try + { + return new global::System.Threading.Tasks.ValueTask(instance.Generic(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.GenerateGenericTestAttribute(typeof(int)), + new global::TUnit.Core.MethodDataSourceAttribute("Rows") + }; + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests.Generic", + methodTypeArgumentsIdentity: "", + filePath: "", + lineNumber: 65, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.MethodDataSourceAttribute("Rows") + { + Factory = static dataGeneratorMetadata => global::TUnit.Core.Helpers.DataSourceFactories.FromEnumerable(static () => global::TUnit.TestProject.Bugs._7163.GenerateGenericTestWithObjectRowsTests.Rows()), + }, +}, + 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__7163_GenerateGenericTestWithObjectRowsTests_Generic__T_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_GenerateGenericTestWithObjectRowsTests_Generic__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__7163_NoDataSourceTests_Generic_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.NoDataSourceTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.NoDataSourceTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.NoDataSourceTests)), + Name = "NoDataSourceTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.NoDataSourceTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, genericTypeCount: 1); + private static global::TUnit.TestProject.Bugs._7163.NoDataSourceTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.NoDataSourceTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.NoDataSourceTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(new global::TUnit.Core.Exceptions.GenericTypeResolutionException("Could not infer the type arguments of generic test method 'Generic': it has no data source to infer them from. List the type arguments with [GenerateGenericTest]."))); + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute() + }; + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.NoDataSourceTests.Generic", + filePath: "", + lineNumber: 74, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + global::TUnit.Core.GenericConstraintViolationDataSource.Create("Could not infer the type arguments of generic test method 'Generic': it has no data source to infer them from. List the type arguments with [GenerateGenericTest]."), +}, + 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__7163_NoDataSourceTests_Generic_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_NoDataSourceTests_Generic_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__7163_ArgumentsAndDataSourceWithSameTypesTests_Generic__T_string_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests)), + Name = "ArgumentsAndDataSourceWithSameTypesTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, genericTypeCount: 1, parameters: global::TUnit.Core.ParameterMetadataFactory.ForGenericMethod(typeof(global::TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests), "Generic", false, 1, new global::TUnit.Core.ParameterMetadata[] +{ +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "value", new global::TUnit.Core.GenericParameter(0, true, "T"), false), +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(string), "label", new global::TUnit.Core.ConcreteType(typeof(string)), false) +})); + private static global::TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + try + { + return new global::System.Threading.Tasks.ValueTask(instance.Generic(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.MethodDataSourceAttribute("Rows") + }; + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests.Generic", + methodTypeArgumentsIdentity: "", + filePath: "", + lineNumber: 87, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.ArgumentsAttribute(1, "a"), + new global::TUnit.Core.MethodDataSourceAttribute("Rows") + { + Factory = static dataGeneratorMetadata => global::TUnit.Core.Helpers.DataSourceFactories.FromEnumerable(static () => global::TUnit.TestProject.Bugs._7163.ArgumentsAndDataSourceWithSameTypesTests.Rows()), + }, +}, + 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__7163_ArgumentsAndDataSourceWithSameTypesTests_Generic__T_string_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_ArgumentsAndDataSourceWithSameTypesTests_Generic__T_string_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__7163_TwoDataSourcesWithSameTypesTests_Generic__T_string_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests)), + Name = "TwoDataSourcesWithSameTypesTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::System.Threading.Tasks.Task), __classMetadata, genericTypeCount: 1, parameters: global::TUnit.Core.ParameterMetadataFactory.ForGenericMethod(typeof(global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests), "Generic", false, 1, new global::TUnit.Core.ParameterMetadata[] +{ +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "value", new global::TUnit.Core.GenericParameter(0, true, "T"), false), +global::TUnit.Core.ParameterMetadataFactory.Create(typeof(string), "label", new global::TUnit.Core.ConcreteType(typeof(string)), false) +})); + private static global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + try + { + return new global::System.Threading.Tasks.ValueTask(instance.Generic(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.MethodDataSourceAttribute("First"), + new global::TUnit.Core.MethodDataSourceAttribute("Second") + }; + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests.Generic", + methodTypeArgumentsIdentity: "", + filePath: "", + lineNumber: 110, + hasDataSource: true, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + new global::TUnit.Core.MethodDataSourceAttribute("First") + { + Factory = static dataGeneratorMetadata => global::TUnit.Core.Helpers.DataSourceFactories.FromEnumerable(static () => global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests.First()), + }, + new global::TUnit.Core.MethodDataSourceAttribute("Second") + { + Factory = static dataGeneratorMetadata => global::TUnit.Core.Helpers.DataSourceFactories.FromEnumerable(static () => global::TUnit.TestProject.Bugs._7163.TwoDataSourcesWithSameTypesTests.Second()), + }, +}, + 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__7163_TwoDataSourcesWithSameTypesTests_Generic__T_string_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_TwoDataSourcesWithSameTypesTests_Generic__T_string_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__7163_NestedGenericReturnTypeTests_Generic_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.NestedGenericReturnTypeTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.NestedGenericReturnTypeTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.NestedGenericReturnTypeTests)), + Name = "NestedGenericReturnTypeTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.NestedGenericReturnTypeTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::System.Threading.Tasks.Task<>), __classMetadata, genericTypeCount: 1); + private static global::TUnit.TestProject.Bugs._7163.NestedGenericReturnTypeTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.NestedGenericReturnTypeTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.NestedGenericReturnTypeTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(new global::TUnit.Core.Exceptions.GenericTypeResolutionException("Could not infer the type arguments of generic test method 'Generic': it has no data source to infer them from. List the type arguments with [GenerateGenericTest]."))); + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute() + }; + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.NestedGenericReturnTypeTests.Generic", + filePath: "", + lineNumber: 124, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + global::TUnit.Core.GenericConstraintViolationDataSource.Create("Could not infer the type arguments of generic test method 'Generic': it has no data source to infer them from. List the type arguments with [GenerateGenericTest]."), +}, + 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__7163_NestedGenericReturnTypeTests_Generic_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_NestedGenericReturnTypeTests_Generic_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__7163_NullableGenericReturnTypeTests_Generic_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.NullableGenericReturnTypeTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.NullableGenericReturnTypeTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.NullableGenericReturnTypeTests)), + Name = "NullableGenericReturnTypeTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.NullableGenericReturnTypeTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::System.Nullable<>), __classMetadata, genericTypeCount: 1); + private static global::TUnit.TestProject.Bugs._7163.NullableGenericReturnTypeTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.NullableGenericReturnTypeTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.NullableGenericReturnTypeTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + try + { + return global::TUnit.Core.AsyncConvert.Convert(() => instance.Generic()); + } + 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.GenerateGenericTestAttribute(typeof(int)) + }; + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.NullableGenericReturnTypeTests.Generic", + methodTypeArgumentsIdentity: "", + filePath: "", + lineNumber: 131, + 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__7163_NullableGenericReturnTypeTests_Generic_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_NullableGenericReturnTypeTests_Generic_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__7163_ContainingGenericReturnTypeTests_Generic_TestSource +{ + private static readonly global::TUnit.Core.ClassMetadata __classMetadata = global::TUnit.Core.ClassMetadata.GetOrAdd("TestsBase`1:global::TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests", new global::TUnit.Core.ClassMetadata + { + Type = typeof(global::TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests), + TypeInfo = new global::TUnit.Core.ConcreteType(typeof(global::TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests)), + Name = "ContainingGenericReturnTypeTests", + Namespace = "TUnit.TestProject.Bugs._7163", + Assembly = global::TUnit.Core.AssemblyMetadata.GetOrAdd("TestsBase`1", "TestsBase`1"), + Parameters = global::System.Array.Empty(), + Properties = global::System.Array.Empty(), + Parent = null + }); + private static readonly global::System.Type __classType = typeof(global::TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests); + private static readonly global::TUnit.Core.MethodMetadata __mm_0 = global::TUnit.Core.MethodMetadataFactory.Create("Generic", __classType, typeof(global::TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests.Outer<>.Inner), __classMetadata, genericTypeCount: 1); + private static global::TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests __CreateInstance_0(global::System.Type[] typeArgs, object?[] args) + { + return new global::TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests(); + } + private static global::System.Threading.Tasks.ValueTask __Invoke_0(global::TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests instance, int methodIndex, object?[] args, global::System.Threading.CancellationToken cancellationToken) + { + return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(new global::TUnit.Core.Exceptions.GenericTypeResolutionException("Could not infer the type arguments of generic test method 'Generic': it has no data source to infer them from. List the type arguments with [GenerateGenericTest]."))); + } + private static global::System.Attribute[] __Attributes_0(int groupIndex) + { + return new global::System.Attribute[] + { + new global::TUnit.Core.TestAttribute() + }; + } + public static readonly global::TUnit.Core.TestEntry[] Entries_0 = new global::TUnit.Core.TestEntry[] + { + global::TUnit.Core.TestEntryFactory.Create( + methodName: "Generic", + fullyQualifiedName: "TUnit.TestProject.Bugs._7163.ContainingGenericReturnTypeTests.Generic", + filePath: "", + lineNumber: 145, + testDataSources: new global::TUnit.Core.IDataSourceAttribute[] +{ + global::TUnit.Core.GenericConstraintViolationDataSource.Create("Could not infer the type arguments of generic test method 'Generic': it has no data source to infer them from. List the type arguments with [GenerateGenericTest]."), +}, + 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__7163_ContainingGenericReturnTypeTests_Generic_TestSource_0 = global::TUnit.Core.SourceRegistrar.RegisterEntries(static () => TUnit_TestProject_Bugs__7163_ContainingGenericReturnTypeTests_Generic_TestSource.Entries_0); +} diff --git a/tests/TUnit.Engine.Tests/Issue7163Tests.cs b/tests/TUnit.Engine.Tests/Issue7163Tests.cs new file mode 100644 index 00000000000..256a205a777 --- /dev/null +++ b/tests/TUnit.Engine.Tests/Issue7163Tests.cs @@ -0,0 +1,99 @@ +using Shouldly; +using TUnit.Engine.Tests.Enums; + +namespace TUnit.Engine.Tests; + +/// +/// A generic test method whose type arguments its data source's declared type cannot determine is +/// discovered in both modes. Reflection mode infers them from the row values and runs the rows. +/// Source-generated mode cannot, so it reports each row as a failed test that explains the fix, +/// rather than registering no test at all (#7163). +/// +public class Issue7163Tests(TestMode testMode) : InvokableTestBase(testMode) +{ + private const string Namespace = "/*/TUnit.TestProject.Bugs._7163"; + private const string CannotInfer = "Could not infer the type arguments of generic test method 'Generic' from data source [MethodDataSource(nameof(Rows))]"; + + [Test] + [Arguments("ObjectRowsTests", 2)] + [Arguments("ObjectArrayRowsTests", 1)] + public async Task Uninferable_Rows_Are_Not_Dropped(string className, int rows) + { + await RunTestsWithFilter( + $"{Namespace}/{className}/*", + testMode == TestMode.Reflection + ? + [ + result => result.ResultSummary.Counters.Total.ShouldBe(rows), + result => result.ResultSummary.Counters.Passed.ShouldBe(rows), + ] + : + [ + result => result.ResultSummary.Counters.Total.ShouldBe(rows), + result => result.ResultSummary.Counters.Failed.ShouldBe(rows), + result => result.Results.ShouldAllBe(x => x.TestName == "Generic"), + result => result.Results.ShouldAllBe(x => x.Output!.ErrorInfo!.Message!.Contains(CannotInfer)), + ]); + } + + [Test] + public async Task Inferable_Row_Runs_Beside_Uninferable_Source() + { + await RunTestsWithFilter( + $"{Namespace}/PartlyInferableTests/*", + testMode == TestMode.Reflection + ? + [ + result => result.ResultSummary.Counters.Total.ShouldBe(2), + result => result.ResultSummary.Counters.Passed.ShouldBe(2), + ] + : + [ + result => result.ResultSummary.Counters.Total.ShouldBe(2), + result => result.ResultSummary.Counters.Passed.ShouldBe(1), + result => result.Results.Single(x => x.Outcome == "Passed").TestName.ShouldBe("Generic(5)"), + result => result.Results.Single(x => x.Outcome == "Failed").Output?.ErrorInfo?.Message.ShouldContain(CannotInfer), + ]); + } + + [Test] + [Arguments("GenerateGenericTestWithObjectRowsTests")] + [Arguments("NullableGenericReturnTypeTests")] + public async Task GenerateGenericTest_Runs_In_Both_Modes(string className) + { + await RunTestsWithFilter( + $"{Namespace}/{className}/*", + [ + result => result.ResultSummary.Counters.Total.ShouldBe(1), + result => result.ResultSummary.Counters.Passed.ShouldBe(1), + ]); + } + + [Test] + [Arguments("ArgumentsAndDataSourceWithSameTypesTests")] + [Arguments("TwoDataSourcesWithSameTypesTests")] + public async Task Sources_Inferring_The_Same_Types_All_Run_In_Both_Modes(string className) + { + await RunTestsWithFilter( + $"{Namespace}/{className}/*", + [ + result => result.ResultSummary.Counters.Total.ShouldBe(2), + result => result.ResultSummary.Counters.Passed.ShouldBe(2), + ]); + } + + [Test] + [Arguments("NoDataSourceTests")] + [Arguments("NestedGenericReturnTypeTests")] + [Arguments("ContainingGenericReturnTypeTests")] + public async Task Method_Without_Data_Source_Fails_In_Both_Modes(string className) + { + await RunTestsWithFilter( + $"{Namespace}/{className}/*", + [ + result => result.ResultSummary.Counters.Total.ShouldBe(1), + result => result.ResultSummary.Counters.Failed.ShouldBe(1), + result => result.Results.Single().TestName.ShouldBe("Generic"), + ]); + } +} diff --git a/tests/TUnit.TestProject/Bugs/_7163/UninferableGenericMethodTests.cs b/tests/TUnit.TestProject/Bugs/_7163/UninferableGenericMethodTests.cs new file mode 100644 index 00000000000..85d235063e2 --- /dev/null +++ b/tests/TUnit.TestProject/Bugs/_7163/UninferableGenericMethodTests.cs @@ -0,0 +1,147 @@ +namespace TUnit.TestProject.Bugs._7163; + +// A generic test method whose type arguments cannot be inferred from a data source's declared type +// must not vanish in source-generated mode. Reflection mode infers them from each row's run-time +// values; source-generated mode cannot, so it reports each row as a failed test that says how to fix +// it, instead of registering no test at all (#7163). +// +// These classes carry no [EngineTest] attribute because their outcome differs between the modes. +// TUnit.Engine.Tests targets them by name. + +// The issue's repro: rows typed `object` say nothing about T. +public class ObjectRowsTests +{ + public static IEnumerable Rows() + { + yield return 1; + yield return 2; + } + + [Test] + [MethodDataSource(nameof(Rows))] + public async Task Generic(T value) => await Assert.That((object?)value).IsNotNull(); +} + +// `object[]` rows, spread across two type parameters. +public class ObjectArrayRowsTests +{ + public static IEnumerable Rows() + { + yield return [1, "a"]; + } + + [Test] + [MethodDataSource(nameof(Rows))] + public async Task Generic(T1 first, T2 second) + { + await Assert.That((object?)first).IsNotNull(); + await Assert.That((object?)second).IsNotNull(); + } +} + +// One source infers the type arguments and another does not. The inferable row keeps running; the +// other source's rows must not be dropped. +public class PartlyInferableTests +{ + public static IEnumerable Rows() + { + yield return 1; + } + + [Test] + [Arguments(5)] + [MethodDataSource(nameof(Rows))] + public async Task Generic(T value) => await Assert.That((object?)value).IsNotNull(); +} + +// With [GenerateGenericTest] the type arguments are listed, so the rows run on that type in both modes. +public class GenerateGenericTestWithObjectRowsTests +{ + public static IEnumerable Rows() + { + yield return 1; + } + + [Test] + [GenerateGenericTest(typeof(int))] + [MethodDataSource(nameof(Rows))] + public async Task Generic(T value) => await Assert.That((object?)value).IsNotNull(); +} + +// No data source at all: nothing can infer T in either mode. +public class NoDataSourceTests +{ + [Test] + public async Task Generic() => await Assert.That(typeof(T)).IsNotNull(); +} + +// An [Arguments] row and a method data source that infer the same type arguments share one +// instantiation, so both run instead of the data source being reported as uninferable. +public class ArgumentsAndDataSourceWithSameTypesTests +{ + public static IEnumerable> Rows() + { + yield return () => (2, "b"); + } + + [Test] + [Arguments(1, "a")] + [MethodDataSource(nameof(Rows))] + public async Task Generic(T value, string label) + { + await Assert.That((object?)value).IsNotNull(); + await Assert.That(label).IsNotNull(); + } +} + +// Two method data sources declared with the same type infer the same type arguments; both run. +public class TwoDataSourcesWithSameTypesTests +{ + public static IEnumerable> First() + { + yield return () => (1, "a"); + } + + public static IEnumerable> Second() + { + yield return () => (2, "b"); + } + + [Test] + [MethodDataSource(nameof(First))] + [MethodDataSource(nameof(Second))] + public async Task Generic(T value, string label) + { + await Assert.That((object?)value).IsNotNull(); + await Assert.That(label).IsNotNull(); + } +} + +// The failing entry's metadata names the return type outside the method, where T does not exist, +// so a return type that nests T must still compile. +public class NestedGenericReturnTypeTests +{ + [Test] + public Task Generic() => Task.FromResult(Array.Empty()); +} + +// Roslyn displays a Nullable return type as `T?`, so it needs its own open form in the metadata. +public class NullableGenericReturnTypeTests +{ + [Test] + [GenerateGenericTest(typeof(int))] + public T? Generic() where T : struct => default; +} + +// A nested type of a generic type takes its type parameters from its containing type, so +// Outer.Inner mentions T without having type arguments of its own. +public class ContainingGenericReturnTypeTests +{ + public class Outer + { + public class Inner; + } + + [Test] + public Outer.Inner Generic() => new(); +}