[PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Passed_synchronization_context_is_used_for_post([Values] PostOverload overload)
        {
            using (SynchronizationContextAssert.ExpectSinglePost(postedAction => { }))
            {
                var contextToUse = SynchronizationContext.Current !;

                using (SynchronizationContextAssert.ExpectNoPost())
                {
                    switch (overload)
                    {
                    case PostOverload.Action:
                        AmbientTasks.Post(contextToUse, () => { });
                        break;

                    case PostOverload.SendOrPostCallback:
                        AmbientTasks.Post(contextToUse, state => { }, state: null);
                        break;

                    case PostOverload.AsyncAction:
                        AmbientTasks.Post(contextToUse, () => Task.CompletedTask);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                }
            }
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_does_not_complete_until_async_task_added_by_user_delegate_completes([Values] PostOverload overload)
        {
            var source       = new TaskCompletionSource <object?>();
            var postedAction = (Action?)null;

            using (SynchronizationContextAssert.ExpectSinglePost(p => postedAction = p))
            {
                AmbientTasksPost(overload, () =>
                {
                    AmbientTasks.Add(source.Task);
                });
            }

            var waitAllTask = AmbientTasks.WaitAllAsync();

            waitAllTask.IsCompleted.ShouldBeFalse();

            postedAction.ShouldNotBeNull();
            postedAction !.Invoke();

            waitAllTask.IsCompleted.ShouldBeFalse();

            source.SetResult(null);

            waitAllTask.Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Subsequent_invocations_by_SynchronizationContext_are_ignored_when_user_code_throws([Values] PostOverload overload)
        {
            var postedAction = (Action?)null;
            var callCount    = 0;

            using (SynchronizationContextAssert.ExpectSinglePost(p =>
            {
                postedAction = p;
            }))
            {
                AmbientTasksPost(overload, () =>
                {
                    callCount++;
                    throw new Exception();
                });
            }

            callCount.ShouldBe(0);
            Should.Throw <Exception>(postedAction);
            callCount.ShouldBe(1);

            postedAction.ShouldNotBeNull();
            postedAction !.Invoke();

            callCount.ShouldBe(1);
        }
예제 #4
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_should_fault_after_adding_synchronously_failed_task_with_no_context_when_on_SynchronizationContext()
        {
            using (SynchronizationContextAssert.ExpectSinglePost(postedAction => { }))
            {
                AmbientTasks.Add(Task.FromException(new Exception()));

                AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.Faulted);
            }
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Exception_from_user_delegate_is_not_thrown_on_SynchronizationContext_when_there_is_a_BeginContext_handler([Values] PostOverload overload)
        {
            AmbientTasks.BeginContext(ex => { });

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction => postedAction.Invoke()))
            {
                AmbientTasksPost(overload, () => throw new Exception());
            }
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Exception_from_user_delegate_is_not_in_task_from_next_call_to_WaitAllAsync_when_there_is_a_BeginContext_handler([Values] PostOverload overload)
        {
            AmbientTasks.BeginContext(ex => { });

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction => postedAction.Invoke()))
            {
                AmbientTasksPost(overload, () => throw new Exception());
            }

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Exception_from_user_delegate_is_thrown_on_SynchronizationContext_when_there_is_no_BeginContext_handler([Values] PostOverload overload)
        {
            var exception = new Exception();

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction =>
            {
                Should.Throw <Exception>(postedAction).ShouldBeSameAs(exception);
            }))
            {
                AmbientTasksPost(overload, () => throw exception);
            }
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Exception_from_SynchronizationContext_post_after_invoking_delegate_is_not_handled_when_there_is_no_BeginContext_handler([Values] PostOverload overload)
        {
            var exception = new Exception();

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction =>
            {
                postedAction.Invoke();
                throw exception;
            }))
            {
                Should.Throw <Exception>(() => AmbientTasksPost(overload, () => { })).ShouldBeSameAs(exception);
            }
        }
예제 #9
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void BeginContext_handler_is_not_executed_using_synchronization_context()
        {
            using (SynchronizationContextAssert.ExpectNoPost())
            {
                AmbientTasks.BeginContext(ex => { });

                AmbientTasks.Add(Task.FromException(new Exception()));

                using (Utils.WithTemporarySynchronizationContext(null))
                {
                    AmbientTasks.Add(Task.FromException(new Exception()));
                }
            }
        }
