CancelAfterCommand
CancelAfterCommand 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.Internal.Abstractions;
using System;
using System.Runtime.CompilerServices;
using System.Threading;
namespace NUnit.Framework.Internal.Commands
{
[NullableContext(1)]
[Nullable(0)]
public class CancelAfterCommand : DelegatingTestCommand
{
private readonly int _timeout;
private readonly IDebugger _debugger;
internal CancelAfterCommand(TestCommand innerCommand, int timeout, IDebugger debugger)
: base(innerCommand)
{
_timeout = timeout;
_debugger = debugger;
Guard.ArgumentValid(innerCommand.Test is TestMethod, "CancelAfterCommand may only apply to a TestMethod", "innerCommand");
Guard.ArgumentValid(timeout > 0, "Timeout value must be greater than zero", "timeout");
Guard.ArgumentNotNull(debugger, "debugger");
}
public override TestResult Execute(TestExecutionContext context)
{
CancellationTokenSource testCancellationTokenSource = new CancellationTokenSource();
try {
using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(_timeout)) {
cancellationTokenSource.Token.Register(delegate {
if (!_debugger.IsAttached)
testCancellationTokenSource.Cancel();
});
context.CancellationToken = testCancellationTokenSource.Token;
try {
innerCommand.Execute(context);
} catch (OperationCanceledException ex) {
context.CurrentResult.RecordException(ex);
} finally {
context.CancellationToken = CancellationToken.None;
}
return context.CurrentResult;
}
} finally {
if (testCancellationTokenSource != null)
((IDisposable)testCancellationTokenSource).Dispose();
}
}
}
}