public void Execute_TaskWithSteps_VerifyLogging() { var logger = Substitute.For <ILogger>(); var concurrentExecution = Substitute.For <IConcurrentTaskExecution>(); var shutdown = Substitute.For <IShutdown>(); var console = Substitute.For <IConsoleWriter>(); var step1 = Substitute.For <IStep <SomeWorkItem> >(); var step2 = Substitute.For <IStep <SomeWorkItem> >(); var workItem = new SomeWorkItem(); var task = new TaskRunnerTesterTask <SomeWorkItem>(new[] { step1, step2 }, workItem); concurrentExecution .Handle(Arg.Is(task), Arg.Any <Arguments>(), Arg.Any <TaskLog>()) .Returns(ConcurrentTaskExecutionResult.Continue()); ITaskExecutionContext <SomeWorkItem> ContextArg() => Arg.Is <ITaskExecutionContext <SomeWorkItem> >(context => context.WorkItem == workItem); step1.ContinueWith(ContextArg()).Returns(Execution.Execute); step2.ContinueWith(ContextArg()).Returns(Execution.Execute); var subject = new TaskRunner(logger, concurrentExecution, shutdown, console); subject.Execute(task); logger.Received().LogEntry(Arg.Any <TaskLog>()); logger.Received().LogEntry(Arg.Is <StepLog>(x => x.Name == step1.Name())); logger.Received().LogEntry(Arg.Is <StepLog>(x => x.Name == step2.Name())); step1.Received().Execute(ContextArg()); step2.Received().Execute(ContextArg()); Assert.That(task.EndCalled, Is.True); }
public void Execute_ConcurrentTaskExecutionShouldStopTask_VerifyTaskNotStarted() { var logger = Substitute.For <ILogger>(); var concurrentExecution = Substitute.For <IConcurrentTaskExecution>(); var shutdown = Substitute.For <IShutdown>(); var console = Substitute.For <IConsoleWriter>(); var task = Substitute.For <ITask <object> >(); concurrentExecution .Handle(Arg.Is(task), Arg.Any <Arguments>(), Arg.Any <TaskLog>()) .Returns(ConcurrentTaskExecutionResult.Stop()); var subject = new TaskRunner(logger, concurrentExecution, shutdown, console); subject.Execute(task); task.DidNotReceive().Start(Arg.Any <ITaskExecutionContext <object> >()); }
public void Execute_FailsAtStep_VerifyLogging() { var logger = Substitute.For <ILogger>(); var concurrentExecution = Substitute.For <IConcurrentTaskExecution>(); var shutdown = Substitute.For <IShutdown>(); var console = Substitute.For <IConsoleWriter>(); var step1 = Substitute.For <IStep <SomeWorkItem> >(); var step2 = Substitute.For <IStep <SomeWorkItem> >(); var workItem = new SomeWorkItem(); var task = new TaskRunnerTesterTask <SomeWorkItem>(new[] { step1, step2 }, workItem); var throwingException = new DivideByZeroException("error"); concurrentExecution .Handle(Arg.Is(task), Arg.Any <Arguments>(), Arg.Any <TaskLog>()) .Returns(ConcurrentTaskExecutionResult.Continue()); ITaskExecutionContext <SomeWorkItem> ContextArg() => Arg.Is <ITaskExecutionContext <SomeWorkItem> >(context => context.WorkItem == workItem); step1.ContinueWith(ContextArg()).Returns(Execution.Execute); step1 .When(x => x.Execute(ContextArg())) .Do(x => throw throwingException); var subject = new TaskRunner(logger, concurrentExecution, shutdown, console); var thrownException = Assert.Throws <TaskExecutionFailedException>(() => subject.Execute(task)); Assert.That(thrownException.InnerException, Is.EqualTo(throwingException)); logger.Received().LogEntry(Arg.Any <TaskLog>()); logger.Received().LogEntry(Arg.Is <StepLog>(x => x.Name == step1.Name())); step1.Received().Execute(ContextArg()); step2.DidNotReceive().Execute(ContextArg()); logger.Received().LogError(Arg.Is(throwingException)); Assert.That(task.EndCalled, Is.False); }
public void Execute_Task_VerifyLogging() { var logger = Substitute.For <ILogger>(); var concurrentExecution = Substitute.For <IConcurrentTaskExecution>(); var shutdown = Substitute.For <IShutdown>(); var console = Substitute.For <IConsoleWriter>(); var task = Substitute.For <ITask <object> >(); concurrentExecution .Handle(Arg.Is(task), Arg.Any <Arguments>(), Arg.Any <TaskLog>()) .Returns(ConcurrentTaskExecutionResult.Continue()); var subject = new TaskRunner(logger, concurrentExecution, shutdown, console); subject.Execute(task); logger.Received().LogEntry(Arg.Any <TaskLog>()); task.Received().Start(Arg.Any <ITaskExecutionContext <object> >()); }
public void Execute_ConcurrentTaskExecutionWithLock_VerifyLockIsDisposed() { var logger = Substitute.For <ILogger>(); var concurrentExecution = Substitute.For <IConcurrentTaskExecution>(); var shutdown = Substitute.For <IShutdown>(); var console = Substitute.For <IConsoleWriter>(); var lockAcquired = Substitute.For <IDisposable>(); var task = Substitute.For <ITask <object> >(); concurrentExecution .Handle(Arg.Is(task), Arg.Any <Arguments>(), Arg.Any <TaskLog>()) .Returns(ConcurrentTaskExecutionResult.Continue(lockAcquired)); var subject = new TaskRunner(logger, concurrentExecution, shutdown, console); subject.Execute(task); task.Received().Start(Arg.Any <ITaskExecutionContext <object> >()); lockAcquired.Received().Dispose(); }
private ConcurrentTaskExecutionResult HandleConcurrentTaskExecution(ITask task, Arguments arguments, TaskLog taskLog) { try { ConcurrentTaskExecutionResult result = _concurrentTaskExecution.Handle(task, arguments, taskLog); if (result == null) { throw new InvalidOperationException($"{_concurrentTaskExecution.GetType().FullName} returned <null> which was not expected."); } return(result); } catch (Exception ex) { ErrorLog errorLog = _logger.LogError(ex); taskLog.ErrorLog = errorLog; throw new TaskExecutionFailedException($"Starting Task '{taskLog.Name}' failed with message: '{ex.DestructMessage()}'. ErrorID: {errorLog?.Id ?? "<null>"}.", ex); } }
public void Execute_IDisposableWorkItem_Step2Fails() { var logger = Substitute.For <ILogger>(); var concurrentExecution = Substitute.For <IConcurrentTaskExecution>(); var shutdown = Substitute.For <IShutdown>(); var console = Substitute.For <IConsoleWriter>(); int disposedCount = 0; var step1 = Substitute.For <IStep <DisposableWorkItem> >(); var step2 = Substitute.For <IStep <DisposableWorkItem> >(); var workItem = new DisposableWorkItem(() => disposedCount++); var exception = new InvalidOperationException(); var task = new TaskRunnerTesterTask <DisposableWorkItem>(new[] { step1, step2 }, workItem); concurrentExecution .Handle(Arg.Is(task), Arg.Any <Arguments>(), Arg.Any <TaskLog>()) .Returns(ConcurrentTaskExecutionResult.Continue()); ITaskExecutionContext <DisposableWorkItem> ContextArg() => Arg.Is <ITaskExecutionContext <DisposableWorkItem> >(context => context.WorkItem == workItem); step1.ContinueWith(ContextArg()).Returns(Execution.Execute); step2.ContinueWith(ContextArg()).Returns(Execution.Execute); step2 .When(x => x.Execute(ContextArg())) .Do(x => throw exception); var subject = new TaskRunner(logger, concurrentExecution, shutdown, console); var thrownException = Assert.Throws <TaskExecutionFailedException>(() => subject.Execute(task)); step1.Received().Execute(ContextArg()); step2.Received().Execute(ContextArg()); Assert.That(task.EndCalled, Is.False); Assert.That(disposedCount, Is.EqualTo(1)); Assert.That(thrownException.InnerException, Is.SameAs(exception)); }
public void Execute_TaskThrowsAggregateException_VerifyLogging() { var logger = Substitute.For <ILogger>(); var concurrentExecution = Substitute.For <IConcurrentTaskExecution>(); var shutdown = Substitute.For <IShutdown>(); var console = Substitute.For <IConsoleWriter>(); var task = new ThrowingAggregateExceptionTask(); concurrentExecution .Handle(Arg.Is(task), Arg.Any <Arguments>(), Arg.Any <TaskLog>()) .Returns(ConcurrentTaskExecutionResult.Continue()); var subject = new TaskRunner(logger, concurrentExecution, shutdown, console); var thrownException = Assert.Throws <TaskExecutionFailedException>(() => subject.Execute(task)); var aggregateException = thrownException.InnerException as AggregateException; Assert.IsNotNull(aggregateException); CollectionAssert.Contains(aggregateException.InnerExceptions.Select(x => x.GetType()), typeof(InvalidOperationException)); CollectionAssert.Contains(aggregateException.InnerExceptions.Select(x => x.GetType()), typeof(DivideByZeroException)); logger.Received().LogError(Arg.Is(aggregateException)); }
private TaskExecutionResult ExecuteInternal <TWorkItem>(ITask <TWorkItem> task, Arguments arguments) { if (task == null) { throw new ArgumentNullException(nameof(task)); } if (arguments == null) { throw new ArgumentNullException(nameof(arguments)); } var output = new List <string>(); void Outputter(string message) { message = $"[{Time.Now:HH:mm:ss}] {message}"; _console.WriteLine(message); output.Add(message); } using (var taskLog = new TaskLog(task, _logger.LogEntry, new Output(Outputter))) using (ConcurrentTaskExecutionResult taskExecution = HandleConcurrentTaskExecution(task, arguments, taskLog)) { if (taskExecution.StopTask) { return(new TaskExecutionResult(output.ToArray())); } Action <string>[] logMessage = { x => { } }; var log = new Log(message => logMessage[0]?.Invoke(message), _logger); var context = new TaskExecutionContext <TWorkItem>(taskLog, log, arguments, _shutdown.Token); if (task.IsDisabled(context)) { Outputter($"Task '{task.Name()}' is disabled."); return(new TaskExecutionResult(output.ToArray())); } try { logMessage[0] = taskLog.LogMessage; context.ThrowIfCancelled(); context.WorkItem = task.Start(context); } catch (Exception ex) { ErrorLog errorLog = _logger.LogError(ex); taskLog.ErrorLog = errorLog; throw new TaskExecutionFailedException($"Starting Task '{taskLog.Name}' failed with message: '{ex.DestructMessage()}'. ErrorID: {errorLog?.Id ?? "<null>"}.", ex); } try { foreach (IStep <TWorkItem> step in task.Steps) { using (StepLog stepLog = taskLog.LogStep(step)) { try { logMessage[0] = stepLog.LogMessage; context.ThrowIfCancelled(); Execution continueWith = step.ContinueWith(context); if (continueWith == Execution.StepOut) { break; } if (continueWith == Execution.StepOver) { continue; } context.ThrowIfCancelled(); step.Execute(context); } catch (Exception ex) { ErrorLog errorLog = _logger.LogError(ex); taskLog.ErrorLog = errorLog; stepLog.ErrorLog = errorLog; throw new TaskExecutionFailedException($"Step '{stepLog.Name}' on Task '{taskLog.Name}' failed with message: '{ex.Message}'. ErrorID: {errorLog?.Id ?? "<null>"}.", ex); } } } try { logMessage[0] = taskLog.LogMessage; context.ThrowIfCancelled(); task.End(context); } catch (Exception ex) { ErrorLog errorLog = _logger.LogError(ex); taskLog.ErrorLog = errorLog; throw new TaskExecutionFailedException($"Ending Task '{taskLog.Name}' failed with message: '{ex.Message}'. ErrorID: {errorLog?.Id ?? "<null>"}.", ex); } } finally { context.WorkItem.DisposeIfDisposable(); } } return(new TaskExecutionResult(output.ToArray())); }