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
8 changes: 8 additions & 0 deletions src/tests/async/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project>
<PropertyGroup>
<!-- runtime async testing in main repo NYI -->
<DisableProjectBuild>true</DisableProjectBuild>
</PropertyGroup>

<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.targets, $(MSBuildThisFileDirectory)..))" />
</Project>
21 changes: 21 additions & 0 deletions src/tests/async/asynctests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<MergedWrapperProjectReference Include="*/**/*.??proj" />
<MergedWrapperProjectReference Include="*.??proj" />
<MergedWrapperProjectReference Remove="$(MSBuildProjectName).csproj" />

<!-- Remove manual benchmarks from the test wrapper -->
<MergedWrapperProjectReference Remove="eh-microbench.csproj" />
<MergedWrapperProjectReference Remove="gc-roots-scan.csproj" />
<MergedWrapperProjectReference Remove="mincallcost-microbench.csproj" />

<MergedWrapperProjectReference Remove="syncfibonacci-with-yields.csproj" />
<MergedWrapperProjectReference Remove="syncfibonacci-without-yields.csproj" />
<MergedWrapperProjectReference Remove="taskbased-asyncfibonacci-with-yields.csproj" />
<MergedWrapperProjectReference Remove="taskbased-asyncfibonacci-without-yields.csproj" />
<MergedWrapperProjectReference Remove="valuetaskbased-asyncfibonacci-without-yields.csproj" />
<MergedWrapperProjectReference Remove="valuetaskbased-asynfibonacci-with-yields.csproj" />
</ItemGroup>

<Import Project="$(TestSourceDir)MergedTestRunner.targets" />
</Project>
52 changes: 52 additions & 0 deletions src/tests/async/awaitingnotasync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Xunit;

public class AwaitNotAsync
{
[Fact]
public static void TestEntryPoint()
{
AsyncEntryPoint().Wait();
}

private static async Task<T> GetTask<T>(T arg)
{
await Task.Yield();
return arg;
}

// TODO: switch every other scenario to use ValueTask
private static async ValueTask<T> GetValueTask<T>(T arg)
{
await Task.Yield();
return arg;
}

private static Task<int> sField;

private static Task<int> sProp => GetTask(6);

private static T sIdentity<T>(T arg) => arg;

private static async2 Task AsyncEntryPoint()
{
// static field
sField = GetTask(5);
Assert.Equal(5, await sField);

// property
Assert.Equal(6, await sProp);

// generic identity
Assert.Equal(6, await sIdentity(sProp));

// await(await ...))
Assert.Equal(7, await await await GetTask(GetTask(GetTask(7))));

}
}
8 changes: 8 additions & 0 deletions src/tests/async/awaitingnotasync.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.IL">
<PropertyGroup>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>
78 changes: 78 additions & 0 deletions src/tests/async/collectible-alc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
using System.Threading.Tasks;
using Xunit;

public class Async2CollectibleAlc
{
[Fact]
public static void TestEntryPoint()
{
AsyncEntryPoint().Wait();
}

private static async2 Task AsyncEntryPoint()
{
WeakReference wr = await CallFooAsyncAndUnload();

for (int i = 0; i < 10 && wr.IsAlive; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}

Assert.False(wr.IsAlive);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static async2 Task<WeakReference> CallFooAsyncAndUnload()
{
TaskCompletionSource tcs = new();
(Task<string> task, WeakReference wr) = CallFooAsyncInCollectibleALC(tcs.Task);
for (int i = 0; i < 10; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}

Assert.True(wr.IsAlive);

tcs.SetResult();
string result = await task;
Assert.Equal("done", result);
return wr;
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static (Task<string>, WeakReference) CallFooAsyncInCollectibleALC(Task task)
{
CollectibleALC alc = new CollectibleALC();
Assembly asm = alc.LoadFromAssemblyPath(Assembly.GetExecutingAssembly().Location);

MethodInfo[] mis = asm.GetType(nameof(Async2CollectibleAlc)).GetMethods(BindingFlags.Static | BindingFlags.NonPublic);
MethodInfo mi = mis.Single(mi => mi.Name == "FooAsync" && mi.ReturnType == typeof(Task<string>));
Task<string> resultTask = (Task<string>)mi.Invoke(null, new object[] { new Task[] { task } });
alc.Unload();
return (resultTask, new WeakReference(alc, trackResurrection: true));
}

// Task[] to work around a compiler bug
private static async2 Task<string> FooAsync(Task[] t)
{
await t[0];
return "done";
}

private class CollectibleALC : AssemblyLoadContext
{
public CollectibleALC() : base(true)
{
}
}
}
10 changes: 10 additions & 0 deletions src/tests/async/collectible-alc.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.IL">
<PropertyGroup>
<!-- For collectible ALC -->
<RequiresProcessIsolation>True</RequiresProcessIsolation>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>
34 changes: 34 additions & 0 deletions src/tests/async/cse-array-index-byref.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Xunit;

public class CseArrayIndexByref
{
[Fact]
public static void TestEntryPoint()
{
int[] arr = new int[1];
AsyncTestEntryPoint(arr, 0).Wait();
Assert.Equal(199_990_000, arr[0]);
}

private static async Task AsyncTestEntryPoint(int[] arr, int index)
{
await HoistedByref(arr, index);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static async2 Task<int> HoistedByref(int[] arr, int index)
{
for (int i = 0; i < 20000; i++)
{
arr[index] += i;
await Task.Yield();
}
return 0;
}
}
8 changes: 8 additions & 0 deletions src/tests/async/cse-array-index-byref.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>
Loading
Loading