/// <summary>
        ///     Publishes results to listeners
        /// </summary>
        /// <param name="transactionResult"></param>
        /// <param name="mode"></param>
        /// <param name="guid"></param>
        public override void ResultHandler(ITransactionResult transactionResult, TransactionQueueMode mode, Guid guid)
        {
            var stringBuilder       = new StringBuilder();
            var receiveData         = (ReceiveData)transactionResult.Result;
            var confirmationNumber  = receiveData?.CompleteSessionResponse?.Payload?.ReferenceNumber;
            var formattedStringList = receiveData.ToFormattedString(new List <string>());
            var timeSpan            = (receiveData.BeginTimeStamp.HasValue && receiveData.EndTimeStamp.HasValue) ? receiveData.EndTimeStamp.Value - receiveData.BeginTimeStamp.Value : new TimeSpan();

            stringBuilder.AppendLine($"==========BEGIN {Display.ToUpper()}==========");
            stringBuilder.AppendLine($"{confirmationNumber}");
            stringBuilder.AppendLine($"{DateTime.Now}");
            stringBuilder.AppendLine((receiveData.Errors.Count == 0) ? "COMPLETED SUCCESSFULLY" : "COMPLETED WITH ERRORS");
            stringBuilder.AppendLine($"FINISHED IN {timeSpan.Minutes}MIN {timeSpan.Seconds}SEC {timeSpan.Milliseconds}MS");
            stringBuilder.AppendLine("==========\n");

            foreach (var formattedString in formattedStringList)
            {
                stringBuilder.Append(formattedString);
            }

            stringBuilder.AppendLine($"==========END {Display.ToUpper()}==========");

            _messageBus.Publish(new TransactionResultsReceivedMessage(mode, guid)
            {
                Result          = transactionResult,
                DetailsString   = stringBuilder.ToString(),
                ReferenceNumber = confirmationNumber
            });
        }
        public Receipt(Parcel parcelable)
        {
            Type receipType = JsonConvert.DeserializeObject<Type>(parcelable.ReadString());

            var receiptString = parcelable.ReadString();
            receipt = JsonConvert.DeserializeObject(receiptString, receipType) as ITransactionResult;
        }
Exemple #3
0
        public async Task WhenAddStepAfterTransactionRun_ShouldThrowException()
        {
            // Arrange
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name = "test transaction";
            });

            target.Add(new TransactionStep <string, object>()
            {
                Id         = "1",
                StepAction = (data, info) => { }
            });
            ITransactionResult <object> result = await target.Run(settings =>
            {
                settings.Mode = RunMode.Run;
            });

            // Act
            target.Add(new TransactionStep <string, object>()
            {
                Id         = "1",
                StepAction = (data, info) => { }
            });

            // Assert
            Assert.Fail("An exception is expected.");
        }
Exemple #4
0
        public void WhenInsertStepsBeforeIdWithComparer_ShouldInsertProperly()
        {
            List <string> runStepActions         = new List <string>();
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name = "test transaction";
            });

            for (int i = 0; i < 7; ++i)
            {
                string index = i == 3 ? i.ToString() + " " : i.ToString();
                target.Add(new TransactionStep <string, object>()
                {
                    Id         = index,
                    StepAction = (data, info) => runStepActions.Add(index)
                });
            }

            Mock <IEqualityComparer <string> > comparer = new Mock <IEqualityComparer <string> >();

            comparer.Setup(x => x.Equals(It.IsAny <string>(), It.IsAny <string>()))
            .Returns((string a, string b) => a.Trim() == b.Trim());

            // Act
            target.InsertBefore("3", new TransactionStep <string, object>[] {
                new TransactionStep <string, object>()
                {
                    Id         = "inserted 1",
                    StepAction = (data, info) => runStepActions.Add("inserted 1")
                },
                new TransactionStep <string, object>()
                {
                    Id         = "inserted 2",
                    StepAction = (data, info) => runStepActions.Add("inserted 2")
                }
            },
                                comparer.Object);

            ITransactionResult <object> result = null;

            target.Run(settings =>
            {
                settings.TransactionResultCallback = x => result = x;
            });

            // Assert
            runStepActions.ShouldAllBeEquivalentTo(new string[]
            {
                "0",
                "1",
                "2",
                "inserted 1",
                "inserted 2",
                "3 ",
                "4",
                "5",
                "6"
            });
        }
Exemple #5
0
        public void WhenInsertStepsAfterIdWithoutComparer_ShouldInsertProperly()
        {
            List <string> runStepActions         = new List <string>();
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name = "test transaction";
            });

            for (int i = 0; i < 7; ++i)
            {
                string index = i.ToString();
                target.Add(new TransactionStep <string, object>()
                {
                    Id         = index,
                    StepAction = (data, info) => runStepActions.Add(index)
                });
            }

            // Act
            target.InsertAfter("5", new TransactionStep <string, object>[] {
                new TransactionStep <string, object>()
                {
                    Id         = "inserted 1",
                    StepAction = (data, info) => runStepActions.Add("inserted 1")
                },
                new TransactionStep <string, object>()
                {
                    Id         = "inserted 2",
                    StepAction = (data, info) => runStepActions.Add("inserted 2")
                },
                new TransactionStep <string, object>()
                {
                    Id         = "inserted 3",
                    StepAction = (data, info) => runStepActions.Add("inserted 3")
                }
            });

            ITransactionResult <object> result = null;

            target.Run(settings =>
            {
                settings.TransactionResultCallback = x => result = x;
            });

            // Assert
            runStepActions.ShouldAllBeEquivalentTo(new string[]
            {
                "0",
                "1",
                "2",
                "3",
                "4",
                "5",
                "inserted 1",
                "inserted 2",
                "inserted 3",
                "6"
            });
        }
 protected internal JsonResult ClientSideTransactionResult(ITransactionResult result, JsonRequestBehavior behavior)
 {
     ClientSide.Models.ClientSideTransactionResult transactionResult = ClientSide.Models.ClientSideTransactionResult.fromTransactionResult(result);
     return(new JsonResult()
     {
         Data = transactionResult, JsonRequestBehavior = behavior
     });
 }
            static void HandleCancelled(object sender, ITransactionResult e)
            {
                if (e != null && e is TransactionBase)
                {
                    TransactionBase tb = ((TransactionBase)e);//e as TransactionBase;

                    tb.TransactionCompleted(sender, e);

                    tb = null;
                }
            }
            static void HandleWrite(object sender, ITransactionResult e)
            {
                if (e != null && e is TransactionBase)
                {
                    TransactionBase tb = ((TransactionBase)e);

                    tb.TransactionOffset += tb.LastTransactionAmount;

                    tb = null;
                }
            }
 public static ClientSideTransactionResult fromTransactionResult(ITransactionResult transactionResult)
 {
     ClientSideTransactionResult t = new ClientSideTransactionResult();
     t.Success = transactionResult.Success;
     t.Data = transactionResult.Data;
     if (transactionResult.Error != null)
     {
         t.Error = transactionResult.Error.Message;
     }
     t.NumEffected = transactionResult.NumEffected;
     return t;
 }
        public static ClientSideTransactionResult fromTransactionResult(ITransactionResult transactionResult)
        {
            ClientSideTransactionResult t = new ClientSideTransactionResult();

            t.Success = transactionResult.Success;
            t.Data    = transactionResult.Data;
            if (transactionResult.Error != null)
            {
                t.Error = transactionResult.Error.Message;
            }
            t.NumEffected = transactionResult.NumEffected;
            return(t);
        }
            static void HandleCompleted(object sender, ITransactionResult e)
            {
                if (e != null && e is TransactionBase)
                {
                    TransactionBase tb = e as TransactionBase;

                    tb.IsTransactionDone = tb.ShouldDispose = true;

                    tb.Dispose();

                    tb = null;
                }
            }
