DelayedConstraint
Applies a delay to the match so that a match can be evaluated in the future.
using NUnit.Framework.Internal;
using System;
using System.Diagnostics;
using System.Threading;
namespace NUnit.Framework.Constraints
{
public class DelayedConstraint : PrefixConstraint
{
private readonly int delayInMilliseconds;
private readonly int pollingInterval;
public override string Description => $"{baseConstraint.Description}""{delayInMilliseconds}""";
public DelayedConstraint(IConstraint baseConstraint, int delayInMilliseconds)
: this(baseConstraint, delayInMilliseconds, 0)
{
}
public DelayedConstraint(IConstraint baseConstraint, int delayInMilliseconds, int pollingInterval)
: base(baseConstraint)
{
if (delayInMilliseconds < 0)
throw new ArgumentException("Cannot check a condition in the past", "delayInMilliseconds");
this.delayInMilliseconds = delayInMilliseconds;
this.pollingInterval = pollingInterval;
}
public override ConstraintResult ApplyTo<TActual>(TActual actual)
{
long timestamp = Stopwatch.GetTimestamp();
long num = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)delayInMilliseconds));
TimeSpan timeSpan;
if (pollingInterval > 0) {
long num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
while ((timestamp = Stopwatch.GetTimestamp()) < num) {
if (num2 > timestamp) {
timeSpan = TimestampDiff((num < num2) ? num : num2, timestamp);
Thread.Sleep((int)timeSpan.TotalMilliseconds);
}
num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
if (baseConstraint.ApplyTo(actual).IsSuccess)
return new ConstraintResult(this, actual, true);
}
}
if ((timestamp = Stopwatch.GetTimestamp()) < num) {
timeSpan = TimestampDiff(num, timestamp);
Thread.Sleep((int)timeSpan.TotalMilliseconds);
}
return new ConstraintResult(this, actual, baseConstraint.ApplyTo(actual).IsSuccess);
}
public override ConstraintResult ApplyTo<TActual>(ActualValueDelegate<TActual> del)
{
long timestamp = Stopwatch.GetTimestamp();
long num = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)delayInMilliseconds));
TimeSpan timeSpan;
object obj;
if (pollingInterval > 0) {
long num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
while ((timestamp = Stopwatch.GetTimestamp()) < num) {
if (num2 > timestamp) {
timeSpan = TimestampDiff((num < num2) ? num : num2, timestamp);
Thread.Sleep((int)timeSpan.TotalMilliseconds);
}
num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
obj = InvokeDelegate(del);
try {
if (baseConstraint.ApplyTo(obj).IsSuccess)
return new ConstraintResult(this, obj, true);
} catch (Exception) {
}
}
}
if ((timestamp = Stopwatch.GetTimestamp()) < num) {
timeSpan = TimestampDiff(num, timestamp);
Thread.Sleep((int)timeSpan.TotalMilliseconds);
}
obj = InvokeDelegate(del);
return new ConstraintResult(this, obj, baseConstraint.ApplyTo(obj).IsSuccess);
}
private static object InvokeDelegate<T>(ActualValueDelegate<T> del)
{
if (AsyncInvocationRegion.IsAsyncOperation(del)) {
using (AsyncInvocationRegion asyncInvocationRegion = AsyncInvocationRegion.Create(del)) {
return asyncInvocationRegion.WaitForPendingOperationsToComplete(del());
}
}
return del();
}
public override ConstraintResult ApplyTo<TActual>(ref TActual actual)
{
long timestamp = Stopwatch.GetTimestamp();
long num = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)delayInMilliseconds));
TimeSpan timeSpan;
if (pollingInterval > 0) {
long num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
while ((timestamp = Stopwatch.GetTimestamp()) < num) {
if (num2 > timestamp) {
timeSpan = TimestampDiff((num < num2) ? num : num2, timestamp);
Thread.Sleep((int)timeSpan.TotalMilliseconds);
}
num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
try {
if (baseConstraint.ApplyTo(actual).IsSuccess)
return new ConstraintResult(this, actual, true);
} catch (Exception) {
}
}
}
if ((timestamp = Stopwatch.GetTimestamp()) < num) {
timeSpan = TimestampDiff(num, timestamp);
Thread.Sleep((int)timeSpan.TotalMilliseconds);
}
return new ConstraintResult(this, actual, baseConstraint.ApplyTo(actual).IsSuccess);
}
protected override string GetStringRepresentation()
{
return $"""{delayInMilliseconds}""{baseConstraint}""";
}
private static long TimestampOffset(long timestamp, TimeSpan offset)
{
return timestamp + (long)(offset.TotalSeconds * (double)Stopwatch.Frequency);
}
private static TimeSpan TimestampDiff(long timestamp1, long timestamp2)
{
return TimeSpan.FromSeconds((double)(timestamp1 - timestamp2) / (double)Stopwatch.Frequency);
}
}
}