예제 #10
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Adding_synchronously_faulted_task_with_no_context_throws_AggregateException_on_current_SynchronizationContext()
        {
            var exception = new Exception();

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction =>
            {
                var aggregateException = Should.Throw <AggregateException>(postedAction);

                aggregateException.InnerExceptions.ShouldBe(new[] { exception });
            }))
            {
                AmbientTasks.Add(Task.FromException(exception));
            }
        }
예제 #11
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Exception_from_user_delegate_is_in_task_from_next_call_to_WaitAllAsync_when_there_is_no_BeginContext_handler([Values] PostOverload overload)
        {
            var exception = new Exception();

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction => postedAction.Invoke()))
            {
                Should.Throw <Exception>(() => AmbientTasksPost(overload, () => throw exception));
            }

            var waitAllTask = AmbientTasks.WaitAllAsync();

            waitAllTask.Status.ShouldBe(TaskStatus.Faulted);

            var aggregateException = waitAllTask.Exception !.InnerExceptions.ShouldHaveSingleItem().ShouldBeOfType <AggregateException>();

            aggregateException.InnerExceptions.ShouldHaveSingleItem().ShouldBeSameAs(exception);
        }
예제 #12
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Exception_from_user_delegate_is_handled_by_BeginContext_handler([Values] PostOverload overload)
        {
            var exception = new Exception();
            var watcher   = new CallbackWatcher();

            AmbientTasks.BeginContext(ex =>
            {
                watcher.OnCallback();
                ex.ShouldBeSameAs(exception);
            });

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction => postedAction.Invoke()))
            {
                using (watcher.ExpectCallback())
                    AmbientTasksPost(overload, () => throw exception);
            }
        }
예제 #13
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_waits_for_SynchronizationContext_Post_to_invoke_delegate_before_completing([Values] PostOverload overload)
        {
            var postedAction = (Action?)null;

            using (SynchronizationContextAssert.ExpectSinglePost(p => postedAction = p))
            {
                AmbientTasksPost(overload, () => { });
            }

            var waitAllTask = AmbientTasks.WaitAllAsync();

            waitAllTask.IsCompleted.ShouldBeFalse();

            postedAction.ShouldNotBeNull();
            postedAction !.Invoke();

            waitAllTask.Status.ShouldBe(TaskStatus.RanToCompletion);
            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
예제 #14
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Delegate_is_abandoned_if_SynchronizationContext_post_throws_before_invoking_delegate([Values] PostOverload overload)
        {
            var postedAction = (Action?)null;

            using (SynchronizationContextAssert.ExpectSinglePost(p =>
            {
                postedAction = p;
                throw new Exception();
            }))
            {
                Should.Throw <Exception>(() => AmbientTasksPost(overload, () => Assert.Fail("The delegate should be abandoned.")));
            }

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);

            postedAction.ShouldNotBeNull();
            postedAction !.Invoke();

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
예제 #15
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Subsequent_invocations_by_SynchronizationContext_are_ignored_when_successful([Values] PostOverload overload)
        {
            var postedAction = (Action?)null;
            var callCount    = 0;

            using (SynchronizationContextAssert.ExpectSinglePost(p =>
            {
                postedAction = p;
            }))
            {
                AmbientTasksPost(overload, () => callCount++);
            }

            callCount.ShouldBe(0);
            postedAction.ShouldNotBeNull();
            postedAction !.Invoke();
            callCount.ShouldBe(1);

            postedAction.Invoke();

            callCount.ShouldBe(1);
        }
예제 #16
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Adding_synchronously_faulted_task_with_multiple_exceptions_and_no_context_throws_AggregateException_on_current_SynchronizationContexts()
        {
            var exceptions = new[]
            {
                new Exception(),
                new Exception()
            };

            var source = new TaskCompletionSource <object?>();

            source.SetException(exceptions);

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction =>
            {
                var aggregateException = Should.Throw <AggregateException>(postedAction);

                aggregateException.InnerExceptions.ShouldBe(exceptions);
            }))
            {
                AmbientTasks.Add(source.Task);
            }
        }
예제 #17
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_waits_for_added_task_with_no_context_and_throws_exception_on_current_SynchronizationContext()
        {
            var source    = new TaskCompletionSource <object?>();
            var exception = new Exception();

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction =>
            {
                var aggregateException = Should.Throw <AggregateException>(postedAction);

                aggregateException.InnerExceptions.ShouldBe(new[] { exception });
            }))
            {
                AmbientTasks.Add(source.Task);

                var waitAllTask = AmbientTasks.WaitAllAsync();
                waitAllTask.IsCompleted.ShouldBeFalse();

                source.SetException(exception);

                waitAllTask.Status.ShouldBe(TaskStatus.Faulted);
            }
        }