Exemple #12
0
        public async Task WhenInsertStepsAtIndex_ShouldInsertProperly()
        {
            List <string> runStepActions         = new List <string>();
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name = "test transaction";
            });

            for (int i = 0; i < 7; ++i)
            {
                string index = i.ToString();
                target.Add(new TransactionStep <string, object>()
                {
                    Id         = index,
                    StepAction = (data, info) => runStepActions.Add(index)
                });
            }

            // Act
            target.InsertAtIndex(3, new TransactionStep <string, object>[] { new TransactionStep <string, object>()
                                                                             {
                                                                                 Id         = "inserted 1",
                                                                                 StepAction = (data, info) => runStepActions.Add("inserted 1")
                                                                             },
                                                                             new TransactionStep <string, object>()
                                                                             {
                                                                                 Id         = "inserted 2",
                                                                                 StepAction = (data, info) => runStepActions.Add("inserted 2")
                                                                             } });

            ITransactionResult <object> result = await target.Run(settings => { });

            // Assert
            runStepActions.ShouldAllBeEquivalentTo(new string[]
            {
                "0",
                "1",
                "2",
                "inserted 1",
                "inserted 2",
                "3",
                "4",
                "5",
                "6"
            });
        }
        /// <summary>
        /// Ends the session.
        /// </summary>
        /// <param name="result">The transaction result.</param>
        public void End(ITransactionResult <TData> result)
        {
            if (this.Ended)
            {
                return;
            }

            this.Ended  = true;
            this.result = result;
            IExecutor callbackExecutor = this.RunSettings.TransactionResultCallbackExecutor;

            if (callbackExecutor != null &&
                callbackExecutor.ShouldRun)
            {
#if NET35 || NOASYNC
                callbackExecutor.Run(() =>
#else
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
                callbackExecutor.Run(async() =>
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
#endif
                {
                    this.RunSettings.TransactionResultCallback?.Invoke(this.result);
#if !NET35 && !NOASYNC
                    this.waitForResultSemaphor.Release();
#endif
                });
            }
            else
            {
                this.RunSettings.TransactionResultCallback?.Invoke(this.result);
#if !NET35 && !NOASYNC
                this.waitForResultSemaphor.Release();
#endif
            }
        }
Exemple #14
0
        public async Task WhenCancellTransaction_ShouldCancelProperly()
        {
            // Arrange
            object        transactionData        = new object();
            List <string> runStepActions         = new List <string>();
            List <string> runUndoActions         = new List <string>();
            List <string> runPostActions         = new List <string>();
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name = "test transaction";
            });

            for (int i = 0; i < 5; ++i)
            {
                string index = i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index
                };

                if (i % 3 == 0)
                {
                    step.AsyncStepAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);

                        if (index == "3")
                        {
                            info.Cancel();
                        }

                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.StepAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);
                    };
                }

                if (i % 4 == 0)
                {
                    step.AsyncUndoAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.UndoAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                    };
                }

                if (i % 2 == 0)
                {
                    step.AsyncPostAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        runPostActions.Add(index);
                        info.CurrentStepId.Should().Be(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.PostAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        runPostActions.Add(index);
                        info.CurrentStepId.Should().Be(index);
                    };
                }

                target.Add(step);
            }
            ITransactionResult <object> transactionCallbackResult = null;

            /*
             * 0:
             * 1:
             * 2:
             * 3: cancel
             * 4:
             */

            // Act
            ITransactionResult <object> result = await target.Run(settings =>
            {
                settings.Data = transactionData;
                settings.Mode = RunMode.Run;
                settings.TransactionResultCallback = callbackResult => transactionCallbackResult = callbackResult;
            });

            // Assert
            result.Should().BeSameAs(transactionCallbackResult);
            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[0]);
            result.Recovered.Should().BeFalse();
            result.Result.Should().Be(ResultType.Cancelled);
            runStepActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[] { "3", "2", "1", "0" });
            runPostActions.ShouldAllBeEquivalentTo(new string[0]);
        }
Exemple #15
0
 public Receipt(ITransactionResult receipt)
 {
     this.receipt = receipt;
 }
