DelayedConstraint
Applies a delay to the match so that a match can be evaluated in the future.
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace NUnit.Framework.Constraints
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class DelayedConstraint : PrefixConstraint
{
[System.Runtime.CompilerServices.Nullable(0)]
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)
{
if (milliSeconds < 0)
throw new ArgumentException("Interval cannot be negative");
_parent.PollingInterval = new Interval(milliSeconds).InMilliseconds;
return new WithRawPollingInterval(_parent);
}
}
[System.Runtime.CompilerServices.Nullable(0)]
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)
{
if (milliSeconds < 0)
throw new ArgumentException("Interval cannot be negative");
_parent.PollingInterval = new Interval(milliSeconds).InMilliseconds;
return new WithRawPollingInterval(_parent);
}
}
[System.Runtime.CompilerServices.Nullable(0)]
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;
}
}
[System.Runtime.CompilerServices.Nullable(0)]
private class DelegatingConstraintResult : ConstraintResult
{
private readonly ConstraintResult _innerResult;
public DelegatingConstraintResult(IConstraint constraint, ConstraintResult innerResult)
: base(constraint, innerResult.ActualValue, innerResult.Status)
{
_innerResult = innerResult;
}
public override void WriteMessageTo(MessageWriter writer)
{
writer.WriteMessageLine(base.Description, Array.Empty<object>());
_innerResult.WriteMessageTo(writer);
}
}
protected Interval DelayInterval { get; set; }
protected Interval PollingInterval { get; set; }
public override string Description {
get {
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(12, 1);
defaultInterpolatedStringHandler.AppendLiteral("After ");
defaultInterpolatedStringHandler.AppendFormatted(DelayInterval);
defaultInterpolatedStringHandler.AppendLiteral(" delay");
return defaultInterpolatedStringHandler.ToStringAndClear();
}
}
public DelayedConstraint(IConstraint baseConstraint, int delayInMilliseconds)
: this(baseConstraint, delayInMilliseconds, 0)
{
}
public DelayedConstraint(IConstraint baseConstraint, int delayInMilliseconds, int pollingIntervalInMilliseconds)
: base(baseConstraint, string.Empty)
{
if (delayInMilliseconds < 0)
throw new ArgumentException("Cannot check a condition in the past", "delayInMilliseconds");
if (pollingIntervalInMilliseconds < 0)
throw new ArgumentException("Interval cannot be negative", "pollingIntervalInMilliseconds");
DelayInterval = new Interval(delayInMilliseconds).InMilliseconds;
PollingInterval = new Interval(pollingIntervalInMilliseconds).InMilliseconds;
}
private DelayedConstraint(IConstraint baseConstraint, Interval delayInterval, Interval pollingInterval)
: base(baseConstraint, string.Empty)
{
DelayInterval = delayInterval;
PollingInterval = pollingInterval;
}
public override ConstraintResult ApplyTo<[System.Runtime.CompilerServices.Nullable(2)] TActual>(TActual actual)
{
return PollLoop(() => base.BaseConstraint.ApplyTo<TActual>(actual));
}
public override ConstraintResult ApplyTo<[System.Runtime.CompilerServices.Nullable(2)] TActual>(ActualValueDelegate<TActual> del)
{
return PollLoop(() => base.BaseConstraint.ApplyTo<TActual>(del));
}
[AsyncStateMachine(typeof(<ApplyToAsync>d__18<>))]
public override Task<ConstraintResult> ApplyToAsync<[System.Runtime.CompilerServices.Nullable(2)] TActual>(Func<Task<TActual>> taskDel)
{
<ApplyToAsync>d__18<TActual> stateMachine = default(<ApplyToAsync>d__18<TActual>);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<ConstraintResult>.Create();
stateMachine.<>4__this = this;
stateMachine.taskDel = taskDel;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(<PollingDelayAsync>d__19))]
private Task<bool> PollingDelayAsync(Stopwatch stopwatch)
{
<PollingDelayAsync>d__19 stateMachine = default(<PollingDelayAsync>d__19);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<bool>.Create();
stateMachine.<>4__this = this;
stateMachine.stopwatch = stopwatch;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
private Task FinalDelayAsync(Stopwatch stopwatch)
{
TimeSpan timeSpan = DelayInterval.AsTimeSpan - stopwatch.Elapsed;
if (timeSpan > TimeSpan.Zero)
return Task.Delay(timeSpan);
return Task.CompletedTask;
}
private ConstraintResult PollLoop(Func<ConstraintResult> applyBaseConstraint)
{
Stopwatch stopwatch = Stopwatch.StartNew();
if (PollingInterval.IsNotZero) {
while (PollingDelay(stopwatch)) {
try {
ConstraintResult constraintResult = applyBaseConstraint();
if (constraintResult.IsSuccess)
return new DelegatingConstraintResult(this, constraintResult);
} catch (Exception) {
}
}
}
FinalDelay(stopwatch);
return new DelegatingConstraintResult(this, applyBaseConstraint());
}
private bool PollingDelay(Stopwatch stopwatch)
{
TimeSpan elapsed = stopwatch.Elapsed;
TimeSpan timeSpan = DelayInterval.AsTimeSpan - elapsed;
TimeSpan timeSpan2 = (timeSpan < PollingInterval.AsTimeSpan) ? timeSpan : PollingInterval.AsTimeSpan;
bool flag = timeSpan2 > TimeSpan.Zero;
if (flag) {
Thread.Sleep(timeSpan2);
TimeSpan timeSpan3 = elapsed + timeSpan2;
while ((elapsed = stopwatch.Elapsed) < timeSpan3) {
Thread.Sleep(timeSpan3 - elapsed);
}
}
return flag;
}
private void FinalDelay(Stopwatch stopwatch)
{
TimeSpan timeSpan = DelayInterval.AsTimeSpan - stopwatch.Elapsed;
if (timeSpan > TimeSpan.Zero)
Thread.Sleep(timeSpan);
}
protected override string GetStringRepresentation()
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(9, 2);
defaultInterpolatedStringHandler.AppendLiteral("<after ");
defaultInterpolatedStringHandler.AppendFormatted(DelayInterval.AsTimeSpan.TotalMilliseconds);
defaultInterpolatedStringHandler.AppendLiteral(" ");
defaultInterpolatedStringHandler.AppendFormatted(base.BaseConstraint);
defaultInterpolatedStringHandler.AppendLiteral(">");
return defaultInterpolatedStringHandler.ToStringAndClear();
}
}
}