[PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283 public static async Task BeginContext_handler_flows_into_new_thread() { var source = new TaskCompletionSource <object?>(); var watcher = new CallbackWatcher(); var thread = new Thread(() => { try { using (watcher.ExpectCallback()) AmbientTasks.Add(Task.FromException(new Exception())); source.SetResult(null); } catch (Exception ex) { source.SetException(ex); } }); AmbientTasks.BeginContext(ex => watcher.OnCallback()); thread.Start(); await source.Task; }
[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_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 async Task BeginContext_handler_flows_into_ThreadPool_QueueUserWorkItem() { var watcher = new CallbackWatcher(); AmbientTasks.BeginContext(ex => watcher.OnCallback()); var source = new TaskCompletionSource <object?>(); ThreadPool.QueueUserWorkItem(_ => { try { using (watcher.ExpectCallback()) AmbientTasks.Add(Task.FromException(new Exception())); source.SetResult(null); } catch (Exception ex) { source.SetException(ex); } }, null); await source.Task; }
[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 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 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 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 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 Adding_synchronously_faulted_task_with_no_context_throws_AggregateException_synchronously() { var exception = new Exception(); var aggregateException = Should.Throw <AggregateException>( () => AmbientTasks.Add(Task.FromException(exception))); aggregateException.InnerExceptions.ShouldBe(new[] { exception }); }
[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 async Task BeginContext_handler_does_not_flow_from_inner_method_back_to_outer_method_after_await() { var watcher = new CallbackWatcher(); AmbientTasks.BeginContext(ex => watcher.OnCallback()); await InnerFunction(); using (watcher.ExpectCallback()) AmbientTasks.Add(Task.FromException(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_SynchronizationContext_post_before_invoking_delegate_is_not_handled_when_there_is_a_BeginContext_handler([Values] PostOverload overload) { AmbientTasks.BeginContext(ex => { }); var exception = new Exception(); using (SynchronizationContextAssert.ExpectSinglePost(postedAction => throw exception)) { Should.Throw <Exception>(() => AmbientTasksPost(overload, () => { })).ShouldBeSameAs(exception); } }
[PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283 public static void BeginContext_handler_is_replaced_with_next_call() { AmbientTasks.BeginContext(ex => Assert.Fail("This handler should not be called.")); var watcher = new CallbackWatcher(); AmbientTasks.BeginContext(ex => watcher.OnCallback()); using (watcher.ExpectCallback()) AmbientTasks.Add(Task.FromException(new Exception())); }
[PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283 public static async Task BeginContext_handler_flows_across_await() { var watcher = new CallbackWatcher(); AmbientTasks.BeginContext(ex => watcher.OnCallback()); await Task.Yield(); using (watcher.ExpectCallback()) AmbientTasks.Add(Task.FromException(new Exception())); }
[PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283 public static async Task BeginContext_handler_flows_into_Task_Run() { var watcher = new CallbackWatcher(); AmbientTasks.BeginContext(ex => watcher.OnCallback()); await Task.Run(() => { using (watcher.ExpectCallback()) AmbientTasks.Add(Task.FromException(new Exception())); }); }
[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_receives_exception_thrown_from_func() { var exception = new Exception(); var watcher = new CallbackWatcher(); AmbientTasks.BeginContext(ex => { watcher.OnCallback(); ex.ShouldBeSameAs(exception); }); using (watcher.ExpectCallback()) AmbientTasks.Add(() => throw exception); }
[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 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)); } }
[PreventExecutionContextLeaks] // Workaround for https://github.com/nunit/nunit/issues/3283 public static void BeginContext_handler_receives_exceptions_from_synchronously_faulted_tasks() { var exception = new Exception(); var watcher = new CallbackWatcher(); AmbientTasks.BeginContext(ex => { watcher.OnCallback(); ex.ShouldBeSameAs(exception); }); using (watcher.ExpectCallback()) AmbientTasks.Add(Task.FromException(exception)); }
[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 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())); } } }
[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 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 Adding_synchronously_faulted_task_with_multiple_exceptions_and_no_context_throws_AggregateException_synchronously_with_all_exceptions() { var exceptions = new[] { new Exception(), new Exception() }; var source = new TaskCompletionSource <object?>(); source.SetException(exceptions); var aggregateException = Should.Throw <AggregateException>(() => AmbientTasks.Add(source.Task)); aggregateException.InnerExceptions.ShouldBe(exceptions); }
[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); }