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));
if (pollingInterval > 0) {
long num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
while ((timestamp = Stopwatch.GetTimestamp()) < num) {
if (num2 > timestamp)
Thread.Sleep((int)TimestampDiff((num < num2) ? num : num2, timestamp).TotalMilliseconds);
num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
ConstraintResult constraintResult = baseConstraint.ApplyTo(actual);
if (constraintResult.IsSuccess)
return new ConstraintResult(this, actual, true);
}
}
if ((timestamp = Stopwatch.GetTimestamp()) < num)
Thread.Sleep((int)TimestampDiff(num, timestamp).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));
object obj;
if (pollingInterval > 0) {
long num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
while ((timestamp = Stopwatch.GetTimestamp()) < num) {
if (num2 > timestamp)
Thread.Sleep((int)TimestampDiff((num < num2) ? num : num2, timestamp).TotalMilliseconds);
num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
obj = InvokeDelegate(del);
try {
ConstraintResult constraintResult = baseConstraint.ApplyTo(obj);
if (constraintResult.IsSuccess)
return new ConstraintResult(this, obj, true);
} catch (Exception) {
}
}
}
if ((timestamp = Stopwatch.GetTimestamp()) < num)
Thread.Sleep((int)TimestampDiff(num, timestamp).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));
if (pollingInterval > 0) {
long num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
while ((timestamp = Stopwatch.GetTimestamp()) < num) {
if (num2 > timestamp)
Thread.Sleep((int)TimestampDiff((num < num2) ? num : num2, timestamp).TotalMilliseconds);
num2 = TimestampOffset(timestamp, TimeSpan.FromMilliseconds((double)pollingInterval));
try {
ConstraintResult constraintResult = baseConstraint.ApplyTo(actual);
if (constraintResult.IsSuccess)
return new ConstraintResult(this, actual, true);
} catch (Exception) {
}
}
}
if ((timestamp = Stopwatch.GetTimestamp()) < num)
Thread.Sleep((int)TimestampDiff(num, timestamp).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);
}
}
}