Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
b7376e1
Refactor Engine tests for a speeder pipeline
thomhurst Jun 1, 2025
123c9a4
Whoops
thomhurst Jun 1, 2025
67259ad
Update snaps
thomhurst Jun 1, 2025
77c9758
Print command
thomhurst Jun 1, 2025
85e4958
Fix
thomhurst Jun 1, 2025
e30004f
Fix
thomhurst Jun 1, 2025
294e843
WIP
thomhurst Jun 1, 2025
2c508be
Merge branch 'main' into feature/refactor-engine-tests
thomhurst Jun 2, 2025
8912536
Refactor Context objects
thomhurst Jun 2, 2025
f93f9e7
WIP
thomhurst Jun 2, 2025
40cdde8
WIP
thomhurst Jun 2, 2025
2ff72b0
WIP
thomhurst Jun 2, 2025
7258a0e
WIP
thomhurst Jun 2, 2025
1789357
Fixes
thomhurst Jun 2, 2025
9bf7157
Fixes
thomhurst Jun 2, 2025
b834e87
Fix
thomhurst Jun 2, 2025
a8d2b82
Fix
thomhurst Jun 2, 2025
a38c903
Fixes
thomhurst Jun 2, 2025
4095c5b
Fixes
thomhurst Jun 2, 2025
24f9153
Fixes
thomhurst Jun 2, 2025
b9bf46e
Fixes
thomhurst Jun 2, 2025
b7de66a
Fixes
thomhurst Jun 2, 2025
6873dd0
Fixes
thomhurst Jun 2, 2025
3deda82
Tweak
thomhurst Jun 2, 2025
a3b9110
Update WindowsOnlyAttribute.cs
thomhurst Jun 2, 2025
f1adb6d
Update snaps
thomhurst Jun 3, 2025
e9218e4
Merge branch 'main' into feature/refactor-contexts
thomhurst Jun 3, 2025
00ac473
WIP
thomhurst Jun 3, 2025
39caf82
Fix nested class data sources
thomhurst Jun 3, 2025
2dd5765
WIP
thomhurst Jun 3, 2025
b1c6283
WIP
thomhurst Jun 3, 2025
04e35e3
WIP
thomhurst Jun 3, 2025
c99ac96
WIP
thomhurst Jun 3, 2025
0065881
WIP
thomhurst Jun 3, 2025
d19de4d
WIP
thomhurst Jun 3, 2025
11cf56d
WIP
thomhurst Jun 3, 2025
8d9ad0d
Fixes
thomhurst Jun 3, 2025
72f5d6e
Fix ReturnValue tests
thomhurst Jun 4, 2025
c03b98a
WIP
thomhurst Jun 4, 2025
2408581
Fixes
thomhurst Jun 4, 2025
f0f88a1
Fix
thomhurst Jun 4, 2025
369b1b5
Fixes
thomhurst Jun 4, 2025
a68c67a
WIP
thomhurst Jun 4, 2025
f97cce7
Fix
thomhurst Jun 4, 2025
493d784
Fixes
thomhurst Jun 4, 2025
b8af095
Fixes
thomhurst Jun 4, 2025
09df420
Fixes
thomhurst Jun 4, 2025
72dfc6a
Fixes
thomhurst Jun 4, 2025
700a9d1
Fixes
thomhurst Jun 4, 2025
b306566
WIP
thomhurst Jun 4, 2025
7f1f8fd
Fixes
thomhurst Jun 4, 2025
fcaaea0
Merge branch 'main' into feature/refactor-contexts
thomhurst Jun 4, 2025
5011e5e
Fixes
thomhurst Jun 4, 2025
fd5f46f
WIP
thomhurst Jun 4, 2025
e353d1c
if statement
thomhurst Jun 4, 2025
c5a5513
PropertyInitializationGenerator
thomhurst Jun 4, 2025
ddbafa1
Fixes
thomhurst Jun 4, 2025
c26f501
Add common interface method for IDataSourceGeneratorAttribute.cs
thomhurst Jun 4, 2025
80a81e9
Fix?
thomhurst Jun 5, 2025
56f413c
Fix
thomhurst Jun 5, 2025
7b8d7d5
Fixes
thomhurst Jun 5, 2025
0c937a8
Update snaps
thomhurst Jun 5, 2025
a1cdb5a
Remove debug line
thomhurst Jun 5, 2025
fba974c
Remove logs
thomhurst Jun 5, 2025
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
Prev Previous commit
Next Next commit
Fix ReturnValue tests
  • Loading branch information