Exemple #16
0
 /// <summary>
 ///     Implement this to handle the results of the transaction
 /// </summary>
 /// <param name="transactionResult"></param>
 /// <param name="mode"></param>
 /// <param name="guid"></param>
 public abstract void ResultHandler(ITransactionResult transactionResult, TransactionQueueMode mode, Guid guid);
        public void WhenRunTransactionWithStepExecutors_ShouldRunAllStepsProperly()
        {
            // Arrange
            object        transactionData                = new object();
            List <string> runStepActions                 = new List <string>();
            List <string> runUndoActions                 = new List <string>();
            List <string> runPostActions                 = new List <string>();
            List <int>    stepActionThreadId             = new List <int>();
            List <int>    postActionThreadId             = new List <int>();
            int           transactionCallbackThreadId    = 0;
            Dictionary <int, TestExecutor> stepExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 2, null },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 5, null },
                { 6, null }
            };
            Dictionary <int, TestExecutor> postExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, null },
                { 2, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, null },
                { 5, null },
                { 6, null }
            };
            int transactionRunThreadId           = Thread.CurrentThread.ManagedThreadId;
            int step1StepActionThreadId          = stepExecutors[1].ThreadId;
            int step2PostActionThreadId          = postExecutors[2].ThreadId;
            int step3StepActionThreadId          = stepExecutors[3].ThreadId;
            int step3PostActionThreadId          = postExecutors[3].ThreadId;
            int step4StepActionThreadId          = stepExecutors[4].ThreadId;
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name = "test transaction";
            });

            for (int i = 0; i < 7; ++i)
            {
                string index = i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index,
                    StepActionExecutor = stepExecutors[i] == null
                                           ? null
                                           : stepExecutors[i],
                    PostActionExecutor = postExecutors[i] == null
                                           ? null
                                           : postExecutors[i]
                };

                step.StepAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runStepActions.Add(index);
                    stepActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                };

                step.UndoAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runUndoActions.Add(index);
                };

                step.PostAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    runPostActions.Add(index);
                    postActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                    info.CurrentStepId.Should().Be(index);
                };

                target.Add(step);
            }
            ITransactionResult <object> result = null;

            /*
             * 0:
             * 1: executor for other thread (step action)
             * 2: executor for other thread (post action)
             * 3: executor for other thread (step action), executor for other thread (post action)
             * 4: executor for other thread (step action)
             * 5:
             * 6:
             */

            // Act
            using (ManualResetEvent transactionEndResetEvent = new ManualResetEvent(false))
            {
                target.Run(settings =>
                {
                    settings.Data = transactionData;
                    settings.Mode = RunMode.Run;
                    settings.TransactionResultCallback = callbackResult =>
                    {
                        transactionCallbackThreadId = Thread.CurrentThread.ManagedThreadId;
                        result = callbackResult;
                        transactionEndResetEvent.Set();
                    };
                });
                transactionEndResetEvent.WaitOne();
            }

            // Assert
            foreach (TestExecutor executor in stepExecutors.Values.Concat(postExecutors.Values).Where(x => x != null))
            {
                executor.Dispose();
            }

            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[0]);
            result.Recovered.Should().BeFalse();
            result.Result.Should().Be(ResultType.Success);

            foreach (TestExecutor executor in stepExecutors.Values.Concat(postExecutors.Values).Where(x => x != null))
            {
                executor.Verify(Times.Once, Times.Once);
            }

            runStepActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4", "5", "6" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[0]);
            runPostActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4", "5", "6" });
            stepActionThreadId.ShouldAllBeEquivalentTo(new int[]
            {
                /*step 0*/ transactionRunThreadId,
                /*step 1*/ step1StepActionThreadId,
                /*step 2*/ step1StepActionThreadId,
                /*step 3*/ step3StepActionThreadId,
                /*step 4*/ step4StepActionThreadId,
                /*step 5*/ step4StepActionThreadId,
                /*step 6*/ step4StepActionThreadId
            });
            postActionThreadId.ShouldAllBeEquivalentTo(new int[]
            {
                /*step 0*/ step4StepActionThreadId,
                /*step 1*/ step4StepActionThreadId,
                /*step 2*/ step2PostActionThreadId,
                /*step 3*/ step3PostActionThreadId,
                /*step 4*/ step3PostActionThreadId,
                /*step 5*/ step3PostActionThreadId,
                /*step 6*/ step3PostActionThreadId
            });
            transactionCallbackThreadId.Should().Be(step3PostActionThreadId);
        }
