public void Test_One_To_Many_Execution_To_Failure()
        {
            // Arrange

            var switcher  = OperationExecutionStateSwitcherBuilder.Build();
            var aggregate = OperationExecutionAggregate.Start
                            (
                Guid.NewGuid(),
                "",
                new []
            {
                new TransactionOutputValueType("1", 1.0m),
                new TransactionOutputValueType("2", 2.0m),
            },
                "",
                false,
                "",
                "",
                OperationExecutionEndpointsConfiguration.OneToOne
                            );

            // Act / Assert

            Assert.Equal(OperationExecutionState.Started, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new ActiveTransactionIdGeneratedEvent
            {
                TransactionNumber = 1
            }));
            Assert.Equal(OperationExecutionState.ActiveTransactionIdGenerated, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new TransactionExecutionStartedEvent
            {
                TransactionNumber = 1
            }));
            Assert.Equal(OperationExecutionState.TransactionExecutionInProgress, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new TransactionExecutionFailedEvent
            {
                ErrorCode         = TransactionExecutionResult.UnknownError,
                TransactionNumber = 1
            }));
            Assert.Equal(OperationExecutionState.Failed, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new OperationExecutionFailedEvent()));
            Assert.Equal(OperationExecutionState.NotifiedAboutEnding, aggregate.State);
        }
        public void Test_Simple_Execution_To_Completion()
        {
            // Arrange

            var switcher  = OperationExecutionStateSwitcherBuilder.Build();
            var aggregate = OperationExecutionAggregate.Start
                            (
                Guid.NewGuid(),
                "",
                new [] { new TransactionOutputValueType("", 0) },
                "",
                false,
                "",
                "",
                OperationExecutionEndpointsConfiguration.OneToOne
                            );

            // Act / Assert

            Assert.Equal(OperationExecutionState.Started, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new ActiveTransactionIdGeneratedEvent
            {
                TransactionNumber = 1
            }));
            Assert.Equal(OperationExecutionState.ActiveTransactionIdGenerated, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new TransactionExecutionStartedEvent
            {
                TransactionNumber = 1
            }));
            Assert.Equal(OperationExecutionState.TransactionExecutionInProgress, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new TransactionExecutionCompletedEvent
            {
                TransactionNumber = 1
            }));
            Assert.Equal(OperationExecutionState.Completed, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new OperationExecutionCompletedEvent()));
            Assert.Equal(OperationExecutionState.NotifiedAboutEnding, aggregate.State);
        }
        protected override void Load(ContainerBuilder builder)
        {
            builder.Register(context => new AutofacDependencyResolver(context)).As <IDependencyResolver>().SingleInstance();

            builder.Register(c => new RetryDelayProvider(
                                 _settings.SourceAddressLockingRetryDelay,
                                 _settings.WaitForTransactionRetryDelay,
                                 _settings.NotEnoughBalanceRetryDelay,
                                 _settings.RebuildingConfirmationCheckRetryDelay))
            .AsSelf();

            builder.RegisterInstance(TransitionExecutionStateSwitcherBuilder.Build())
            .As <IStateSwitcher <TransactionExecutionAggregate> >();

            builder.RegisterInstance(OperationExecutionStateSwitcherBuilder.Build())
            .As <IStateSwitcher <OperationExecutionAggregate> >();

            // Sagas
            builder.RegisterType <TransactionExecutionSaga>();
            builder.RegisterType <OperationExecutionSaga>();

            // Interceptors
            builder.RegisterType <ErrorsCommandInterceptor>();
            builder.RegisterType <ErrorsEventInterceptor>();

            // Command handlers
            builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(t =>
                                                                                 t.Namespace == typeof(StartOperationExecutionCommandsHandler).Namespace ||
                                                                                 t.Namespace == typeof(StartTransactionExecutionCommandHandler).Namespace));

            //CQRS Message Cancellation
            Lykke.Cqrs.MessageCancellation.Configuration.ContainerBuilderExtensions.RegisterCqrsMessageCancellation(
                builder,
                (options) =>
            {
                #region Registry

                //Commands
                options.Value
                .MapMessageId <ClearActiveTransactionCommand>(x => x.OperationId.ToString())
                .MapMessageId <GenerateActiveTransactionIdCommand>(x => x.OperationId.ToString())
                .MapMessageId <NotifyOperationExecutionCompletedCommand>(x => x.OperationId.ToString())
                .MapMessageId <NotifyOperationExecutionFailedCommand>(x => x.OperationId.ToString())
                .MapMessageId <BroadcastTransactionCommand>(x => x.OperationId.ToString())
                .MapMessageId <BuildTransactionCommand>(x => x.OperationId.ToString())
                .MapMessageId <ClearBroadcastedTransactionCommand>(x => x.OperationId.ToString())
                .MapMessageId <LockSourceAddressCommand>(x => x.OperationId.ToString())
                .MapMessageId <ReleaseSourceAddressLockCommand>(x => x.OperationId.ToString())
                .MapMessageId <SignTransactionCommand>(x => x.OperationId.ToString())
                .MapMessageId <StartTransactionExecutionCommand>(x => x.OperationId.ToString())
                .MapMessageId <WaitForTransactionEndingCommand>(x => x.OperationId.ToString())
                .MapMessageId <StartOperationExecutionCommand>(x => x.OperationId.ToString())
                .MapMessageId <StartOneToManyOutputsExecutionCommand>(x => x.OperationId.ToString())

                //Events
                .MapMessageId <ActiveTransactionClearedEvent>(x => x.OperationId.ToString())
                .MapMessageId <ActiveTransactionIdGeneratedEvent>(x => x.OperationId.ToString())
                .MapMessageId <OperationExecutionStartedEvent>(x => x.OperationId.ToString())
                .MapMessageId <BroadcastTransactionCommand>(x => x.OperationId.ToString())
                .MapMessageId <SourceAddressLockedEvent>(x => x.OperationId.ToString())
                .MapMessageId <SourceAddressLockReleasedEvent>(x => x.OperationId.ToString())
                .MapMessageId <TransactionBroadcastedEvent>(x => x.OperationId.ToString())
                .MapMessageId <TransactionBuildingRejectedEvent>(x => x.OperationId.ToString())
                .MapMessageId <TransactionBuiltEvent>(x => x.OperationId.ToString())
                .MapMessageId <TransactionExecutionCompletedEvent>(x => x.OperationId.ToString())
                .MapMessageId <TransactionExecutionFailedEvent>(x => x.OperationId.ToString())
                .MapMessageId <TransactionExecutionRepeatRequestedEvent>(x => x.OperationId.ToString())
                .MapMessageId <TransactionExecutionStartedEvent>(x => x.OperationId.ToString())
                .MapMessageId <TransactionReBuildingRejectedEvent>(x => x.OperationId.ToString())
                .MapMessageId <TransactionSignedEvent>(x => x.OperationId.ToString())
                .MapMessageId <OneToManyOperationExecutionCompletedEvent>(x => x.OperationId.ToString())
                .MapMessageId <OperationExecutionCompletedEvent>(x => x.OperationId.ToString())
                .MapMessageId <OperationExecutionFailedEvent>(x => x.OperationId.ToString())
                .MapMessageId <BroadcastedTransactionClearedEvent>(x => x.OperationId.ToString());

                #endregion
            });

            builder.Register(CreateEngine)
            .As <ICqrsEngine>()
            .SingleInstance()
            .AutoActivate();
        }
        public void Test_Execution_With_Double_Transaction_Repeat_To_Failure()
        {
            // Arrange

            var switcher  = OperationExecutionStateSwitcherBuilder.Build();
            var aggregate = OperationExecutionAggregate.Start
                            (
                Guid.NewGuid(),
                "",
                new [] { new TransactionOutputValueType("", 0) },
                "",
                false,
                "",
                "",
                OperationExecutionEndpointsConfiguration.OneToOne
                            );

            // Act / Assert

            Assert.Equal(OperationExecutionState.Started, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new ActiveTransactionIdGeneratedEvent
            {
                TransactionNumber = 1
            }));
            Assert.Equal(OperationExecutionState.ActiveTransactionIdGenerated, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new TransactionExecutionStartedEvent
            {
                TransactionNumber = 1
            }));
            Assert.Equal(OperationExecutionState.TransactionExecutionInProgress, aggregate.State);

            foreach (var transactionNumber in Enumerable.Range(2, 2))
            {
                Assert.True(switcher.Switch(aggregate, new TransactionExecutionRepeatRequestedEvent
                {
                    ErrorCode         = TransactionExecutionResult.RebuildingIsRequired,
                    TransactionNumber = transactionNumber - 1
                }));
                Assert.Equal(OperationExecutionState.TransactionExecutionRepeatRequested, aggregate.State);

                Assert.True(switcher.Switch(aggregate, new ActiveTransactionClearedEvent
                {
                    TransactionNumber = transactionNumber - 1
                }));
                Assert.Equal(OperationExecutionState.ActiveTransactionCleared, aggregate.State);

                Assert.True(switcher.Switch(aggregate, new ActiveTransactionIdGeneratedEvent
                {
                    TransactionNumber = transactionNumber
                }));
                Assert.Equal(OperationExecutionState.ActiveTransactionIdGenerated, aggregate.State);

                Assert.True(switcher.Switch(aggregate, new TransactionExecutionStartedEvent
                {
                    TransactionNumber = transactionNumber
                }));
                Assert.Equal(OperationExecutionState.TransactionExecutionInProgress, aggregate.State);
            }

            Assert.True(switcher.Switch(aggregate, new TransactionExecutionFailedEvent
            {
                ErrorCode         = TransactionExecutionResult.UnknownError,
                TransactionNumber = 3
            }));
            Assert.Equal(OperationExecutionState.Failed, aggregate.State);

            Assert.True(switcher.Switch(aggregate, new OperationExecutionFailedEvent()));
            Assert.Equal(OperationExecutionState.NotifiedAboutEnding, aggregate.State);
        }