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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions TUnit.Core/Extensions/TupleExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace TUnit.Core.Extensions;
using System.Runtime.CompilerServices;

namespace TUnit.Core.Extensions;

internal static class TupleExtensions
{
Expand All @@ -7,7 +9,18 @@ internal static class TupleExtensions
{
return [value];
}


#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP
public static object?[] ToObjectArray(this ITuple tuple)
{
var result = new object?[tuple.Length];
for (var i = 0; i < tuple.Length; i++)
{
result[i] = tuple[i];
}
return result;
}
#else
public static object?[] ToObjectArray<T1, T2>(this (T1, T2) tuple)
{
return [tuple.Item1, tuple.Item2];
Expand All @@ -27,19 +40,20 @@ internal static class TupleExtensions
{
return [tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5];
}

public static object?[] ToObjectArray<T1, T2, T3, T4, T5, T6>(this (T1, T2, T3, T4, T5, T6) tuple)
{
return [tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5, tuple.Item6];
}

public static object?[] ToObjectArray<T1, T2, T3, T4, T5, T6, T7>(this (T1, T2, T3, T4, T5, T6, T7) tuple)
{
return [tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5, tuple.Item6, tuple.Item7];
}

public static object?[] ToObjectArray<T1, T2, T3, T4, T5, T6, T7, T8>(this (T1, T2, T3, T4, T5, T6, T7, T8) tuple)
{
return [tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5, tuple.Item6, tuple.Item7, tuple.Item8];
}
#endif
}
24 changes: 22 additions & 2 deletions TUnit.Core/Helpers/DataConversionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,25 @@ public static class DataConversionHelper
}
}

#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP
/// <summary>
/// Converts IAsyncEnumerable of any tuple type to IAsyncEnumerable<object?[]> using ITuple
/// </summary>
public static async IAsyncEnumerable<object?[]> ConvertAsyncEnumerableTupleToObjectArrays<T>(
IAsyncEnumerable<T> source,
[EnumeratorCancellation] CancellationToken ct = default) where T : ITuple
{
await foreach (var tuple in source.WithCancellation(ct))
{
var items = new object?[tuple.Length];
for (var i = 0; i < tuple.Length; i++)
{
items[i] = tuple[i];
}
yield return items;
}
}
#else
/// <summary>
/// Converts IAsyncEnumerable<(T1, T2)> to IAsyncEnumerable<object?[]>
/// </summary>
Expand Down Expand Up @@ -204,6 +223,7 @@ public static class DataConversionHelper
yield return [item1, item2, item3, item4, item5];
}
}
#endif

/// <summary>
/// Wraps a Task<IEnumerable<T>> to ensure it returns object arrays
Expand Down Expand Up @@ -232,8 +252,7 @@ public static class DataConversionHelper
}
return result;
}
#endif

#else
/// <summary>
/// Unwraps a ValueTuple<T1, T2> to an object?[] array (optimized for 2-tuples)
/// </summary>
Expand Down Expand Up @@ -305,4 +324,5 @@ public static class DataConversionHelper
{
return [tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5, tuple.Item6, tuple.Item7, tuple.Item8, tuple.Item9, tuple.Item10];
}
#endif
}
34 changes: 4 additions & 30 deletions TUnit.Core/Helpers/DataSourceHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ public static T InvokeIfFunc<T>(object? value)
}
}

#if !NETSTANDARD2_1_OR_GREATER && !NETCOREAPP
/// <summary>
/// Generic tuple unwrapping for when types are known at compile time
/// </summary>
Expand All @@ -164,6 +165,7 @@ public static T InvokeIfFunc<T>(object? value)

public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7>(ValueTuple<T1, T2, T3, T4, T5, T6, T7> tuple)
=> [tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5, tuple.Item6, tuple.Item7];
#endif