Exemple #18
0
 public JudoReceipt(ITransactionResult receipt)
 {
     this.receipt = receipt;
 }
        public void WhenRunRecoveredTransactionWithCurrentStepAsFirstStepWithExecutor_ShouldProcessStepsProperly()
        {
            // Arrange
            object        transactionData                = new object();
            List <string> runStepActions                 = new List <string>();
            List <string> runUndoActions                 = new List <string>();
            List <string> runPostActions                 = new List <string>();
            List <int>    stepActionThreadId             = new List <int>();
            List <int>    undoActionThreadId             = new List <int>();
            List <int>    postActionThreadId             = new List <int>();
            int           transactionCallbackThreadId    = 0;
            int           transactionRunThreadId         = Thread.CurrentThread.ManagedThreadId;
            Dictionary <int, TestExecutor> stepExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, null },
                { 2, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 5, null },
                { 6, null }
            };
            Dictionary <int, TestExecutor> undoExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 1, null },
                { 2, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 3, null },
                { 4, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 5, null },
                { 6, null }
            };
            Dictionary <int, TestExecutor> postExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, null },
                { 2, null },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, null },
                { 5, null },
                { 6, null }
            };
            TestExecutor callBackExecutor = new TestExecutor()
            {
                ShouldRun = true
            };
            Mock <ITransactionStorage <object> > storageMock   = new Mock <ITransactionStorage <object> >();
            Mock <ITransactionData <object> >    recoveredData = new Mock <ITransactionData <object> >();

            recoveredData.SetupGet(x => x.CurrentStepIndex)
            .Returns(0);
            recoveredData.SetupGet(x => x.Data)
            .Returns(transactionData);
            recoveredData.SetupGet(x => x.SessionId)
            .Returns(Guid.NewGuid());
            recoveredData.SetupGet(x => x.StartTimestamp)
            .Returns(DateTime.Now);
            storageMock.Setup(x => x.RecoverTransaction())
            .Returns(recoveredData.Object);
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name      = "test transaction";
                options.TransactionStorageCreator = context => storageMock.Object;
            });

            for (int i = 0; i < 7; ++i)
            {
                string index = i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index,
                    StepActionExecutor = stepExecutors[i],
                    UndoActionExecutor = undoExecutors[i],
                    PostActionExecutor = postExecutors[i],
                    Settings           = StepSettings.None
                };

                step.StepAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runStepActions.Add(index);
                    stepActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                };

                step.UndoAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runUndoActions.Add(index);
                    undoActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                };

                step.PostAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    runPostActions.Add(index);
                    postActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                    info.CurrentStepId.Should().Be(index);
                };

                target.Add(step);
            }
            ITransactionResult <object> result = null;

            /*
             * 0: recovered step, executor for other thread (undo action)
             * 1:
             * 2: executor for other thread (step action), executor for other thread (undo action)
             * 3: executor for other thread (step action), executor for other thread (post action)
             * 4: executor for other thread (step action), executor for other thread (undo action)
             * 5:
             * 6:
             */

            // Act
            using (ManualResetEvent transactionEndResetEvent = new ManualResetEvent(false))
            {
                target.Run(settings =>
                {
                    settings.Data = transactionData;
                    settings.Mode = RunMode.RecoverAndUndoAndRun;
                    settings.TransactionResultCallback = callbackResult =>
                    {
                        transactionCallbackThreadId = Thread.CurrentThread.ManagedThreadId;
                        result = callbackResult;
                        transactionEndResetEvent.Set();
                    };
                    settings.TransactionResultCallbackExecutor = callBackExecutor;
                });
                transactionEndResetEvent.WaitOne();
            }

            // Assert
            callBackExecutor.Dispose();

            foreach (TestExecutor executor in stepExecutors.Values.Concat(postExecutors.Values).Where(x => x != null))
            {
                executor.Dispose();
            }

            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[0]);
            result.Recovered.Should().BeTrue();
            result.Result.Should().Be(ResultType.Success);
            callBackExecutor.Verify(Times.Once, Times.Once);

            foreach (TestExecutor executor in stepExecutors.Values.Concat(postExecutors.Values).Where(x => x != null))
            {
                executor.Verify(Times.Once, Times.Once);
            }

            runStepActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4", "5", "6" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[] { "0" });
            runPostActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4", "5", "6" });
            stepActionThreadId.ShouldAllBeEquivalentTo(new int[]
            {
                /*step 0*/ undoExecutors[0].ThreadId,
                /*step 1*/ undoExecutors[0].ThreadId,
                /*step 2*/ stepExecutors[2].ThreadId,
                /*step 3*/ stepExecutors[3].ThreadId,
                /*step 4*/ stepExecutors[4].ThreadId,
                /*step 5*/ stepExecutors[4].ThreadId,
                /*step 6*/ stepExecutors[4].ThreadId
            });
            undoActionThreadId.ShouldAllBeEquivalentTo(new int[] { undoExecutors[0].ThreadId });
            postActionThreadId.ShouldAllBeEquivalentTo(new int[]
            {
                /*step 0*/ stepExecutors[4].ThreadId,
                /*step 1*/ stepExecutors[4].ThreadId,
                /*step 2*/ stepExecutors[4].ThreadId,
                /*step 3*/ postExecutors[3].ThreadId,
                /*step 4*/ postExecutors[3].ThreadId,
                /*step 5*/ postExecutors[3].ThreadId,
                /*step 6*/ postExecutors[3].ThreadId
            });
            transactionCallbackThreadId.Should().Be(callBackExecutor.ThreadId);
            storageMock.AssertStorageOperations(new AssertStorageOperationsContext <string, object>()
            {
                SessionStartedTimes = Times.Never(),
                TransactionData     = transactionData,
                Transaction         = target,
                ExpectedStepsOrder  = runStepActions,
                ExpectedUndoOrder   = runUndoActions
            });
        }
        public async Task WhenRunTransaction_ShouldRunAllStepsProperly()
        {
            // Arrange
            object        transactionData = new object();
            List <string> runStepActions  = new List <string>();
            List <string> runUndoActions  = new List <string>();
            List <string> runPostActions  = new List <string>();
            Mock <ITransactionStorage <object> > storageMock = new Mock <ITransactionStorage <object> >();
            ITransaction <string, object>        target      = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name      = "test transaction";
                options.TransactionStorageCreator = partContext => storageMock.Object;
            });

            for (int i = 0; i < 5; ++i)
            {
                string index = i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index
                };

                if (i % 3 == 0)
                {
                    step.AsyncStepAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.StepAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);
                    };
                }

                if (i % 4 == 0)
                {
                    step.AsyncUndoAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.UndoAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                    };
                }

                if (i % 2 == 0)
                {
                    step.AsyncPostAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        runPostActions.Add(index);
                        info.CurrentStepId.Should().Be(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.PostAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runPostActions.Add(index);
                    };
                }

                target.Add(step);
            }
            ITransactionResult <object> transactionCallbackResult = null;

            /*
             * 0:
             * 1:
             * 2:
             * 3:
             * 4:
             */

            // Act
            ITransactionResult <object> result = await target.Run(settings =>
            {
                settings.Data = transactionData;
                settings.Mode = RunMode.Run;
                settings.TransactionResultCallback = callbackResult => transactionCallbackResult = callbackResult;
            });

            // Assert
            result.Should().BeSameAs(transactionCallbackResult);
            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[0]);
            result.Recovered.Should().BeFalse();
            result.Result.Should().Be(ResultType.Success);
            runStepActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[0]);
            runPostActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4" });
            storageMock.AssertStorageOperations(new AssertStorageOperationsContext <string, object>()
            {
                TransactionData    = transactionData,
                Transaction        = target,
                ExpectedStepsOrder = runStepActions,
                ExpectedUndoOrder  = runUndoActions
            });
        }