thomhurst committed Jun 4, 2025
commit 72f5d6e94b97c5d4912851cf06ea5ee31f6a3dba
90 changes: 77 additions & 13 deletions TUnit.Core/AsyncConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace TUnit.Core;
public static class AsyncConvert
{
private static Type? _fSharpAsyncType;

[MethodImpl(MethodImplOptions.AggressiveInlining
#if NET
| MethodImplOptions.AggressiveOptimization
Expand All @@ -31,7 +31,7 @@ public static ValueTask Convert(Func<ValueTask> action)
{
return action();
}

[MethodImpl(MethodImplOptions.AggressiveInlining
#if NET
| MethodImplOptions.AggressiveOptimization
Expand Down Expand Up @@ -60,31 +60,31 @@ public static ValueTask ConvertObject(object? invoke)
{
return default;
}

if (invoke is Func<object> syncFunc)
{
syncFunc();
return default;
}

if (invoke is Func<Task> asyncFunc)
{
return Convert(asyncFunc);
}

if (invoke is Func<ValueTask> asyncValueFunc)
{
return Convert(asyncValueFunc);
}


if (invoke is Task task)
{
if(task is { IsCompleted: true, IsFaulted: false })
{
return default;
}

if(task.IsFaulted || !task.IsCompleted)
{
return new ValueTask(task);
Expand All @@ -96,16 +96,28 @@ public static ValueTask ConvertObject(object? invoke)
return valueTask;
}

// If it has a GetAwaiter method, we can assume it's an awaitable type
if (TryGetAwaitableTask(invoke, out var awaitable))
{
if (awaitable is { IsCompleted: true, IsFaulted: false })
{
return default;
}

return new ValueTask(awaitable);
}

var type = invoke.GetType();
if (type.IsGenericType
if (type.IsGenericType
&& type.GetGenericTypeDefinition().FullName == "Microsoft.FSharp.Control.FSharpAsync`1")
{
return StartAsFSharpTask(invoke, type);
}

throw new ArgumentException("Invalid object type: " + type.Name, nameof(invoke));
// We can assume it's not awaitable, and so the invocation should have completed synchronously.
return default;
}

[UnconditionalSuppressMessage("Trimming", "IL2077:Target parameter argument does not satisfy \'DynamicallyAccessedMembersAttribute\' in call to target method. The source field does not have matching annotations.")]
[UnconditionalSuppressMessage("Trimming", "IL2072:Target parameter argument does not satisfy \'DynamicallyAccessedMembersAttribute\' in call to target method. The return value of the source method does not have matching annotations.")]
[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with \'RequiresDynamicCodeAttribute\' may break functionality when AOT compiling.")]
Expand All @@ -119,7 +131,59 @@ private static ValueTask StartAsFSharpTask(object invoke, Type type)

var fSharpTask = (Task)startAsTaskOpenGenericMethod.MakeGenericMethod(type.GetGenericArguments()[0])
.Invoke(null, [invoke, null, null])!;

return new ValueTask(fSharpTask);
}
}

[UnconditionalSuppressMessage("Trimming", "IL2075:\'this\' argument does not satisfy \'DynamicallyAccessedMembersAttribute\' in call to target method. The return value of the source method does not have matching annotations.")]
public static bool TryGetAwaitableTask(object awaitable, [NotNullWhen(true)] out Task? task)
{
var getAwaiter = awaitable.GetType().GetMethod("GetAwaiter", Type.EmptyTypes);

if (getAwaiter == null)
{
task = null;
return false;
}

var awaiter = getAwaiter.Invoke(awaitable, null);

if (awaiter == null)
{
task = null;
return false;
}

var isCompletedProp = awaiter.GetType().GetProperty("IsCompleted");

if (isCompletedProp == null)
{
task = null;
return false;
}

var isCompleted = isCompletedProp.GetValue(awaiter) as bool?;

if (isCompleted == true)
{
task = Task.CompletedTask;
return true;
}

if(!isCompleted.HasValue)
{
task = null;
return false;
}

var tcs = new TaskCompletionSource<object?>();

var onCompleted = awaiter.GetType().GetMethod("OnCompleted", [typeof(Action)]);

onCompleted!.Invoke(awaiter, [new Action(() => tcs.SetResult(null))]);

task = tcs.Task;

return true;
}
}