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
{
public class WithRawDelayInterval : DelayedConstraint
{
private readonly DelayedConstraint _parent;
public WithDimensionedDelayInterval Minutes {
get {
_parent.DelayInterval = _parent.DelayInterval.InMinutes;
return new WithDimensionedDelayInterval(_parent);
}
}
public WithDimensionedDelayInterval Seconds {
get {
base.DelayInterval = base.DelayInterval.InSeconds;
return new WithDimensionedDelayInterval(_parent);
}
}
public WithDimensionedDelayInterval MilliSeconds {
get {
base.DelayInterval = base.DelayInterval.InMilliseconds;
return new WithDimensionedDelayInterval(_parent);
}
}
public WithRawDelayInterval(DelayedConstraint parent)
: base(parent.BaseConstraint, parent.DelayInterval, parent.PollingInterval)
{
base.DelayInterval = parent.DelayInterval;
_parent = parent;
}
public WithRawPollingInterval PollEvery(int milliSeconds)
{
_parent.PollingInterval = new Interval(milliSeconds).InMilliseconds;
return new WithRawPollingInterval(_parent);
}
}
public class WithDimensionedDelayInterval : DelayedConstraint
{
private readonly DelayedConstraint _parent;
public WithDimensionedDelayInterval(DelayedConstraint parent)
: base(parent.BaseConstraint, parent.DelayInterval, parent.PollingInterval)
{
base.DelayInterval = parent.DelayInterval;
_parent = parent;
}
public WithRawPollingInterval PollEvery(int milliSeconds)
{
_parent.PollingInterval = new Interval(milliSeconds).InMilliseconds;
return new WithRawPollingInterval(_parent);
}
}
public class WithRawPollingInterval : DelayedConstraint
{
private readonly DelayedConstraint _parent;
public DelayedConstraint Minutes {
get {
_parent.PollingInterval = _parent.PollingInterval.InMinutes;
return _parent;
}
}
public DelayedConstraint Seconds {
get {
_parent.PollingInterval = _parent.PollingInterval.InSeconds;
return _parent;
}
}
public DelayedConstraint MilliSeconds {
get {
_parent.PollingInterval = _parent.PollingInterval.InMilliseconds;
return _parent;
}
}
public WithRawPollingInterval(DelayedConstraint parent)
: base(parent.BaseConstraint, parent.DelayInterval, parent.PollingInterval)
{
_parent = parent;
}
}
protected Interval DelayInterval { get; set; }
protected Interval PollingInterval { get; set; }
public override string Description => $"{base.BaseConstraint.Description}""{DelayInterval}""";
public DelayedConstraint(IConstraint baseConstraint, int delayInMilliseconds)
: this(baseConstraint, delayInMilliseconds, 0)
{
}
public DelayedConstraint(IConstraint baseConstraint, int delayInMilliseconds, int pollingIntervalInMilliseconds)
: base(baseConstraint)
{
if (delayInMilliseconds < 0)
throw new ArgumentException("Cannot check a condition in the past", "delayInMilliseconds");
DelayInterval = new Interval(delayInMilliseconds).InMilliseconds;
PollingInterval = new Interval(pollingIntervalInMilliseconds).InMilliseconds;
}
private DelayedConstraint(IConstraint baseConstraint, Interval delayInterval, Interval pollingInterval)
: base(baseConstraint)
{
DelayInterval = delayInterval;
PollingInterval = pollingInterval;
}
public override ConstraintResult ApplyTo<TActual>(TActual actual)
{
long timestamp = Stopwatch.GetTimestamp();
long num = TimestampOffset(timestamp, DelayInterval.AsTimeSpan);
TimeSpan timeSpan;
if (PollingInterval.IsNotZero) {
long num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
while ((timestamp = Stopwatch.GetTimestamp()) < num) {
if (num2 > timestamp) {
timeSpan = TimestampDiff((num < num2) ? num : num2, timestamp);
Thread.Sleep((int)timeSpan.TotalMilliseconds);
}
num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
if (base.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, base.BaseConstraint.ApplyTo(actual).IsSuccess);
}
public override ConstraintResult ApplyTo<TActual>(ActualValueDelegate<TActual> del)
{
long timestamp = Stopwatch.GetTimestamp();
long num = TimestampOffset(timestamp, DelayInterval.AsTimeSpan);
TimeSpan timeSpan;
object obj;
if (PollingInterval.IsNotZero) {
long num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
while ((timestamp = Stopwatch.GetTimestamp()) < num) {
if (num2 > timestamp) {
timeSpan = TimestampDiff((num < num2) ? num : num2, timestamp);
Thread.Sleep((int)timeSpan.TotalMilliseconds);
}
num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
obj = InvokeDelegate(del);
try {
if (base.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, base.BaseConstraint.ApplyTo(obj).IsSuccess);
}
public override ConstraintResult ApplyTo<TActual>(ref TActual actual)
{
long timestamp = Stopwatch.GetTimestamp();
long num = TimestampOffset(timestamp, DelayInterval.AsTimeSpan);
TimeSpan timeSpan;
if (PollingInterval.IsNotZero) {
long num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
while ((timestamp = Stopwatch.GetTimestamp()) < num) {
if (num2 > timestamp) {
timeSpan = TimestampDiff((num < num2) ? num : num2, timestamp);
Thread.Sleep((int)timeSpan.TotalMilliseconds);
}
num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
try {
if (base.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, base.BaseConstraint.ApplyTo(actual).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();
}
protected override string GetStringRepresentation()
{
return $"""{DelayInterval.AsTimeSpan.TotalMilliseconds}""{base.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);
}
}
}