Exemple #21
0
        public void WhenRunTransactionAndErrorOccurredStepAction_ShouldRunUndoSteps()
        {
            // Arrange
            object        transactionData = new object();
            List <string> runStepActions  = new List <string>();
            List <string> runUndoActions  = new List <string>();
            List <string> runPostActions  = new List <string>();
            Exception     testException   = new Exception("test exception");
            Mock <ITransactionStorage <object> > storageMock = new Mock <ITransactionStorage <object> >();
            ITransaction <string, object>        target      = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name      = "test transaction";
                options.TransactionStorageCreator = partContext => storageMock.Object;
            });

            for (int i = 0; i < 6; ++i)
            {
                string index = i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index
                };

                step.StepAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runStepActions.Add(index);

                    if (index == "3")
                    {
                        throw testException;
                    }
                };

                step.UndoAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runUndoActions.Add(index);
                };

                step.PostAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    runPostActions.Add(index);
                    info.CurrentStepId.Should().Be(index);
                };

                target.Add(step);
            }
            ITransactionResult <object> result = null;

            /*
             * 0:
             * 1:
             * 2:
             * 3: error
             * 4:
             * 5:
             */

            // Act
            target.Run(settings =>
            {
                settings.Data = transactionData;
                settings.Mode = RunMode.Run;
                settings.TransactionResultCallback = callbackResult => result = callbackResult;
            });

            // Assert
            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[] { testException });
            result.Recovered.Should().BeFalse();
            result.Result.Should().Be(ResultType.Failed);
            runStepActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[] { "3", "2", "1", "0" });
            runPostActions.ShouldAllBeEquivalentTo(new string[0]);
            storageMock.AssertStorageOperations(new AssertStorageOperationsContext <string, object>()
            {
                TransactionData    = transactionData,
                Transaction        = target,
                ExpectedStepsOrder = runStepActions,
                ExpectedUndoOrder  = runUndoActions
            });
        }
 protected internal JsonResult ClientSideTransactionResult(ITransactionResult result, JsonRequestBehavior behavior)
 {
     ClientSide.Models.ClientSideTransactionResult transactionResult = ClientSide.Models.ClientSideTransactionResult.fromTransactionResult(result);
     return new JsonResult() { Data = transactionResult, JsonRequestBehavior = behavior };
 }
 static void HandleRead(object sender, ITransactionResult e)
 {
     //if (e == null && false == sct is TransactionBase) return;
 }
        public async Task WhenRunRecoveredTransactionWittCurrentStepWithUndoOnRecoverSettingAndPreviousStepsWithUndoOnRecover_ShouldUndoTheSteps()
        {
            // Arrange
            object        transactionData = new object();
            List <string> runStepActions  = new List <string>();
            List <string> runUndoActions  = new List <string>();
            List <string> runPostActions  = new List <string>();
            Mock <ITransactionStorage <object> > storageMock   = new Mock <ITransactionStorage <object> >();
            Mock <ITransactionData <object> >    recoveredData = new Mock <ITransactionData <object> >();

            recoveredData.SetupGet(x => x.CurrentStepIndex)
            .Returns(3);
            recoveredData.SetupGet(x => x.Data)
            .Returns(transactionData);
            recoveredData.SetupGet(x => x.SessionId)
            .Returns(Guid.NewGuid());
            recoveredData.SetupGet(x => x.StartTimestamp)
            .Returns(DateTime.Now);
            storageMock.Setup(x => x.RecoverTransaction())
            .Returns(Task.FromResult <ITransactionData <object> >(recoveredData.Object));
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name      = "test transaction";
                options.TransactionStorageCreator = context => storageMock.Object;
            });

            for (int i = 0; i < 6; ++i)
            {
                string index = i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id       = index,
                    Settings = i == 1 || i == 2 || i == 3 ? StepSettings.UndoOnRecover : StepSettings.None
                };

                if (i % 3 == 0)
                {
                    step.AsyncStepAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.StepAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);
                    };
                }

                if (i % 2 == 0)
                {
                    step.AsyncUndoAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.UndoAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                    };
                }

                if (i % 3 == 0)
                {
                    step.AsyncPostAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        runPostActions.Add(index);
                        info.CurrentStepId.Should().Be(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.PostAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        runPostActions.Add(index);
                        info.CurrentStepId.Should().Be(index);
                    };
                }

                target.Add(step);
            }
            ITransactionResult <object> transactionCallbackResult = null;

            /*
             * 0:
             * 1: undo on recover
             * 2: undo on recover
             * 3: recovered step, undo on recover
             * 4:
             * 5:
             */

            // Act
            ITransactionResult <object> result = await target.Run(settings =>
            {
                settings.Data = transactionData;
                settings.Mode = RunMode.RecoverAndContinue;
                settings.TransactionResultCallback = callbackResult => transactionCallbackResult = callbackResult;
            });

            // Assert
            result.Should().BeSameAs(transactionCallbackResult);
            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[0]);
            result.Recovered.Should().BeTrue();
            result.Result.Should().Be(ResultType.Success);
            runStepActions.ShouldAllBeEquivalentTo(new string[] { "1", "2", "3", "4", "5" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[] { "3", "2", "1" });
            runPostActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4", "5" });
            storageMock.AssertStorageOperations(new AssertStorageOperationsContext <string, object>()
            {
                SessionStartedTimes = Times.Never(),
                TransactionData     = transactionData,
                Transaction         = target,
                ExpectedStepsOrder  = runStepActions,
                ExpectedUndoOrder   = runUndoActions
            });
        }
Exemple #25
0
        public void WhenGoForwardWithoutComparer_ShouldMoveToStepProperly()
        {
            // Arrange
            object        transactionData = new object();
            List <string> runStepActions  = new List <string>();
            List <string> runUndoActions  = new List <string>();
            List <string> runPostActions  = new List <string>();
            Mock <ITransactionStorage <object> > storageMock = new Mock <ITransactionStorage <object> >();
            ITransaction <string, object>        target      = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name      = "test transaction";
                options.TransactionStorageCreator = partContext => storageMock.Object;
            });

            for (int i = 0; i < 5; ++i)
            {
                string index = i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index
                };

                step.StepAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);

                    if (info.CurrentStepId == "1")
                    {
                        info.GoForward("4");
                    }

                    runStepActions.Add(index);
                };

                step.UndoAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runUndoActions.Add(index);
                };

                step.PostAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runPostActions.Add(index);
                };

                target.Add(step);
            }

            /*
             * 0:
             * 1: go forward to step 4
             * 2:
             * 3:
             * 4:
             */

            // Act
            ITransactionResult <object> result = null;

            target.Run(settings =>
            {
                settings.Data = transactionData;
                settings.Mode = RunMode.Run;
                settings.TransactionResultCallback = callbackResult => result = callbackResult;
            });

            // Assert
            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[0]);
            result.Recovered.Should().BeFalse();
            result.Result.Should().Be(ResultType.Success);
            runStepActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "4" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[0]);
            runPostActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4" });
            storageMock.AssertStorageOperations(new AssertStorageOperationsContext <string, object>()
            {
                TransactionData    = transactionData,
                Transaction        = target,
                ExpectedStepsOrder = runStepActions,
                ExpectedUndoOrder  = runUndoActions
            });
        }
