[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 Handler_should_be_called_one_additional_time_to_handle_its_own_exception()
        {
            var taskException    = new Exception();
            var handlerException = new Exception();
            var watcher          = new CallbackWatcher();

            AmbientTasks.BeginContext(ex =>
            {
                watcher.OnCallback(out var callCount);

                if (callCount == 1)
                {
                    throw handlerException;
                }

                ex.ShouldBe(handlerException);
            });

            using (watcher.ExpectCallback(count: 2))
                AmbientTasks.Add(Task.FromException(taskException));

            var waitAllTask = AmbientTasks.WaitAllAsync();

            waitAllTask.Status.ShouldBe(TaskStatus.Faulted);

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

            aggregateException.InnerExceptions.ShouldHaveSingleItem().ShouldBeSameAs(taskException);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_should_fault_after_adding_synchronously_failed_task_with_no_context()
        {
            Should.Throw <AggregateException>(
                () => 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 WaitAllAsync_does_not_reset_until_all_tasks_have_completed()
        {
            var source1 = new TaskCompletionSource <object?>();
            var source2 = new TaskCompletionSource <object?>();

            AmbientTasks.Add(source1.Task);
            var waitTaskSeenAfterFirstAdd = AmbientTasks.WaitAllAsync();

            waitTaskSeenAfterFirstAdd.IsCompleted.ShouldBeFalse();

            // Should not reset on next call
            AmbientTasks.WaitAllAsync().ShouldBeSameAs(waitTaskSeenAfterFirstAdd);

            AmbientTasks.Add(source2.Task);
            AmbientTasks.WaitAllAsync().ShouldBeSameAs(waitTaskSeenAfterFirstAdd);

            // Should not reset on next call
            AmbientTasks.WaitAllAsync().ShouldBeSameAs(waitTaskSeenAfterFirstAdd);

            source1.SetResult(null);
            AmbientTasks.WaitAllAsync().ShouldBeSameAs(waitTaskSeenAfterFirstAdd);

            // Should not reset on next call
            AmbientTasks.WaitAllAsync().ShouldBeSameAs(waitTaskSeenAfterFirstAdd);

            source2.SetResult(null);
            waitTaskSeenAfterFirstAdd.Status.ShouldBe(TaskStatus.RanToCompletion);
            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Handled_exceptions_do_not_appear_in_a_subsequent_call_to_WaitAllAsync()
        {
            AmbientTasks.BeginContext(handler => { });

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

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_should_reset_after_fault_is_displayed_in_previously_returned_task()
        {
            Should.Throw <AggregateException>(
                () => AmbientTasks.Add(Task.FromException(new Exception())));

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.Faulted);
            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [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);
            }
        }
Beispiel #8
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Func_returning_synchronously_canceled_task_is_noop()
        {
            var source = new TaskCompletionSource <object?>();

            source.SetCanceled();
            AmbientTasks.Add(() => source.Task);

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [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 SynchronizationContext_that_throws_on_post_does_not_prevent_WaitAllAsync_completion()
        {
            var source = new TaskCompletionSource <object?>();

            using (SynchronizationContextAssert.ExpectSinglePost(postedAction => throw new Exception()))
            {
                AmbientTasks.Add(source.Task);

                var waitAllTask = AmbientTasks.WaitAllAsync();
                source.SetException(new Exception());
                waitAllTask.Status.ShouldBe(TaskStatus.Faulted);
            }
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void BeginContext_handler_can_be_removed()
        {
            AmbientTasks.BeginContext(ex => Assert.Fail("This handler should not be called."));

            AmbientTasks.BeginContext();

            var exception          = new Exception();
            var aggregateException = Should.Throw <AggregateException>(
                () => AmbientTasks.Add(Task.FromException(exception)));

            aggregateException.InnerExceptions.ShouldHaveSingleItem().ShouldBeSameAs(exception);

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.Faulted);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_waits_for_added_task_with_no_context_to_fault()
        {
            var source = new TaskCompletionSource <object?>();

            AmbientTasks.Add(source.Task);

            var waitAllTask = AmbientTasks.WaitAllAsync();

            waitAllTask.IsCompleted.ShouldBeFalse();

            source.SetException(new Exception());
            waitAllTask.Status.ShouldBe(TaskStatus.Faulted);
            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static async Task WaitAllAsync_should_throw_AggregateException_when_awaited()
        {
            var source = new TaskCompletionSource <object?>();

            AmbientTasks.Add(source.Task);

            var waitAllTask = AmbientTasks.WaitAllAsync();

            var exception = new Exception();

            source.SetException(exception);

            var aggregateException = await Should.ThrowAsync <AggregateException>(waitAllTask);

            aggregateException.InnerExceptions.ShouldBe(new[] { exception });
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_resets_after_overlapping_tasks_fail()
        {
            var source1 = new TaskCompletionSource <object?>();
            var source2 = new TaskCompletionSource <object?>();

            AmbientTasks.Add(source1.Task);
            AmbientTasks.Add(source2.Task);

            var waitAllTaskBeforeAllExceptions = AmbientTasks.WaitAllAsync();

            source1.SetException(new Exception());
            source2.SetException(new Exception());

            waitAllTaskBeforeAllExceptions.Status.ShouldBe(TaskStatus.Faulted);
            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Handled_exceptions_do_not_appear_in_task_returned_from_WaitAllAsync_while_waiting_for_task()
        {
            var source    = new TaskCompletionSource <object?>();
            var exception = new Exception();

            AmbientTasks.BeginContext(handler => { });

            AmbientTasks.Add(source.Task);

            var waitAllTask = AmbientTasks.WaitAllAsync();

            waitAllTask.IsCompleted.ShouldBeFalse();

            source.SetException(exception);

            waitAllTask.Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [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);
        }
        [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);
        }
        [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);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_should_have_single_AggregateException_with_all_exceptions_from_each_task_all_faulted_synchronously()
        {
            var task1Exceptions = new[] { new Exception("Task 1 exception 1"), new Exception("Task 1 exception 2") };
            var task2Exceptions = new[] { new Exception("Task 2 exception 1"), new Exception("Task 2 exception 2") };
            var source1         = new TaskCompletionSource <object?>();
            var source2         = new TaskCompletionSource <object?>();

            AmbientTasks.Add(source1.Task);
            AmbientTasks.Add(source2.Task);

            source1.SetException(task1Exceptions);
            source2.SetException(task2Exceptions);

            var waitAllTask = AmbientTasks.WaitAllAsync();

            waitAllTask.Status.ShouldBe(TaskStatus.Faulted);

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

            aggregateException.InnerExceptions.ShouldBe(task1Exceptions.Concat(task2Exceptions));
        }
        [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);
            }
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_does_not_return_with_fault_from_added_test_until_last_task_completes()
        {
            var source1 = new TaskCompletionSource <object?>();
            var source2 = new TaskCompletionSource <object?>();
            var source3 = new TaskCompletionSource <object?>();

            AmbientTasks.Add(source1.Task);
            AmbientTasks.Add(source2.Task);
            AmbientTasks.Add(source3.Task);

            var waitAllTask = AmbientTasks.WaitAllAsync();

            source1.SetException(new Exception());
            waitAllTask.IsCompleted.ShouldBeFalse();
            AmbientTasks.WaitAllAsync().ShouldBeSameAs(waitAllTask);

            source2.SetResult(null);
            waitAllTask.IsCompleted.ShouldBeFalse();
            AmbientTasks.WaitAllAsync().ShouldBeSameAs(waitAllTask);

            source3.SetResult(null);
            waitAllTask.Status.ShouldBe(TaskStatus.Faulted);
            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void WaitAllAsync_should_have_single_AggregateException_with_all_three_exceptions_when_handler_throws_exception_twice()
        {
            var taskException     = new Exception();
            var handlerException1 = new Exception();
            var handlerException2 = new Exception();
            var watcher           = new CallbackWatcher();

            AmbientTasks.BeginContext(ex =>
            {
                watcher.OnCallback(out var callCount);

                throw callCount == 1 ? handlerException1 : handlerException2;
            });

            using (watcher.ExpectCallback(count: 2))
                AmbientTasks.Add(Task.FromException(taskException));

            var waitAllTask = AmbientTasks.WaitAllAsync();

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

            aggregateException.InnerExceptions.ShouldBe(new[] { taskException, handlerException1, handlerException2 });
        }
Beispiel #23
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Func_throwing_TaskCanceledException_is_noop()
        {
            AmbientTasks.Add(() => throw new TaskCanceledException());

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
Beispiel #24
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Func_returning_synchronously_successfully_completed_task_is_noop()
        {
            AmbientTasks.Add(() => Task.CompletedTask);

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
Beispiel #25
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Func_returning_null_task_is_noop()
        {
            AmbientTasks.Add(() => null !);

            AmbientTasks.WaitAllAsync().Status.ShouldBe(TaskStatus.RanToCompletion);
        }
Beispiel #26
0
        [PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283
        public static void Adding_null_func_is_noop()
        {
            AmbientTasks.Add((Func <Task>?)null);

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