Exemple #1
0
        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);
        }
Exemple #2
0
        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> >());
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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> >());
        }
Exemple #5
0
        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);
            }
        }
Exemple #7
0
        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));
        }
Exemple #8
0
        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()));
        }