Exemple #26
0
        public void WhenGoForwardWithComparerWithCompareFailure_ShouldFailTransaction()
        {
            // Arrange
            object        transactionData = new object();
            List <string> runStepActions  = new List <string>();
            List <string> runUndoActions  = new List <string>();
            List <string> runPostActions  = new List <string>();
            Mock <ITransactionStorage <object> > storageMock = new Mock <ITransactionStorage <object> >();
            ITransaction <string, object>        target      = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name      = "test transaction";
                options.TransactionStorageCreator = partContext => storageMock.Object;
            });

            for (int i = 0; i < 5; ++i)
            {
                string index = "A" + i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index
                };

                step.StepAction = (data, info) =>
                {
                    if (info.CurrentStepId == "A1")
                    {
                        info.GoForward("a4", StringComparer.Ordinal);
                    }

                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runStepActions.Add(index);
                };

                step.UndoAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runUndoActions.Add(index);
                };

                step.PostAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runPostActions.Add(index);
                };

                target.Add(step);
            }

            /*
             * 0:
             * 1: go forward to step 4
             * 2:
             * 3:
             * 4:
             */

            // Act
            ITransactionResult <object> result = null;

            target.Run(settings =>
            {
                settings.Data = transactionData;
                settings.Mode = RunMode.Run;
                settings.TransactionResultCallback = callbackResult => result = callbackResult;
            });

            // Assert
            result.Data.Should().BeSameAs(transactionData);
            result.Errors.Count().Should().Be(1);
            result.Errors.First().Message.Contains("Could not move forward to a step with id 'a4' as the step does not exist.").Should().BeTrue();
            result.Recovered.Should().BeFalse();
            result.Result.Should().Be(ResultType.Failed);
            runStepActions.ShouldAllBeEquivalentTo(new string[] { "A0", "A1" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[] { "A1", "A0" });
            runPostActions.ShouldAllBeEquivalentTo(new string[0]);
            storageMock.AssertStorageOperations(new AssertStorageOperationsContext <string, object>()
            {
                TransactionData    = transactionData,
                Transaction        = target,
                ExpectedStepsOrder = runStepActions,
                ExpectedUndoOrder  = runUndoActions
            });
        }
        public async Task WhenRunTransactionWithStepExecutorsWithSameExecutorForAllActions_ShouldRunAllStepsProperly()
        {
            // Arrange
            object        transactionData                = new object();
            List <string> runStepActions                 = new List <string>();
            List <string> runUndoActions                 = new List <string>();
            List <string> runPostActions                 = new List <string>();
            List <int>    stepActionThreadId             = new List <int>();
            List <int>    postActionThreadId             = new List <int>();
            int           transactionCallbackThreadId    = 0;
            Dictionary <int, TestExecutor> stepExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 2, null },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 5, null },
                { 6, null }
            };
            Dictionary <int, TestExecutor> postExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, null },
                { 2, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, null },
                { 5, null },
                { 6, null }
            };
            int transactionRunThreadId           = Thread.CurrentThread.ManagedThreadId;
            int step1StepActionThreadId          = stepExecutors[1].ThreadId;
            int step2PostActionThreadId          = postExecutors[2].ThreadId;
            int step3StepActionThreadId          = stepExecutors[3].ThreadId;
            int step3PostActionThreadId          = postExecutors[3].ThreadId;
            int step4StepActionThreadId          = stepExecutors[4].ThreadId;
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name = "test transaction";
            });

            for (int i = 0; i < 7; ++i)
            {
                string index = i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index,
                    StepActionExecutor = stepExecutors[i] == null
                                           ? null
                                           : stepExecutors[i],
                    PostActionExecutor = postExecutors[i] == null
                                           ? null
                                           : postExecutors[i],
                    Settings = i == 1
                                ? StepSettings.SameExecutorForAllActions
                                : StepSettings.None
                };

                if (i == 3 ||
                    i == 4)
                {
                    step.AsyncStepAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);
                        stepActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.StepAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);
                        stepActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                    };
                }

                if (i % 4 == 0)
                {
                    step.AsyncUndoAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.UndoAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                    };
                }

                if (i == 1 ||
                    i == 2)
                {
                    step.AsyncPostAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        runPostActions.Add(index);
                        postActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                        info.CurrentStepId.Should().Be(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.PostAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        runPostActions.Add(index);
                        postActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                        info.CurrentStepId.Should().Be(index);
                    };
                }

                target.Add(step);
            }
            ITransactionResult <object> transactionCallbackResult = null;

            /*
             * 0:
             * 1: executor for other thread (step action), SameExecutorForAllActions
             * 2: executor for other thread (post action)
             * 3: executor for other thread (step action), executor for other thread (post action)
             * 4: executor for other thread (step action)
             * 5:
             * 6:
             */

            // Act
            ITransactionResult <object> result = await target.Run(settings =>
            {
                settings.Data = transactionData;
                settings.Mode = RunMode.Run;
                settings.TransactionResultCallback = callbackResult =>
                {
                    transactionCallbackThreadId = Thread.CurrentThread.ManagedThreadId;
                    transactionCallbackResult   = callbackResult;
                };
            });

            // Assert
            foreach (TestExecutor executor in stepExecutors.Values.Concat(postExecutors.Values).Where(x => x != null))
            {
                executor.Dispose();
            }

            result.Should().BeSameAs(transactionCallbackResult);
            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[0]);
            result.Recovered.Should().BeFalse();
            result.Result.Should().Be(ResultType.Success);
            TestExecutor sharedExecutor = stepExecutors[1];

            sharedExecutor.Verify(Times.Exactly(2), Times.Exactly(2));

            foreach (TestExecutor executor in stepExecutors.Values.Concat(postExecutors.Values).Where(x => x != null && x != sharedExecutor))
            {
                executor.Verify(Times.Once, Times.Once);
            }

            runStepActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4", "5", "6" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[0]);
            runPostActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4", "5", "6" });
            stepActionThreadId.ShouldAllBeEquivalentTo(new int[]
            {
                /*step 0*/ transactionRunThreadId,
                /*step 1*/ step1StepActionThreadId,
                /*step 2*/ step1StepActionThreadId,
                /*step 3*/ step3StepActionThreadId,
                /*step 4*/ step4StepActionThreadId,
                /*step 5*/ step4StepActionThreadId,
                /*step 6*/ step4StepActionThreadId
            });
            postActionThreadId.ShouldAllBeEquivalentTo(new int[]
            {
                /*step 0*/ step4StepActionThreadId,
                /*step 1*/ step1StepActionThreadId,
                /*step 2*/ step2PostActionThreadId,
                /*step 3*/ step3PostActionThreadId,
                /*step 4*/ step3PostActionThreadId,
                /*step 5*/ step3PostActionThreadId,
                /*step 6*/ step3PostActionThreadId
            });
            transactionCallbackThreadId.Should().Be(step3PostActionThreadId);
        }
