/// <summary> /// Initializes a new instance of the <see cref="TimeoutCommand"/> class. /// </summary> /// <param name="innerCommand">The inner command</param> /// <param name="timeout">Timeout value</param> /// <param name="debugger">An <see cref="IDebugger" /> instance</param> 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", nameof(innerCommand)); Guard.ArgumentValid(timeout > 0, "Timeout value must be greater than zero", nameof(timeout)); Guard.ArgumentNotNull(debugger, nameof(debugger)); #if THREAD_ABORT BeforeTest = (context) => { var testThread = Thread.CurrentThread; var nativeThreadId = ThreadUtility.GetCurrentThreadNativeId(); // Create a timer to cancel the current thread _commandTimer = new Timer( (o) => { if (_debugger.IsAttached) { return; } _commandTimedOut = true; ThreadUtility.Abort(testThread, nativeThreadId); // No join here, since the thread doesn't really terminate }, null, timeout, Timeout.Infinite); }; AfterTest = (context) => { _commandTimer.Dispose(); // If the timer cancelled the current thread, change the result if (_commandTimedOut) { string message = $"Test exceeded Timeout value of {timeout}ms"; context.CurrentResult.SetResult( new ResultState(TestStatus.Failed, message), message); } }; #else BeforeTest = _ => { }; AfterTest = _ => { }; #endif }
/// <summary> /// Initializes a new instance of the <see cref="TimeoutCommand"/> class. /// </summary> /// <param name="innerCommand">The inner command</param> /// <param name="timeout">Timeout value</param> public TimeoutCommand(TestCommand innerCommand, int timeout) : base(innerCommand) { _timeout = timeout; Guard.ArgumentValid(innerCommand.Test is TestMethod, "TimeoutCommand may only apply to a TestMethod", nameof(innerCommand)); Guard.ArgumentValid(timeout > 0, "Timeout value must be greater than zero", nameof(timeout)); #if THREAD_ABORT BeforeTest = (context) => { var testThread = Thread.CurrentThread; var nativeThreadId = ThreadUtility.GetCurrentThreadNativeId(); // Create a timer to cancel the current thread _commandTimer = new Timer( (o) => { _commandTimedOut = true; ThreadUtility.Abort(testThread, nativeThreadId); // No join here, since the thread doesn't really terminate }, null, timeout, Timeout.Infinite); }; AfterTest = (context) => { _commandTimer.Dispose(); // If the timer cancelled the current thread, change the result if (_commandTimedOut) { context.CurrentResult.SetResult(ResultState.Failure, $"Test exceeded Timeout value of {timeout}ms"); } }; #else BeforeTest = _ => { }; AfterTest = _ => { }; #endif }