public void Task_With_PreventConcurrentTaskExecutionAttribute_UnableToAcquireLock_Verify_InteractsWithDistributedMutex()
        {
            var distributedMutex = new DistributedMutexStub();

            using (var context = ApplicationContext.Create(application => application
                                                           .ConfigureForUnitTest()
                                                           .Services(services => services
                                                                     .Advanced(advanced => advanced
                                                                               .Register <IRuntimeSettings>(kernel => new InMemoryRuntimeSettings()
                                                                                                            .Set("ConcurrentTaskExecution.PreventConcurrentTaskExecutionOnAllTasks", "false"))
                                                                               .Register <IDistributedMutex>(kernel => distributedMutex)))
                                                           .Tasks(tasks => tasks
                                                                  .Task <ThrowIfStartsTask>())))
            {
                var runner  = context.Resolve <ITaskRunner>();
                var factory = context.Resolve <ITaskFactory>();

                // Create an existing lock based on the actual task
                distributedMutex.SimulateLockFromTask <ThrowIfStartsTask>();

                ITask task = factory.Get <ThrowIfStartsTask>();

                var exception = Assert.Throws <TaskExecutionFailedException>(() => runner.Execute(task));

                Assert.IsNotNull(exception.InnerException);
                Assert.IsInstanceOf <TaskExecutionLockNotAcquiredException>(exception.InnerException);

                Assert.IsNotNull(exception.InnerException.InnerException);
                Assert.IsInstanceOf <DistributedMutexStub.IsLockedException>(exception.InnerException.InnerException);
            }
        }
        public void Task_With_PreventConcurrentTaskExecutionAttribute_ReturnNullExceptionHandler_Verify_InteractsWithDistributedMutex()
        {
            var distributedMutex = new DistributedMutexStub();

            using (var context = ApplicationContext.Create(application => application
                                                           .ConfigureForUnitTest()
                                                           .Services(services => services
                                                                     .Advanced(advanced => advanced
                                                                               .Register <IRuntimeSettings>(kernel => new InMemoryRuntimeSettings()
                                                                                                            .Set("ConcurrentTaskExecution.PreventConcurrentTaskExecutionOnAllTasks", "false"))
                                                                               .Register <IDistributedMutex>(kernel => distributedMutex)))
                                                           .Tasks(tasks => tasks
                                                                  .Task <ReturnNullOnSyncExceptionTask>()
                                                                  .ConcurrentTaskExecution(concurrentTaskExecution => concurrentTaskExecution
                                                                                           .AddExceptionHandler <ReturnNullExceptionHandler>()))))
            {
                var runner  = context.Resolve <ITaskRunner>();
                var factory = context.Resolve <ITaskFactory>();

                // Create an existing lock based on the actual task
                distributedMutex.SimulateLockFromTask <ReturnNullOnSyncExceptionTask>();

                ITask task = factory.Get <ReturnNullOnSyncExceptionTask>();

                runner.Execute(task);
            }
        }
        public void RunSameTaskInParallel_Verify_OneTaskThrows()
        {
            var distributedMutex        = new DistributedMutexStub();
            var cancellationTokenSource = new CancellationTokenSource();
            var synchronizationContext  = new SynchronizationContext(cancellationTokenSource);

            using (var context = ApplicationContext.Create(application => application
                                                           .ConfigureForUnitTest()
                                                           .Services(services => services
                                                                     .Advanced(advanced => advanced
                                                                               .Register(kernel => synchronizationContext)
                                                                               .Register <IRuntimeSettings>(kernel => new InMemoryRuntimeSettings()
                                                                                                            .Set("ConcurrentTaskExecution.PreventConcurrentTaskExecutionOnAllTasks", "true"))
                                                                               .Register <IDistributedMutex>(kernel => distributedMutex)))
                                                           .Tasks(tasks => tasks
                                                                  .Task <SomeTask>())))
            {
                var runner  = context.Resolve <ITaskRunner>();
                var factory = context.Resolve <ITaskFactory>();

                var taskA = System.Threading.Tasks.Task.Factory.StartNew(() =>
                                                                         runner.Execute(factory.Get <SomeTask>()), cancellationTokenSource.Token);

                var taskB = System.Threading.Tasks.Task.Factory.StartNew(() =>
                                                                         runner.Execute(factory.Get <SomeTask>()), cancellationTokenSource.Token);

                cancellationTokenSource.CancelAfter(100);

                try
                {
                    System.Threading.Tasks.Task.WaitAll(taskA, taskB);
                }
                catch (AggregateException)
                {
                }

                var tasks       = new[] { taskA, taskB };
                var failedTasks = tasks.Where(x => x.Exception != null).ToArray();

                Assert.That(failedTasks.Length, Is.EqualTo(1));
                Assert.That(((Exception)failedTasks[0].Exception).AggregateMessages(), Does.Contain("Unable to acquire lock 'SomeTask'"));

                var completedTasks = tasks.Where(x => x.Status == TaskStatus.RanToCompletion).ToArray();

                Assert.That(completedTasks.Length, Is.EqualTo(1));
            }
        }