public void AwaitingSynchronousDependencyExecutesSynchronously() { using (var runner = new LocalTaskRunner(this.exceptionHandler)) { var t = runner.StartTask(TestAsync, runner); t.AssertCompletedSuccessfully(); Assert.AreEqual(2, t.Result); } async Task <int> TestAsync(ITaskRunner runner) { if (await runner.StartTask(DependencyAsync)) { return(1); } return(2); } async Task <bool> DependencyAsync() { if (DateTime.UtcNow.Year > 0) { return(false); } await Task.Delay(TimeSpan.FromHours(1)); return(true); } }
public void FinishedTasksAreRemovedFromRunner() { var exHandler = new MockExceptionHandler(); using (var runner = new LocalTaskRunner(exHandler)) { runner.AssertRunningTaskCount(0); runner.StartTask(TestOfTAsync); runner.AssertRunningTaskCount(1); runner.Execute(); runner.AssertRunningTaskCount(0); runner.AssertRunningTaskCount(0); runner.StartTask(TestAsync); runner.AssertRunningTaskCount(1); runner.Execute(); runner.AssertRunningTaskCount(0); } async Task TestAsync() { await Task.Yield(); } async Task <int> TestOfTAsync() { await Task.Yield(); return(42); } }
public void DoesNotAllowStartingTaskAfterDispose() { var exHandler = new MockExceptionHandler(); var runner = new LocalTaskRunner(exHandler); runner.Dispose(); Assert.Throws <ObjectDisposedException>(() => runner.StartTask(() => Task.CompletedTask)); Assert.Throws <ObjectDisposedException>(() => runner.StartTask(() => Task.FromResult <int>(42))); }
public void ThrowsForTaskCreatorsThatReturnsNull() { var exHandler = new MockExceptionHandler(); using (var runner = new LocalTaskRunner(exHandler)) { Assert.Throws <TaskCreatorReturnedNullException>(() => runner.StartTask(TaskReturnNull)); Assert.Throws <TaskCreatorReturnedNullException>(() => runner.StartTask(TaskOfTReturnNull)); } Task TaskReturnNull() => null; Task <int> TaskOfTReturnNull() => null; }
public void YieldWaitsForNextExecute() { const int iterations = 25; var count = 0; using (var runner = new LocalTaskRunner(this.exceptionHandler)) { runner.StartTask(WaitAndIncrementAsync); for (int i = 0; i < iterations; i++) { Assert.AreEqual(i, count); runner.Execute(); } } async Task WaitAndIncrementAsync() { for (int i = 0; i < iterations; i++) { await Task.Yield(); count++; } } }
public void ExecuteThreadingStressTest() { var exHandler = new MockExceptionHandler(); using (var runner = new LocalTaskRunner(exHandler)) { // Start many tasks tasks. for (int i = 0; i < 100; i++) { runner.StartTask(TestAsync); } for (int interation = 0; interation < 11; interation++) { // Execute from many different threads in parallel. for (int thread = 0; thread < 100; thread++) { ThreadPool.QueueUserWorkItem(r => ((LocalTaskRunner)r).Execute(), runner); } Thread.Sleep(millisecondsTimeout: 100); } // Assert that all tasks have finished. runner.AssertRunningTaskCount(0); } async Task TestAsync() { for (int i = 0; i < 10; i++) { await Task.Yield(); } } }
public void CallbackPostThreadingStressTest() { var exHandler = new MockExceptionHandler(); using (var runner = new LocalTaskRunner(exHandler)) { // Start the stress tasks. for (int i = 0; i < 50; i++) { runner.StartTask(StressAsync); } // Execute enough times to finish all tasks. for (int i = 0; i < 99; i++) { runner.Execute(); Thread.Sleep(10); } // Assert that all tasks have finished. runner.AssertRunningTaskCount(0); } async Task StressAsync() { /* This stresses the sync-context by posting callbacks from many different threads. */ for (int i = 0; i < 50; i++) { await Task.Run(() => Thread.Yield()); } } }
public void RunnerScopePropagatesToCalledMethods() { var count = 0; using (var runner = new LocalTaskRunner(this.exceptionHandler)) { var t = runner.StartTask(TestAsync); runner.Execute(); Assert.AreEqual(0, count); runner.Execute(); Assert.AreEqual(1, count); runner.Execute(); Assert.AreEqual(1, count); runner.Execute(); Assert.AreEqual(2, count); t.AssertCompletedSuccessfully(); } async Task TestAsync() { count += await SubTestAsync(); count += await SubTestAsync(); } async Task <int> SubTestAsync() { await Task.Yield(); await Task.Yield(); return(1); } }
public void CancelledTaskExceptionCanBeCaught() { using (var runner1 = new LocalTaskRunner(this.exceptionHandler)) { Task <int> t; using (var runner2 = new LocalTaskRunner(this.exceptionHandler)) t = runner1.StartTask(TestAsync, runner2); runner1.Execute(); Assert.AreEqual(-1, t.Result); } async Task <int> TestAsync(ITaskRunner r) { try { return(await r.StartTask(GetIntAsync)); } catch (TaskCanceledException) { return(-1); } } async Task <int> GetIntAsync() { await Task.Yield(); return(42); } }
public void CancelledExceptionIsReportedWhenAwaitingDisposedRunner() { using (var runner1 = new LocalTaskRunner(this.exceptionHandler)) { using (var runner2 = new LocalTaskRunner(this.exceptionHandler)) { runner1.StartTask(TestAsync, runner2); this.exceptionHandler.AssertNoExceptions(); } runner1.Execute(); this.exceptionHandler.AssertPop <TaskCanceledException>(); } async Task TestAsync(ITaskRunner r) { await r.StartTask(GetIntAsync); } async Task <int> GetIntAsync() { await Task.Yield(); return(42); } }
public void StartingCompletedTaskIsReturnedDirectly() { var tcs = new TaskCompletionSource <int>(); tcs.SetResult(42); Task <int> completedTaskOfInt = tcs.Task; Task completedTask = tcs.Task; var exHandler = new MockExceptionHandler(); using (var runner = new LocalTaskRunner(exHandler)) { var taskOfInt = runner.StartTask(taskCreator: () => completedTaskOfInt); Assert.True(object.ReferenceEquals(completedTaskOfInt, taskOfInt)); var task = runner.StartTask(taskCreator: () => completedTask); Assert.True(object.ReferenceEquals(completedTask, task)); } }
public void ExceptionsInSynchronousMethodAreThrownDirectly() { using (var runner = new LocalTaskRunner(this.exceptionHandler)) { Assert.Throws <TestException>(() => runner.StartTask(TestAsync)); } Task TestAsync() { throw new TestException(); } }
public void StartingFaultedTaskIsReturnedDirectlyAndErrorIsReported() { var tcs = new TaskCompletionSource <int>(); tcs.SetException(new TestException()); Task <int> faultedTaskOfInt = tcs.Task; Task faultedTask = tcs.Task; var exHandler = new MockExceptionHandler(); using (var runner = new LocalTaskRunner(exHandler)) { var taskOfInt = runner.StartTask(taskCreator: () => faultedTaskOfInt); Assert.True(object.ReferenceEquals(faultedTaskOfInt, taskOfInt)); exHandler.AssertPop <TestException>(); var task = runner.StartTask(taskCreator: () => faultedTask); Assert.True(object.ReferenceEquals(faultedTask, task)); exHandler.AssertPop <TestException>(); } }
public void ThrowWhenTaskChangesSyncronizationContextInSyncronousPart() { var exHandler = new MockExceptionHandler(); using (var runner = new LocalTaskRunner(exHandler)) { Assert.Throws <ContextChangedException>(() => runner.StartTask(TaskThatChangesSyncContext)); } Task TaskThatChangesSyncContext() { SynchronizationContext.SetSynchronizationContext(new MockSynchronizationContext()); return(Task.CompletedTask); } }
public void CancelTokenIsTrippedWhenDisposingRunning() { var heavyCalcRunning = false; using (var runner = new LocalTaskRunner(this.exceptionHandler)) { runner.StartTask(TestAsync); // Wait for 'heavyCalc' to start on a different thread. while (!Volatile.Read(ref heavyCalcRunning)) { Thread.Yield(); } } // Assert that 'HeavyCalc' stops. for (int i = 0; i < 100_000; i++) { if (!Volatile.Read(ref heavyCalcRunning)) { return; } Thread.Yield(); } Assert.Fail("'HeavyCalcAsync' did not stop"); async Task TestAsync(CancellationToken cancelToken) { await Task.Run(() => HeavyCalcAsync(cancelToken)); } async Task <int> HeavyCalcAsync(CancellationToken cancelToken) { heavyCalcRunning = true; try { await Task.Delay(TimeSpan.FromHours(1), cancelToken); return(1); } catch (OperationCanceledException) { heavyCalcRunning = false; return(-1); } } }
public void ExceptionsAreReportedInSynchronousPartOfAsyncMethod() { using (var runner = new LocalTaskRunner(this.exceptionHandler)) { runner.StartTask(TestAsync); this.exceptionHandler.AssertPop <TestException>(); } #pragma warning disable CS1998 async Task TestAsync() { throw new TestException(); } #pragma warning restore CS1998 }
public void CodeBeforeAwaitRunsSynchronously() { var i = 0; using (var runner = new LocalTaskRunner(this.exceptionHandler)) { runner.StartTask(IncrementAndWaitAsync); Assert.AreEqual(1, i); } async Task IncrementAndWaitAsync() { i++; await Task.Yield(); } }
public void ExceptionsAreReportedInAsyncMethod() { using (var runner = new LocalTaskRunner(this.exceptionHandler)) { runner.StartTask(TestAsync); this.exceptionHandler.AssertNoExceptions(); runner.Execute(); this.exceptionHandler.AssertPop <TestException>(); } async Task TestAsync() { await Task.Yield(); throw new TestException(); } }
public void AwaitingCompletedTaskExecutesSynchronously() { var count = 0; using (var runner = new LocalTaskRunner(this.exceptionHandler)) { runner.StartTask(TestAsync); Assert.AreEqual(1, count); } async Task TestAsync() { await Task.CompletedTask; await Task.CompletedTask; count++; } }
public void TaskGetsCancelledWhenRunnerIsDisposed() { Task t; using (var runner = new LocalTaskRunner(this.exceptionHandler)) { t = runner.StartTask(TestAsync); t.AssertRunning(); } t.AssertCanceled(); async Task TestAsync() { while (true) { await Task.Yield(); } } }
public void TaskIsResumedWhenDependencyIsDone() { var count = 0; using (var runner = new LocalTaskRunner(this.exceptionHandler)) using (var dependencyRunner = new LocalTaskRunner(this.exceptionHandler)) { var dep = dependencyRunner.StartTask(DependencyAsync); var t = runner.StartTask(TestAsync, dep); // Task does not complete on its own. runner.Execute(); Assert.AreEqual(0, count); // But when completing dependency. dependencyRunner.Execute(); Assert.AreEqual(0, count); // And then executing the original running the task is completed. runner.Execute(); t.AssertCompletedSuccessfully(); Assert.AreEqual(1, count); } async Task TestAsync(Task dependency) { await dependency; count++; } async Task DependencyAsync() { await Task.Yield(); } }