[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); }
[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); } }
[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 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 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); } }
[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 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); } }
[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 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); }