TimeoutCommand
TimeoutCommand creates a timer in order to cancel
a test if it exceeds a specified time and adjusts
the test result if it did time out.
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal.Abstractions;
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace NUnit.Framework.Internal.Commands
{
[NullableContext(1)]
[Nullable(0)]
public class TimeoutCommand : BeforeAndAfterTestCommand
{
private readonly int _timeout;
private readonly IDebugger _debugger;
internal TimeoutCommand(TestCommand innerCommand, int timeout, IDebugger debugger)
: base(innerCommand)
{
_timeout = timeout;
_debugger = debugger;
Guard.ArgumentValid(innerCommand.Test is TestMethod, "TimeoutCommand may only apply to a TestMethod", "innerCommand");
Guard.ArgumentValid(timeout > 0, "Timeout value must be greater than zero", "timeout");
Guard.ArgumentNotNull(debugger, "debugger");
BeforeTest = delegate {
};
AfterTest = delegate {
};
}
public override TestResult Execute(TestExecutionContext context)
{
try {
using (new TestExecutionContext.IsolatedContext()) {
Task<TestResult> task = Task.Run(() => innerCommand.Execute(TestExecutionContext.CurrentContext));
if (Task.WaitAny(new Task[1] {
task
}, _timeout) == -1 && !_debugger.IsAttached) {
TestResult currentResult = context.CurrentResult;
ResultState failure = ResultState.Failure;
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(33, 1);
defaultInterpolatedStringHandler.AppendLiteral("Test exceeded Timeout value of ");
defaultInterpolatedStringHandler.AppendFormatted(_timeout);
defaultInterpolatedStringHandler.AppendLiteral("ms");
currentResult.SetResult(failure, defaultInterpolatedStringHandler.ToStringAndClear());
} else
context.CurrentResult = task.GetAwaiter().GetResult();
}
} catch (Exception ex) {
context.CurrentResult.RecordException(ex, FailureSite.Test);
}
return context.CurrentResult;
}
}
}