/// <summary>
/// AOT-compatible data source processor for when the return type is known at compile time
Expand Down Expand Up @@ -378,7 +380,7 @@ public static T InvokeIfFunc<T>(object? value)
{
// Special case: If there's a single parameter that expects a tuple type,
// and the item is a tuple, don't unwrap
if (expectedTypes.Length == 1 && IsTupleType(expectedTypes[0]))
if (expectedTypes.Length == 1 && TupleHelper.IsTupleType(expectedTypes[0]))
{
return [item];
}
Expand Down Expand Up @@ -417,7 +419,7 @@ public static T InvokeIfFunc<T>(object? value)
var expectedType = expectedTypes[typeIndex];

// Check if the expected type is a tuple type
if (IsTupleType(expectedType) && IsTuple(element))
if (TupleHelper.IsTupleType(expectedType) && IsTuple(element))
{
// Keep nested tuple as-is
result.Add(element);
Expand All @@ -439,34 +441,6 @@ public static T InvokeIfFunc<T>(object? value)
return UnwrapTupleAot(value);
}

/// <summary>
/// Checks if a Type represents a tuple type.
/// </summary>
private static bool IsTupleType(Type type)
{
if (!type.IsGenericType)
{
return false;
}

var genericType = type.GetGenericTypeDefinition();
return genericType == typeof(ValueTuple<>) ||
genericType == typeof(ValueTuple<,>) ||
genericType == typeof(ValueTuple<,,>) ||
genericType == typeof(ValueTuple<,,,>) ||
genericType == typeof(ValueTuple<,,,,>) ||
genericType == typeof(ValueTuple<,,,,,>) ||
genericType == typeof(ValueTuple<,,,,,,>) ||
genericType == typeof(ValueTuple<,,,,,,,>) ||
genericType == typeof(Tuple<>) ||
genericType == typeof(Tuple<,>) ||
genericType == typeof(Tuple<,,>) ||
genericType == typeof(Tuple<,,,>) ||
genericType == typeof(Tuple<,,,,>) ||
genericType == typeof(Tuple<,,,,,>) ||
genericType == typeof(Tuple<,,,,,,>) ||
genericType == typeof(Tuple<,,,,,,,>);
}

public static bool IsTuple(object? obj)
{
Expand Down
28 changes: 1 addition & 27 deletions TUnit.Engine/Helpers/DataUnwrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public static (object?[] Data, TestDataRowMetadata? Metadata) UnwrapWithTypesAnd
if (values.Length == 1 &&
expectedParameters.Length == 1 &&
DataSourceHelpers.IsTuple(values[0]) &&
IsTupleType(expectedParameters[0].Type))
TupleHelper.IsTupleType(expectedParameters[0].Type))
{
return values;
}
Expand All @@ -99,30 +99,4 @@ public static (object?[] Data, TestDataRowMetadata? Metadata) UnwrapWithTypesAnd

return values;
}