Exemple #28
0
        public void WhenGoForwardWithComparerWithCompareFailureWithStepExecutors_ShouldFailTransaction()
        {
            // Arrange
            object        transactionData                = new object();
            List <string> runStepActions                 = new List <string>();
            List <string> runUndoActions                 = new List <string>();
            List <string> runPostActions                 = new List <string>();
            List <int>    stepActionThreadId             = new List <int>();
            List <int>    postActionThreadId             = new List <int>();
            int           transactionCallbackThreadId    = 0;
            Dictionary <int, TestExecutor> stepExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 2, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 5, null },
                { 6, null }
            };
            Dictionary <int, TestExecutor> postExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, null },
                { 2, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, null },
                { 5, null },
                { 6, null }
            };
            int          transactionRunThreadId = Thread.CurrentThread.ManagedThreadId;
            TestExecutor callBackExecutor       = new TestExecutor()
            {
                ShouldRun = true
            };
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name = "test transaction";
            });

            for (int i = 0; i < 7; ++i)
            {
                string index = "B" + i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index,
                    StepActionExecutor = stepExecutors[i] == null
                                           ? null
                                           : stepExecutors[i],
                    PostActionExecutor = postExecutors[i] == null
                                           ? null
                                           : postExecutors[i]
                };

                step.StepAction = (data, info) =>
                {
                    if (info.CurrentStepId == "B2")
                    {
                        info.GoForward("b4", StringComparer.Ordinal);
                    }

                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runStepActions.Add(index);
                    stepActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                };

                step.UndoAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runUndoActions.Add(index);
                };

                step.PostAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    runPostActions.Add(index);
                    postActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                    info.CurrentStepId.Should().Be(index);
                };

                target.Add(step);
            }

            /*
             * 0:
             * 1: executor for other thread (step action)
             * 2: executor for other thread (step action), executor for other thread (post action), go forward to step 4
             * 3: executor for other thread (step action), executor for other thread (post action)
             * 4: executor for other thread (step action)
             * 5:
             * 6:
             */

            // Act
            ITransactionResult <object> result = null;

            using (ManualResetEvent transactionEndResetEvent = new ManualResetEvent(false))
            {
                target.Run(settings =>
                {
                    settings.Data = transactionData;
                    settings.Mode = RunMode.Run;
                    settings.TransactionResultCallback = callbackResult =>
                    {
                        transactionCallbackThreadId = Thread.CurrentThread.ManagedThreadId;
                        result = callbackResult;
                        transactionEndResetEvent.Set();
                    };
                    settings.TransactionResultCallbackExecutor = callBackExecutor;
                });
                transactionEndResetEvent.WaitOne();
            }

            // Assert
            callBackExecutor.Dispose();

            foreach (TestExecutor executor in stepExecutors.Values.Concat(postExecutors.Values).Where(x => x != null))
            {
                executor.Dispose();
            }

            result.Data.Should().BeSameAs(transactionData);
            result.Errors.Count().Should().Be(1);
            result.Errors.First().Message.Contains("Could not move forward to a step with id 'b4' as the step does not exist.").Should().BeTrue();
            result.Recovered.Should().BeFalse();
            result.Result.Should().Be(ResultType.Failed);
            runStepActions.ShouldAllBeEquivalentTo(new string[] { "B0", "B1", "B2" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[] { "B2", "B1", "B0" });
            runPostActions.ShouldAllBeEquivalentTo(new string[0]);
            stepActionThreadId.ShouldAllBeEquivalentTo(new int[]
            {
                /*step 0*/ transactionRunThreadId,
                /*step 1*/ stepExecutors[1].ThreadId,
                /*step 2*/ stepExecutors[2].ThreadId
            });
            transactionCallbackThreadId.Should().Be(callBackExecutor.ThreadId);
        }
        public void WhenRunRecoveredTransaction_ShouldProcessStepsProperly()
        {
            // Arrange
            object        transactionData = new object();
            List <string> runStepActions  = new List <string>();
            List <string> runUndoActions  = new List <string>();
            List <string> runPostActions  = new List <string>();
            Mock <ITransactionStorage <object> > storageMock   = new Mock <ITransactionStorage <object> >();
            Mock <ITransactionData <object> >    recoveredData = new Mock <ITransactionData <object> >();

            recoveredData.SetupGet(x => x.CurrentStepIndex)
            .Returns(2);
            recoveredData.SetupGet(x => x.Data)
            .Returns(transactionData);
            recoveredData.SetupGet(x => x.SessionId)
            .Returns(Guid.NewGuid());
            recoveredData.SetupGet(x => x.StartTimestamp)
            .Returns(DateTime.Now);
            storageMock.Setup(x => x.RecoverTransaction())
            .Returns(recoveredData.Object);
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name      = "test transaction";
                options.TransactionStorageCreator = context => storageMock.Object;
            });

            for (int i = 0; i < 6; ++i)
            {
                string index = i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id       = index,
                    Settings = StepSettings.None
                };

                step.StepAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runStepActions.Add(index);
                };

                step.UndoAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    info.CurrentStepId.Should().Be(index);
                    runUndoActions.Add(index);
                };

                step.PostAction = (data, info) =>
                {
                    data.Should().BeSameAs(transactionData);
                    runPostActions.Add(index);
                    info.CurrentStepId.Should().Be(index);
                };

                target.Add(step);
            }
            ITransactionResult <object> result = null;

            /*
             * 0:
             * 1:
             * 2: recovered step
             * 3:
             * 4:
             * 5:
             */

            // Act
            target.Run(settings =>
            {
                settings.Data = transactionData;
                settings.Mode = RunMode.RecoverAndUndoAndRun;
                settings.TransactionResultCallback = callbackResult => result = callbackResult;
            });

            // Assert
            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[0]);
            result.Recovered.Should().BeTrue();
            result.Result.Should().Be(ResultType.Success);
            runStepActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4", "5" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[] { "2", "1", "0" });
            runPostActions.ShouldAllBeEquivalentTo(new string[] { "0", "1", "2", "3", "4", "5" });
            storageMock.AssertStorageOperations(new AssertStorageOperationsContext <string, object>()
            {
                SessionStartedTimes = Times.Never(),
                TransactionData     = transactionData,
                Transaction         = target,
                ExpectedStepsOrder  = runStepActions,
                ExpectedUndoOrder   = runUndoActions
            });
        }
