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);
        }
Example #10
0
        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.");
        }
Example #11
0
        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);
        }
Example #12
0
        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));
            });
        }
Example #13
0
        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.");
        }
Example #14
0
        public void RunThrowsIfActionIsNull()
        {
            ThreadAbortScope scope = new ThreadAbortScope();

            scope.Run(null);
        }
Example #15
0
        public IDisposable Protect()
        {
            ThreadAbortScope scope = FindActiveScopeForThread(Thread.CurrentThread);

            return(scope != null?scope.Protect() : null);
        }
Example #16
0
        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);
                                }
                            }
                        }
                    }
                }
            }
        }