private static bool IsTupleType(Type type)
{
if (!type.IsGenericType)
{
return false;
}

var genericType = type.GetGenericTypeDefinition();
return genericType == typeof(ValueTuple<>) ||
genericType == typeof(ValueTuple<,>) ||
genericType == typeof(ValueTuple<,,>) ||
genericType == typeof(ValueTuple<,,,>) ||
genericType == typeof(ValueTuple<,,,,>) ||
genericType == typeof(ValueTuple<,,,,,>) ||
genericType == typeof(ValueTuple<,,,,,,>) ||
genericType == typeof(ValueTuple<,,,,,,,>) ||
genericType == typeof(Tuple<>) ||
genericType == typeof(Tuple<,>) ||
genericType == typeof(Tuple<,,>) ||
genericType == typeof(Tuple<,,,>) ||
genericType == typeof(Tuple<,,,,>) ||
genericType == typeof(Tuple<,,,,,>) ||
genericType == typeof(Tuple<,,,,,,>) ||
genericType == typeof(Tuple<,,,,,,,>);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2046,27 +2046,13 @@ namespace .Helpers
{
[.(typeof(..<ConvertAsyncEnumerableToObjectArrays>d__2<T>))]
public static .<object?[]> ConvertAsyncEnumerableToObjectArrays<T>(.<T> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple2ToObjectArrays>d__3<T1?, T2?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple2ToObjectArrays<T1, T2>(.<<T1, T2>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple3ToObjectArrays>d__4<T1?, T2?, T3?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple3ToObjectArrays<T1, T2, T3>(.<<T1, T2, T3>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple4ToObjectArrays>d__5<T1?, T2?, T3?, T4?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple4ToObjectArrays<T1, T2, T3, T4>(.<<T1, T2, T3, T4>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple5ToObjectArrays>d__6<T1?, T2?, T3?, T4?, T5?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple5ToObjectArrays<T1, T2, T3, T4, T5>(.<<T1, T2, T3, T4, T5>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertToAsyncEnumerableInternal>d__1?))]
[.(typeof(..<ConvertAsyncEnumerableTupleToObjectArrays>d__3<T>))]
public static .<object?[]> ConvertAsyncEnumerableTupleToObjectArrays<T>(.<T> source, [.] .CancellationToken ct = default)
where T : . { }
[.(typeof(..<ConvertToAsyncEnumerableInternal>d__1))]
public static .<object?[]> ConvertToAsyncEnumerableInternal(.<object?[]> data, [.] .CancellationToken ct = default) { }
public static .<object?[]> ConvertToObjectArrays(object? data) { }
public static object?[] UnwrapTuple(. tuple) { }
public static object?[] UnwrapTuple<T1, T2>(<T1, T2> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3>(<T1, T2, T3> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4>(<T1, T2, T3, T4> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5>(<T1, T2, T3, T4, T5> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6>(<T1, T2, T3, T4, T5, T6> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7>(<T1, T2, T3, T4, T5, T6, T7> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7, T8>(<T1, T2, T3, T4, T5, T6, T7, <T8>> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>(<T1, T2, T3, T4, T5, T6, T7, <T8, T9>> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(<T1, T2, T3, T4, T5, T6, T7, <T8, T9, T10>> tuple) { }
public static .<.<object?[]>> WrapTaskEnumerableAsObjectArrays<T>(.<.<T>> task) { }
}
public static class DataSourceHelpers
Expand All @@ -2093,13 +2079,6 @@ namespace .Helpers
"success",
"createdInstance"})]
public static .<<bool, object?>> TryCreateWithInitializerAsync( type, .MethodMetadata testInformation, string testSessionId) { }
public static object?[] UnwrapTuple<T1>(<T1> tuple) { }
public static object?[] UnwrapTuple<T1, T2>(<T1, T2> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3>(<T1, T2, T3> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4>(<T1, T2, T3, T4> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5>(<T1, T2, T3, T4, T5> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6>(<T1, T2, T3, T4, T5, T6> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7>(<T1, T2, T3, T4, T5, T6, T7> tuple) { }
public static object?[] UnwrapTupleAot(object? value) { }
}
public static class DecimalParsingHelper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2046,27 +2046,13 @@ namespace .Helpers
{
[.(typeof(..<ConvertAsyncEnumerableToObjectArrays>d__2<T>))]
public static .<object?[]> ConvertAsyncEnumerableToObjectArrays<T>(.<T> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple2ToObjectArrays>d__3<T1?, T2?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple2ToObjectArrays<T1, T2>(.<<T1, T2>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple3ToObjectArrays>d__4<T1?, T2?, T3?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple3ToObjectArrays<T1, T2, T3>(.<<T1, T2, T3>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple4ToObjectArrays>d__5<T1?, T2?, T3?, T4?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple4ToObjectArrays<T1, T2, T3, T4>(.<<T1, T2, T3, T4>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple5ToObjectArrays>d__6<T1?, T2?, T3?, T4?, T5?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple5ToObjectArrays<T1, T2, T3, T4, T5>(.<<T1, T2, T3, T4, T5>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertToAsyncEnumerableInternal>d__1?))]
[.(typeof(..<ConvertAsyncEnumerableTupleToObjectArrays>d__3<T>))]
public static .<object?[]> ConvertAsyncEnumerableTupleToObjectArrays<T>(.<T> source, [.] .CancellationToken ct = default)
where T : . { }
[.(typeof(..<ConvertToAsyncEnumerableInternal>d__1))]
public static .<object?[]> ConvertToAsyncEnumerableInternal(.<object?[]> data, [.] .CancellationToken ct = default) { }
public static .<object?[]> ConvertToObjectArrays(object? data) { }
public static object?[] UnwrapTuple(. tuple) { }
public static object?[] UnwrapTuple<T1, T2>(<T1, T2> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3>(<T1, T2, T3> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4>(<T1, T2, T3, T4> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5>(<T1, T2, T3, T4, T5> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6>(<T1, T2, T3, T4, T5, T6> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7>(<T1, T2, T3, T4, T5, T6, T7> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7, T8>(<T1, T2, T3, T4, T5, T6, T7, <T8>> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>(<T1, T2, T3, T4, T5, T6, T7, <T8, T9>> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(<T1, T2, T3, T4, T5, T6, T7, <T8, T9, T10>> tuple) { }
public static .<.<object?[]>> WrapTaskEnumerableAsObjectArrays<T>(.<.<T>> task) { }
}
public static class DataSourceHelpers
Expand All @@ -2093,13 +2079,6 @@ namespace .Helpers
"success",
"createdInstance"})]
public static .<<bool, object?>> TryCreateWithInitializerAsync( type, .MethodMetadata testInformation, string testSessionId) { }
public static object?[] UnwrapTuple<T1>(<T1> tuple) { }
public static object?[] UnwrapTuple<T1, T2>(<T1, T2> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3>(<T1, T2, T3> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4>(<T1, T2, T3, T4> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5>(<T1, T2, T3, T4, T5> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6>(<T1, T2, T3, T4, T5, T6> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7>(<T1, T2, T3, T4, T5, T6, T7> tuple) { }
public static object?[] UnwrapTupleAot(object? value) { }
}
public static class DecimalParsingHelper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2046,27 +2046,13 @@ namespace .Helpers
{
[.(typeof(..<ConvertAsyncEnumerableToObjectArrays>d__2<T>))]
public static .<object?[]> ConvertAsyncEnumerableToObjectArrays<T>(.<T> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple2ToObjectArrays>d__3<T1?, T2?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple2ToObjectArrays<T1, T2>(.<<T1, T2>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple3ToObjectArrays>d__4<T1?, T2?, T3?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple3ToObjectArrays<T1, T2, T3>(.<<T1, T2, T3>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple4ToObjectArrays>d__5<T1?, T2?, T3?, T4?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple4ToObjectArrays<T1, T2, T3, T4>(.<<T1, T2, T3, T4>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertAsyncEnumerableTuple5ToObjectArrays>d__6<T1?, T2?, T3?, T4?, T5?>?))]
public static .<object?[]> ConvertAsyncEnumerableTuple5ToObjectArrays<T1, T2, T3, T4, T5>(.<<T1, T2, T3, T4, T5>> source, [.] .CancellationToken ct = default) { }
[.(typeof(..<ConvertToAsyncEnumerableInternal>d__1?))]
[.(typeof(..<ConvertAsyncEnumerableTupleToObjectArrays>d__3<T>))]
public static .<object?[]> ConvertAsyncEnumerableTupleToObjectArrays<T>(.<T> source, [.] .CancellationToken ct = default)
where T : . { }
[.(typeof(..<ConvertToAsyncEnumerableInternal>d__1))]
public static .<object?[]> ConvertToAsyncEnumerableInternal(.<object?[]> data, [.] .CancellationToken ct = default) { }
public static .<object?[]> ConvertToObjectArrays(object? data) { }
public static object?[] UnwrapTuple(. tuple) { }
public static object?[] UnwrapTuple<T1, T2>(<T1, T2> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3>(<T1, T2, T3> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4>(<T1, T2, T3, T4> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5>(<T1, T2, T3, T4, T5> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6>(<T1, T2, T3, T4, T5, T6> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7>(<T1, T2, T3, T4, T5, T6, T7> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7, T8>(<T1, T2, T3, T4, T5, T6, T7, <T8>> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>(<T1, T2, T3, T4, T5, T6, T7, <T8, T9>> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(<T1, T2, T3, T4, T5, T6, T7, <T8, T9, T10>> tuple) { }
public static .<.<object?[]>> WrapTaskEnumerableAsObjectArrays<T>(.<.<T>> task) { }
}
public static class DataSourceHelpers
Expand All @@ -2093,13 +2079,6 @@ namespace .Helpers
"success",
"createdInstance"})]
public static .<<bool, object?>> TryCreateWithInitializerAsync( type, .MethodMetadata testInformation, string testSessionId) { }
public static object?[] UnwrapTuple<T1>(<T1> tuple) { }
public static object?[] UnwrapTuple<T1, T2>(<T1, T2> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3>(<T1, T2, T3> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4>(<T1, T2, T3, T4> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5>(<T1, T2, T3, T4, T5> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6>(<T1, T2, T3, T4, T5, T6> tuple) { }
public static object?[] UnwrapTuple<T1, T2, T3, T4, T5, T6, T7>(<T1, T2, T3, T4, T5, T6, T7> tuple) { }
public static object?[] UnwrapTupleAot(object? value) { }
}
public static class DecimalParsingHelper
Expand Down
Loading