コード例 #1
0
        public async Task TaskRunnerBase_DoesNotShutDownFaultedThread_AfterRepeatedFaultsWithOverriddenRepeatedTaskFailureTime()
        {
            var counter = 0;
            var exceptionHandlerCounter = 0;

            var sut = new TaskRunnerActual((ct =>
            {
                return(new List <TaskRunnerInformationBase>()
                {
                    GetTaskRunnerInformation <object>(
                        () => { counter++; throw (new Exception()); },
                        (ex, info) => { exceptionHandlerCounter++; return Task.FromResult(0); },
                        (ex, ts) => { return TimeSpan.FromDays(1); },
                        null,
                        ct
                        )
                });
            })
                                           );

            sut.Settings.MaxUnhandledExceptions = 1;
            // This setting would allow the task be retried forever if respected
            sut.Settings.DefaultRepeatedTaskFailureTime = TimeSpan.FromDays(-1);

            await RunSUT(sut, () =>
            {
                Assert.True(counter > sut.Settings.MaxUnhandledExceptions + 1, $"Expected thread to be tried once and retried many times, was run {counter} times instead");
                //We expect the exception handler NOT to run on counter runs up to MaxUnhandledExceptions.
                //For example, with MUH = 2, we expect an initial run (counter = 0), and 1 more (counter = 1) which do not call the exception handler
                var expectedExceptionHandlerCount = counter - (sut.Settings.MaxUnhandledExceptions);
                Assert.True(exceptionHandlerCounter == expectedExceptionHandlerCount, $"Expected exception handler to be run {expectedExceptionHandlerCount} times, was ran {exceptionHandlerCounter} times instead");
            }).ConfigureAwait(false);
        }
コード例 #2
0
        public async Task TaskRunnerBase_DoesNotShutDownFaultedThread_AfterRepeatedSeparateFaultsWithOverriddenRepeatedTaskFailureTime()
        {
            var counter = 0;
            var exceptionHandlerCounter = 0;

            var sut = new TaskRunnerActual((ct =>
            {
                return(new List <TaskRunnerInformationBase>()
                {
                    GetTaskRunnerInformation <object>(
                        () => { counter++; throw (new Exception()); },
                        (ex, info) => { exceptionHandlerCounter++; return Task.FromResult(0); },
                        (ex, ts) => { return TimeSpan.FromDays(-1); },
                        null,
                        ct
                        ),
                });
            })
                                           );

            await RunSUT(sut, () =>
            {
                Assert.True(counter > sut.Settings.MaxUnhandledExceptions + 1, $"Expected thread to be tried once and retried many times, was run {counter} times instead");
                Assert.True(exceptionHandlerCounter == 0, $"Expected exception handler to not be run, was ran {exceptionHandlerCounter} times instead");
            }).ConfigureAwait(false);
        }
コード例 #3
0
        public async Task TaskRunnerBase_DoesNotThrow_FailureInRepeatedTaskFailureTimeHandler()
        {
            var counter = 0;
            var exceptionHandlerCounter = 0;

            var sut = new TaskRunnerActual((ct =>
            {
                return(new List <TaskRunnerInformationBase>()
                {
                    GetTaskRunnerInformation <object>(
                        () => { counter++; throw new Exception(); },
                        (ex, info) => { exceptionHandlerCounter++; return Task.FromResult(0); },
                        (ex, ts) => { throw new Exception(); },
                        null,
                        ct
                        )
                });
            })
                                           );

            await RunSUT(sut, () =>
            {
                Assert.True(counter > sut.Settings.MaxUnhandledExceptions + 1, $"Expected thread to be tried once and retried many times, was run {counter} times instead");
                //We expect the exception handler NOT to run on counter runs up to MaxUnhandledExceptions.
                //For example, with MUH = 2, we expect an initial run (counter = 0), and 1 more (counter = 1) which do not call the exception handler
                var expectedExceptionHandlerCount = counter - (sut.Settings.MaxUnhandledExceptions);
                Assert.True(exceptionHandlerCounter == expectedExceptionHandlerCount, $"Expected exception handler to be run {expectedExceptionHandlerCount} times, was ran {exceptionHandlerCounter} times instead");
            }).ConfigureAwait(false);
        }
