public void AbortWaitsUntilProtectedScopeEndsBeforeOccurring() { ThreadAbortScope scope = new ThreadAbortScope(); ManualResetEvent barrier = new ManualResetEvent(false); Tasks.StartThreadTask("Background Abort", delegate { barrier.WaitOne(); scope.Abort(); }); int count = 0; Assert.IsNotNull(scope.Run(delegate { count += 1; using (scope.Protect()) { count += 1; barrier.Set(); Thread.Sleep(5000); count += 1; } count += 1; // should not run })); Assert.AreEqual(3, count); Tasks.JoinAndVerify(TimeSpan.FromMilliseconds(100)); }
public void TryToAsynchronouslyHitARunningActionAtRandomTimes() { const int Iterations = 50; Random random = new Random(0); for (int i = 0; i < Iterations; i++) { ThreadAbortScope scope = new ThreadAbortScope(); Tasks.StartThreadTask("Background Abort", delegate { Thread.Sleep(random.Next(5)); scope.Abort(); }); Stopwatch timeout = Stopwatch.StartNew(); while (scope.Run(delegate { Thread.SpinWait(1000); }) == null) { if (timeout.ElapsedMilliseconds > 500) { Assert.Fail("The scope failed to stop the run during iteration {0}.", i); } } Tasks.JoinAndVerify(TimeSpan.FromMilliseconds(100)); } }
public void AbortFromADifferentThreadUnwindsGracefully() { ThreadAbortScope scope = new ThreadAbortScope(); ManualResetEvent barrier = new ManualResetEvent(false); Tasks.StartThreadTask("Background Abort", delegate { barrier.WaitOne(); scope.Abort(); }); int count = 0; Assert.IsNotNull(scope.Run(delegate { count += 1; barrier.Set(); Thread.Sleep(5000); count += 1; // should not run })); Assert.AreEqual(1, count); Tasks.JoinAndVerify(TimeSpan.FromMilliseconds(100)); }
public void AbortBeforeRunCausesImmediateAbortion() { ThreadAbortScope scope = new ThreadAbortScope(); int count = 0; scope.Abort(); Assert.IsNotNull(scope.Run(delegate { count += 1; })); Assert.AreEqual(0, count); }
public void AbortFromADifferentSourceUnwindsGracefully() { ThreadAbortScope outerScope = new ThreadAbortScope(); Assert.IsNotNull(outerScope.Run(delegate { ThreadAbortScope innerScope = new ThreadAbortScope(); innerScope.Run(delegate { outerScope.Abort(); }); })); }
public void ProtectOutsideOfScopeJustRunsTheAction() { ThreadAbortScope scope = new ThreadAbortScope(); bool ran = false; using (scope.Protect()) ran = true; Assert.IsTrue(ran, "Should have run the action."); }
public void RunCanBeCalledRepeatedly() { ThreadAbortScope scope = new ThreadAbortScope(); int count = 0; for (int i = 0; i < 3; i++) { Assert.IsNull(scope.Run(delegate { count += 1; })); } Assert.AreEqual(3, count); }
public void RunThrowsIfCalledReentrantlyOnSameThread() { ThreadAbortScope scope = new ThreadAbortScope(); scope.Run(delegate { Assert.Throws <InvalidOperationException>(delegate { scope.Run(delegate { }); }); }); }
public void AbortAfterRunCausesImmediateAbortionOfNextRun() { ThreadAbortScope scope = new ThreadAbortScope(); int count = 0; Assert.IsNull(scope.Run(delegate { count += 1; })); scope.Abort(); Assert.IsNotNull(scope.Run(delegate { count += 1; })); Assert.AreEqual(1, count); }
public void ProtectInAnotherThreadJustRunsTheAction() { ThreadAbortScope scope = new ThreadAbortScope(); bool ran = false; Tasks.StartThreadTask("Different thread", () => { using (scope.Protect()) ran = true; }); Tasks.JoinAndVerify(TimeSpan.FromMilliseconds(100)); Assert.IsTrue(ran, "Should have run the action."); }
public void AbortDuringRunOnSameThreadUnwindsGracefully() { ThreadAbortScope scope = new ThreadAbortScope(); int count = 0; Assert.IsNotNull(scope.Run(delegate { count += 1; scope.Abort(); count += 1; })); Assert.AreEqual(1, count); }
public void RunThrowsIfCalledReentrantlyOnDifferentThread() { ThreadAbortScope scope = new ThreadAbortScope(); scope.Run(delegate { Tasks.StartThreadTask("Reentrant Call to Scope.Run", () => { Assert.Throws <InvalidOperationException>(delegate { scope.Run(delegate { }); }); }); Tasks.JoinAndVerify(TimeSpan.FromMilliseconds(500)); }); }
public void AbortFromWithinProtectedScopeDoesNotOccurUntilTheProtectedScopeExits() { bool ranToCompletion = false; ThreadAbortScope scope = new ThreadAbortScope(); ThreadAbortException ex = scope.Run(() => { using (scope.Protect()) { scope.Abort(); ranToCompletion = true; } }); Assert.IsNotNull(ex, "Should have aborted."); Assert.IsTrue(ranToCompletion, "Should have run the action."); }
public void RunThrowsIfActionIsNull() { ThreadAbortScope scope = new ThreadAbortScope(); scope.Run(null); }
public IDisposable Protect() { ThreadAbortScope scope = FindActiveScopeForThread(Thread.CurrentThread); return(scope != null?scope.Protect() : null); }
public TestOutcome Run(MarkupDocumentWriter markupDocumentWriter, Action action, string description) { // NOTE: This method has been optimized to minimize the total stack depth of the action // by inlining blocks on the critical path that had previously been factored out. if (markupDocumentWriter == null) { throw new ArgumentNullException("markupDocumentWriter"); } if (action == null) { throw new ArgumentNullException("action"); } ThreadAbortScope scope = null; try { lock (syncRoot) { ThrowIfDisposed(); if (!abortOutcome.HasValue) { if (scopesAndThreads == null) { scopesAndThreads = new List <Pair <ThreadAbortScope, Thread> >(); } scope = new ThreadAbortScope(); scopesAndThreads.Add(new Pair <ThreadAbortScope, Thread>(scope, Thread.CurrentThread)); } } if (scope == null) { return(HandleAbort(markupDocumentWriter, description, null)); } // Run the action within the scope we have acquired. try { ThreadAbortException ex = scope.Run(action); if (ex != null) { return(HandleAbort(markupDocumentWriter, description, ex)); } return(TestOutcome.Passed); } catch (Exception ex) { // If the test itself threw a thread abort, not because we aborted it // ourselves but most likely due to a bug in the test subject, then we // prevent the abort from bubbling up any further. if (ex is ThreadAbortException && !AppDomain.CurrentDomain.IsFinalizingForUnload()) { Thread.ResetAbort(); } TestOutcome outcome; TestException testException = ex as TestException; if (testException != null) { outcome = testException.Outcome; if (testException.ExcludeStackTrace) { LogMessage(markupDocumentWriter, description, outcome, testException.HasNonDefaultMessage ? testException.Message : null, null); } else { LogMessage(markupDocumentWriter, description, outcome, null, testException); } } else { outcome = TestOutcome.Failed; LogMessage(markupDocumentWriter, description, outcome, null, ex); } return(outcome); } } finally { if (scope != null) { lock (syncRoot) { if (scopesAndThreads != null) { for (int i = 0; i < scopesAndThreads.Count; i++) { if (scopesAndThreads[i].First == scope) { scopesAndThreads.RemoveAt(i); } } } } } } }