81 lines
2.9 KiB
C#
81 lines
2.9 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
|
{
|
|
// Possibly useful as a general-purpose async testing helper?
|
|
public class SyncPoint
|
|
{
|
|
private readonly TaskCompletionSource<object> _atSyncPoint = new TaskCompletionSource<object>();
|
|
private readonly TaskCompletionSource<object> _continueFromSyncPoint = new TaskCompletionSource<object>();
|
|
|
|
/// <summary>
|
|
/// Waits for the code-under-test to reach <see cref="WaitToContinue"/>.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Task WaitForSyncPoint() => _atSyncPoint.Task;
|
|
|
|
/// <summary>
|
|
/// Releases the code-under-test to continue past where it waited for <see cref="WaitToContinue"/>.
|
|
/// </summary>
|
|
public void Continue() => _continueFromSyncPoint.TrySetResult(null);
|
|
|
|
/// <summary>
|
|
/// Used by the code-under-test to wait for the test code to sync up.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This code will unblock <see cref="WaitForSyncPoint"/> and then block waiting for <see cref="Continue"/> to be called.
|
|
/// </remarks>
|
|
/// <returns></returns>
|
|
public Task WaitToContinue()
|
|
{
|
|
_atSyncPoint.TrySetResult(null);
|
|
return _continueFromSyncPoint.Task;
|
|
}
|
|
|
|
public static Func<Task> Create(out SyncPoint syncPoint)
|
|
{
|
|
var handler = Create(1, out var syncPoints);
|
|
syncPoint = syncPoints[0];
|
|
return handler;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a re-entrant function that waits for sync points in sequence.
|
|
/// </summary>
|
|
/// <param name="count">The number of sync points to expect</param>
|
|
/// <param name="syncPoints">The <see cref="SyncPoint"/> objects that can be used to coordinate the sync point</param>
|
|
/// <returns></returns>
|
|
public static Func<Task> Create(int count, out SyncPoint[] syncPoints)
|
|
{
|
|
// Need to use a local so the closure can capture it. You can't use out vars in a closure.
|
|
var localSyncPoints = new SyncPoint[count];
|
|
for (var i = 0; i < count; i += 1)
|
|
{
|
|
localSyncPoints[i] = new SyncPoint();
|
|
}
|
|
|
|
syncPoints = localSyncPoints;
|
|
|
|
var counter = 0;
|
|
return () =>
|
|
{
|
|
if (counter >= localSyncPoints.Length)
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
else
|
|
{
|
|
var syncPoint = localSyncPoints[counter];
|
|
|
|
counter += 1;
|
|
return syncPoint.WaitToContinue();
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|