コード例 #4
0
        public async Task TaskRunnerBase_Throws_PartitionKillerException()
        {
            var knownKillerExceptions = new List <Exception>()
            {
                new OutOfMemoryException()
            };

            foreach (var exception in knownKillerExceptions)
            {
                var sut = new TaskRunnerActual((ct =>
                {
                    return(new List <TaskRunnerInformationBase>()
                    {
                        GetTaskRunnerInformation <object>(() => { throw(exception); }, null, null, null, ct)
                    });
                }));

                var task = Task.Run(() => sut.OuterRun(CancellationToken.None));

                var e = await Assert.ThrowsAsync <AggregateException>(async() =>
                {
                    await task.ConfigureAwait(false);
                });

                Assert.True(e.InnerException.GetType() == exception.GetType(),
                            $"Expected exception to be {exception.GetType()}, was {task.Exception.InnerException.GetType()} instead");
            }
        }
コード例 #5
0
        public async Task TaskRunnerBase_Cancels_AfterCancellationRequested()
        {
            var counter = 0;

            var sut = new TaskRunnerActual((ct =>
            {
                return(new List <TaskRunnerInformationBase>()
                {
                    GetTaskRunnerInformation <object>(async() => { counter++; await Task.Delay(Timeout.Infinite); }, null, null, null, ct)
                });
            }));

            var source = new CancellationTokenSource();
            var task   = Task.Run(() => sut.OuterRun(source.Token));

            await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);

            source.Cancel();

            Assert.True(counter == 1, $"Expected thread to only run once, ran {counter} times instead");
            Assert.True(sut.InitialCancellationToken.IsCancellationRequested == true, $"Expected cancellation token passed into SUT to be cancelled");
            Assert.True(sut.LinkedCancellationToken.IsCancellationRequested == true, $"Expected linked cancellation token created in SUT to be cancelled");

            await task.AwaitCompleteOrCancel();
        }
コード例 #6
0
        public async Task TaskRunnerBase_DoesNotShutDownFaultedThread_AfterRepeatedSeparateFaults()
        {
            var counter = 0;
            var exceptionHandlerCounter = 0;

            var dateTimeProvider = new Mock <IDateTimeProvider>();

            dateTimeProvider.Setup(x => x.UtcNow).Returns(() => { return(DateTime.UtcNow.AddDays(counter)); });

            var sut = new TaskRunnerActual((ct =>
            {
                return(new List <TaskRunnerInformationBase>()
                {
                    GetTaskRunnerInformation <object>(
                        () => { counter++; throw (new Exception()); },
                        (ex, info) => { exceptionHandlerCounter++; return Task.FromResult(0); },
                        null,
                        null,
                        ct
                        ),
                });
            }),
                                           dateTimeProvider.Object
                                           );

            await RunSUT(sut, () =>
            {
                Assert.True(counter > sut.Settings.MaxUnhandledExceptions + 1, $"Expected thread to be tried once and retried many times, was run {counter} times instead");
                Assert.True(exceptionHandlerCounter == 0, $"Expected exception handler to not be run, was ran {exceptionHandlerCounter} times instead");
            }).ConfigureAwait(false);
        }
コード例 #7
0
        public async Task TaskRunnerBase_DoesNotThrow_ExceptionsFromExceptionHandler()
        {
            var counter = 0;
            var exceptionHandlerCounter = 0;

            var sut = new TaskRunnerActual((ct =>
            {
                return(new List <TaskRunnerInformationBase>()
                {
                    GetTaskRunnerInformation <object>(
                        () => { counter++; throw new Exception(); },
                        (ex, info) => { exceptionHandlerCounter++; throw new Exception(); },
                        null,
                        null,
                        ct
                        )
                });
            })
                                           );

            await RunSUT(sut, () =>
            {
                VerifySubmittedLogWarning(sut.MockLog, "ClearTasks", "", Times.Never());
                VerifySubmittedLogError(sut.MockLog, "RunTask", Times.Exactly(counter - sut.Settings.MaxUnhandledExceptions + 1));
                VerifySubmittedLogWarning(sut.MockLog, "RunTask", "Unhandled exception in final exception handler", Times.Exactly(counter - sut.Settings.MaxUnhandledExceptions));

                Assert.True(exceptionHandlerCounter == counter - sut.Settings.MaxUnhandledExceptions, $"Expected exception handler to run {counter - sut.Settings.MaxUnhandledExceptions} times, ran {exceptionHandlerCounter} times instead");
            }).ConfigureAwait(false);
        }