Exemple #30
0
        public async Task WhenGoForwardWithComparerWithCompareSuccessWithStepExecutors_ShouldMoveToStepProperly()
        {
            // Arrange
            object        transactionData                = new object();
            List <string> runStepActions                 = new List <string>();
            List <string> runUndoActions                 = new List <string>();
            List <string> runPostActions                 = new List <string>();
            List <int>    stepActionThreadId             = new List <int>();
            List <int>    postActionThreadId             = new List <int>();
            int           transactionCallbackThreadId    = 0;
            Dictionary <int, TestExecutor> stepExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 2, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 5, null },
                { 6, null }
            };
            Dictionary <int, TestExecutor> postExecutors = new Dictionary <int, TestExecutor>()
            {
                { 0, null },
                { 1, null },
                { 2, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 3, new TestExecutor()
                  {
                      ShouldRun = true
                  } },
                { 4, null },
                { 5, null },
                { 6, null }
            };
            int          transactionRunThreadId = Thread.CurrentThread.ManagedThreadId;
            TestExecutor callBackExecutor       = new TestExecutor()
            {
                ShouldRun = true
            };
            ITransaction <string, object> target = new TransactionFactory().Create <string, object>(options =>
            {
                options.TransactionInfo.Name = "test transaction";
            });

            for (int i = 0; i < 7; ++i)
            {
                string index = "B" + i.ToString();
                TransactionStep <string, object> step = new TransactionStep <string, object>()
                {
                    Id = index,
                    StepActionExecutor = stepExecutors[i] == null
                                           ? null
                                           : stepExecutors[i],
                    PostActionExecutor = postExecutors[i] == null
                                           ? null
                                           : postExecutors[i]
                };

                if (i != 2)
                {
                    step.AsyncStepAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);
                        stepActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.StepAction = (data, info) =>
                    {
                        info.GoForward("b4", StringComparer.OrdinalIgnoreCase);
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runStepActions.Add(index);
                        stepActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                    };
                }

                if (i % 4 == 0)
                {
                    step.AsyncUndoAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.UndoAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        info.CurrentStepId.Should().Be(index);
                        runUndoActions.Add(index);
                    };
                }

                if (i == 1 ||
                    i == 2)
                {
                    step.AsyncPostAction = async(data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        runPostActions.Add(index);
                        postActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                        info.CurrentStepId.Should().Be(index);
                        await Task.CompletedTask;
                    };
                }
                else
                {
                    step.PostAction = (data, info) =>
                    {
                        data.Should().BeSameAs(transactionData);
                        runPostActions.Add(index);
                        postActionThreadId.Add(Thread.CurrentThread.ManagedThreadId);
                        info.CurrentStepId.Should().Be(index);
                    };
                }

                target.Add(step);
            }
            ITransactionResult <object> transactionCallbackResult = null;

            /*
             * 0:
             * 1: executor for other thread (step action)
             * 2: executor for other thread (step action), executor for other thread (post action), go forward to step 4
             * 3: executor for other thread (step action), executor for other thread (post action)
             * 4: executor for other thread (step action)
             * 5:
             * 6:
             */

            // Act
            ITransactionResult <object> result = await target.Run(settings =>
            {
                settings.Data = transactionData;
                settings.Mode = RunMode.Run;
                settings.TransactionResultCallback = callbackResult =>
                {
                    transactionCallbackThreadId = Thread.CurrentThread.ManagedThreadId;
                    transactionCallbackResult   = callbackResult;
                };
                settings.TransactionResultCallbackExecutor = callBackExecutor;
            });

            // Assert
            callBackExecutor.Dispose();

            foreach (TestExecutor executor in stepExecutors.Values.Concat(postExecutors.Values).Where(x => x != null))
            {
                executor.Dispose();
            }

            result.Should().BeSameAs(transactionCallbackResult);
            result.Data.Should().BeSameAs(transactionData);
            result.Errors.ShouldAllBeEquivalentTo(new Exception[0]);
            result.Recovered.Should().BeFalse();
            result.Result.Should().Be(ResultType.Success);
            callBackExecutor.Verify(Times.Once, Times.Once);

            foreach (TestExecutor executor in stepExecutors.Values.Concat(postExecutors.Values).Where(x => x != null && x != stepExecutors[3]))
            {
                executor.Verify(Times.Once, Times.Once);
            }

            stepExecutors[3].Verify(Times.Never, Times.Never);
            runStepActions.ShouldAllBeEquivalentTo(new string[] { "B0", "B1", "B2", "B4", "B5", "B6" });
            runUndoActions.ShouldAllBeEquivalentTo(new string[0]);
            runPostActions.ShouldAllBeEquivalentTo(new string[] { "B0", "B1", "B2", "B3", "B4", "B5", "B6" });
            stepActionThreadId.ShouldAllBeEquivalentTo(new int[]
            {
                /*step 0*/ transactionRunThreadId,
                /*step 1*/ stepExecutors[1].ThreadId,
                /*step 2*/ stepExecutors[2].ThreadId,
                /*step 4*/ stepExecutors[4].ThreadId,
                /*step 5*/ stepExecutors[4].ThreadId,
                /*step 6*/ stepExecutors[4].ThreadId
            });
            postActionThreadId.ShouldAllBeEquivalentTo(new int[]
            {
                /*step 0*/ stepExecutors[4].ThreadId,
                /*step 1*/ stepExecutors[4].ThreadId,
                /*step 2*/ postExecutors[2].ThreadId,
                /*step 3*/ postExecutors[3].ThreadId,
                /*step 4*/ postExecutors[3].ThreadId,
                /*step 5*/ postExecutors[3].ThreadId,
                /*step 6*/ postExecutors[3].ThreadId
            });
            transactionCallbackThreadId.Should().Be(callBackExecutor.ThreadId);
        }