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.Runtime.CompilerServices;
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 WriteActualValueTo(MessageWriter writer)
            {
                _innerResult.WriteActualValueTo(writer);
            }
            public override void WriteAdditionalLinesTo(MessageWriter writer)
            {
                _innerResult.WriteAdditionalLinesTo(writer);
            }
        }
        protected Interval DelayInterval { get; set; }
        protected Interval PollingInterval { get; set; }
        public override string Description {
            get {
                DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 2);
                defaultInterpolatedStringHandler.AppendFormatted(base.BaseConstraint.Description);
                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)
        {
            long timestamp = Stopwatch.GetTimestamp();
            long num = TimestampOffset(timestamp, DelayInterval.AsTimeSpan);
            TimeSpan timeSpan;
            if (PollingInterval.IsNotZero) {
                while ((timestamp = Stopwatch.GetTimestamp()) < num) {
                    long num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
                    timeSpan = TimestampDiff((num < num2) ? num : num2, timestamp);
                    ThreadUtility.BlockingDelay((int)timeSpan.TotalMilliseconds);
                    ConstraintResult constraintResult = base.BaseConstraint.ApplyTo(actual);
                    if (constraintResult.IsSuccess)
                        return new DelegatingConstraintResult(this, constraintResult);
                }
            }
            if ((timestamp = Stopwatch.GetTimestamp()) < num) {
                timeSpan = TimestampDiff(num, timestamp);
                ThreadUtility.BlockingDelay((int)timeSpan.TotalMilliseconds);
            }
            return new DelegatingConstraintResult(this, base.BaseConstraint.ApplyTo(actual));
        }
        public override ConstraintResult ApplyTo<[System.Runtime.CompilerServices.Nullable(2)] TActual>(ActualValueDelegate<TActual> del)
        {
            long timestamp = Stopwatch.GetTimestamp();
            long num = TimestampOffset(timestamp, DelayInterval.AsTimeSpan);
            TimeSpan timeSpan;
            object actual;
            if (PollingInterval.IsNotZero) {
                long num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
                while ((timestamp = Stopwatch.GetTimestamp()) < num) {
                    if (num2 > timestamp) {
                        timeSpan = TimestampDiff((num < num2) ? num : num2, timestamp);
                        ThreadUtility.BlockingDelay((int)timeSpan.TotalMilliseconds);
                    }
                    num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
                    actual = InvokeDelegate(del);
                    try {
                        ConstraintResult constraintResult = base.BaseConstraint.ApplyTo(actual);
                        if (constraintResult.IsSuccess)
                            return new DelegatingConstraintResult(this, constraintResult);
                    } catch (Exception) {
                    }
                }
            }
            if ((timestamp = Stopwatch.GetTimestamp()) < num) {
                timeSpan = TimestampDiff(num, timestamp);
                ThreadUtility.BlockingDelay((int)timeSpan.TotalMilliseconds);
            }
            actual = InvokeDelegate(del);
            return new DelegatingConstraintResult(this, base.BaseConstraint.ApplyTo(actual));
        }
        public override ConstraintResult ApplyTo<[System.Runtime.CompilerServices.Nullable(2)] 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);
                        ThreadUtility.BlockingDelay((int)timeSpan.TotalMilliseconds);
                    }
                    num2 = TimestampOffset(timestamp, PollingInterval.AsTimeSpan);
                    try {
                        ConstraintResult constraintResult = base.BaseConstraint.ApplyTo(actual);
                        if (constraintResult.IsSuccess)
                            return new DelegatingConstraintResult(this, constraintResult);
                    } catch (Exception) {
                    }
                }
            }
            if ((timestamp = Stopwatch.GetTimestamp()) < num) {
                timeSpan = TimestampDiff(num, timestamp);
                ThreadUtility.BlockingDelay((int)timeSpan.TotalMilliseconds);
            }
            return new DelegatingConstraintResult(this, base.BaseConstraint.ApplyTo(actual));
        }
        [System.Runtime.CompilerServices.NullableContext(2)]
        private static object InvokeDelegate<T>([System.Runtime.CompilerServices.Nullable(1)] ActualValueDelegate<T> del)
        {
            if (AsyncToSyncAdapter.IsAsyncOperation(del))
                return AsyncToSyncAdapter.Await(() => del());
            return del();
        }
        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();
        }
        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);
        }
    }
}