コード例 #8
0
        private async Task RunSUT(TaskRunnerActual sut, Action code)
        {
            var source = new CancellationTokenSource();
            var task   = Task.Run(() => sut.Run(source.Token));

            await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(false);

            code();

            source.Cancel();
            await task.AwaitCompleteOrCancel();
        }
コード例 #9
0
        public async Task TaskRunnerBase_Awaits_AfterAllComplete()
        {
            var counter = 0;

            var sut = new TaskRunnerActual((ct =>
            {
                return(new List <TaskRunnerInformationBase>()
                {
                    GetTaskRunnerInformation <object>(() => { counter++; return Task.FromResult(0); }, null, null, null, ct),
                });
            }));

            await RunSUT(sut, () =>
            {
                Assert.True(counter == 1, $"Expected thread to only run once, ran {counter} times instead");
            }).ConfigureAwait(false);
        }
コード例 #10
0
        public async Task TaskRunnerBase_DoesNotShutDownFaultedThread_AfterRepeatedSeparateFaultsWithOccasionalSequentialFaults()
        {
            var counter = 0;
            var exceptionHandlerCounter = 0;

            var dateTimeProvider = new Mock <IDateTimeProvider>();

            dateTimeProvider.Setup(x => x.UtcNow).Returns(() => {
                // Half the time, return a value that makes it look like it's been a long time since the thread faulted
                //Note that the "+1" is required here to prevent the spoofed date occuring on the same counter as the
                //first exceptionCount that is not under the MaxUnhandledExceptions, as this would erroneously cause
                //the test to fail (as only the UtcNow used for the taskStartTime would be increased by the mock,
                //not the one within ShouldRespondToException).
                if ((counter + 1) % 2 == 0)
                {
                    return(DateTime.UtcNow.AddDays(counter));
                }

                // The rest of the time, return the current time, which will look like it's been no time since the task faulted
                return(DateTime.UtcNow);
            });

            var sut = new TaskRunnerActual((ct =>
            {
                return(new List <TaskRunnerInformationBase>()
                {
                    GetTaskRunnerInformation <object>(
                        () => { counter++; throw (new Exception()); },
                        (ex, info) => { exceptionHandlerCounter++; return Task.FromResult(0); },
                        null,
                        null,
                        ct
                        ),
                });
            }),
                                           dateTimeProvider.Object
                                           );

            await RunSUT(sut, () =>
            {
                Assert.True(counter > sut.Settings.MaxUnhandledExceptions + 1, $"Expected thread to be tried once and retried many times, was run {counter} times instead");
                Assert.True(exceptionHandlerCounter == 0, $"Expected exception handler to not be run, was ran {exceptionHandlerCounter} times instead");
            }).ConfigureAwait(false);
        }
コード例 #11
0
        public async Task TaskRunnerBase_OnlyRestartsFaultedThread_AfterFault()
        {
            var counter          = 0;
            var exceptionCounter = 0;

            var sut = new TaskRunnerActual((ct =>
            {
                return(new List <TaskRunnerInformationBase>()
                {
                    GetTaskRunnerInformation <object>(() => { counter++; return Task.FromResult(0); }, null, null, null, ct),
                    GetTaskRunnerInformation <object>(async() => { exceptionCounter++; await Task.Delay(TimeSpan.FromSeconds(1)); throw(new Exception()); }, null, null, null, ct),
                });
            }));

            await RunSUT(sut, () =>
            {
                Assert.True(counter == 1, $"Expected thread to only run once, ran {counter} times instead");
                Assert.True(exceptionCounter == sut.Settings.MaxUnhandledExceptions + 1, $"Expected exception handler to run {sut.Settings.MaxUnhandledExceptions + 1} times, was run {exceptionCounter} times instead");
            }).ConfigureAwait(false);
        }