public void OnceSteps_RevertFailed_RetryRevertAndSucceed()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind()
            {
                ThrowFromRevertFour = true,
                ThrowFromRevertTwo  = true
            };
            var sequence = new RevertableSequence(codeBehind);

            sequence.Perform();

            var exception = Assert.Throws <AggregateException>(() => {
                sequence.Revert();
            });

            codeBehind.TakeLog();

            codeBehind.ThrowFromRevertFour = false;
            codeBehind.ThrowFromRevertTwo  = false;

            //-- Act

            sequence.Revert();

            //-- Assert

            Assert.Equal(sequence.State, RevertableSequenceState.Reverted);
            Assert.Equal(codeBehind.TakeLog(), new[] {
                "RevertFour()", "RevertTwo()"
            });
        }
        public void OnceSteps_Revert_ReverseOrder()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind();
            var sequence   = new RevertableSequence(codeBehind);

            sequence.Perform();

            //-- Act

            var log1 = codeBehind.TakeLog();

            sequence.Revert();

            var log2 = codeBehind.TakeLog();

            //-- Assert

            Assert.Equal(sequence.State, RevertableSequenceState.Reverted);
            Assert.Equal(log1, new[] {
                "PerformOne()", "PerformTwo()", "PerformThree()"
            });
            Assert.Equal(log2, new[] {
                "RevertFour()", "RevertTwo()", "RevertOne()"
            });
        }
        public void MultipleCollectionSteps_RevertFailed_RetryAndRevertAll()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind(
                fiveItems: new[] { 111, 222 },
                sixItems: new[] { "AAA", "BBB" },
                sevenItems: new[] { DayOfWeek.Friday, DayOfWeek.Sunday });
            var sequence = new RevertableSequence(codeBehind);

            codeBehind.ThrowFromPerformSixItemIndex = 1;
            codeBehind.ThrowFromRevertFiveItemIndex = 0;
            codeBehind.ThrowFromRevertFour          = true;

            var exception = Assert.Throws <AggregateException>(() => {
                sequence.Perform();
            });

            codeBehind.ThrowFromRevertFiveItemIndex = null;
            codeBehind.ThrowFromRevertFour          = false;
            codeBehind.TakeLog();

            //-- Act

            sequence.Revert();

            //-- Assert

            Assert.Equal(sequence.State, RevertableSequenceState.Reverted);
            Assert.Equal(codeBehind.TakeLog(), new[] {
                "RevertFiveItem(111,index=0,last=F)",
                "RevertFour()",
            });
        }
        public void MultipleCollectionSteps_RevertSucceeded_AllItemsReverted()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind(
                fiveItems: new[] { 111, 222 },
                sixItems: new[] { "AAA", "BBB" },
                sevenItems: new[] { DayOfWeek.Friday, DayOfWeek.Sunday });
            var sequence = new RevertableSequence(codeBehind);

            sequence.Perform();
            codeBehind.TakeLog();

            //-- Act

            sequence.Revert();

            Assert.Equal(sequence.State, RevertableSequenceState.Reverted);
            Assert.Equal(codeBehind.TakeLog(), new[] {
                "RevertSevenItem(Sunday,index=1,last=T)",
                "RevertSevenItem(Friday,index=0,last=F)",
                "RevertFiveItem(222,index=1,last=T)",
                "RevertFiveItem(111,index=0,last=F)",
                "RevertFour()",
                "RevertTwo()",
                "RevertOne()",
            });
        }
        public void OnceSteps_RevertFailed_AggregateExceptionThrown()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind()
            {
                ThrowFromRevertFour = true,
                ThrowFromRevertTwo  = true
            };
            var sequence = new RevertableSequence(codeBehind);

            sequence.Perform();
            codeBehind.TakeLog();

            //-- Act

            var exception = Assert.Throws <AggregateException>(() => {
                sequence.Revert();
            });

            //-- Assert

            Assert.Equal(sequence.State, RevertableSequenceState.RevertFailed);
            Assert.Equal(codeBehind.TakeLog(), new[] {
                "THROWING-FROM:RevertFour()", "THROWING-FROM:RevertTwo()", "RevertOne()"
            });

            Assert.True(exception.InnerExceptions.All(e => e is TestSequenceException), "Exception type");
            Assert.Equal(exception.InnerExceptions.Select(e => e.Message), new[] {
                "RevertFour()", "RevertTwo()"
            });
        }
        public void OnceSteps_Revert_ReverseOrder()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind();
            var sequence = new RevertableSequence(codeBehind);

            sequence.Perform();

            //-- Act

            var log1 = codeBehind.TakeLog();

            sequence.Revert();

            var log2 = codeBehind.TakeLog();

            //-- Assert

            Assert.That(sequence.State, Is.EqualTo(RevertableSequenceState.Reverted));
            Assert.That(log1, Is.EqualTo(new[] {
                "PerformOne()", "PerformTwo()", "PerformThree()"
            }));
            Assert.That(log2, Is.EqualTo(new[] {
                "RevertFour()", "RevertTwo()", "RevertOne()"
            }));
        }
        public void OnceSteps_RevertFailed_RetryRevertAndSucceed()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind() {
                ThrowFromRevertFour = true,
                ThrowFromRevertTwo = true
            };
            var sequence = new RevertableSequence(codeBehind);

            sequence.Perform();

            try
            {
                sequence.Revert();
            }
            catch ( AggregateException )
            {
            }

            codeBehind.TakeLog();

            codeBehind.ThrowFromRevertFour = false;
            codeBehind.ThrowFromRevertTwo = false;

            //-- Act

            sequence.Revert();

            //-- Assert

            Assert.That(sequence.State, Is.EqualTo(RevertableSequenceState.Reverted));
            Assert.That(codeBehind.TakeLog(), Is.EqualTo(new[] {
                "RevertFour()", "RevertTwo()"
            }));
        }
        public void OnceSteps_RevertFailed_AggregateExceptionThrown()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind() {
                ThrowFromRevertFour = true,
                ThrowFromRevertTwo = true
            };
            var sequence = new RevertableSequence(codeBehind);

            sequence.Perform();
            codeBehind.TakeLog();

            //-- Act

            try
            {
                sequence.Revert();
            }
            catch ( AggregateException aggregate )
            {
                //-- Assert

                Assert.That(sequence.State, Is.EqualTo(RevertableSequenceState.RevertFailed));
                Assert.That(codeBehind.TakeLog(), Is.EqualTo(new[] {
                    "THROWING-FROM:RevertFour()", "THROWING-FROM:RevertTwo()", "RevertOne()"
                }));

                Assert.That(aggregate.InnerExceptions.All(e => e is TestSequenceException), "Exception type");
                Assert.That(aggregate.InnerExceptions.Select(e => e.Message), Is.EqualTo(new[] {
                    "RevertFour()", "RevertTwo()"
                }));
            }
        }
        public void MultipleCollectionSteps_RevertSucceeded_AllItemsReverted()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind(
                fiveItems: new[] { 111, 222 },
                sixItems: new[] { "AAA", "BBB" },
                sevenItems: new[] { DayOfWeek.Friday, DayOfWeek.Sunday });
            var sequence = new RevertableSequence(codeBehind);

            sequence.Perform();
            codeBehind.TakeLog();

            //-- Act

            sequence.Revert();

            Assert.That(sequence.State, Is.EqualTo(RevertableSequenceState.Reverted));
            Assert.That(codeBehind.TakeLog(), Is.EqualTo(new[] {
                "RevertSevenItem(Sunday,index=1,last=T)",
                "RevertSevenItem(Friday,index=0,last=F)",
                "RevertFiveItem(222,index=1,last=T)",
                "RevertFiveItem(111,index=0,last=F)",
                "RevertFour()",
                "RevertTwo()",
                "RevertOne()",
            }));
        }
        public void MultipleCollectionSteps_RevertFailed_RetryAndRevertAll()
        {
            //-- Arrange

            var codeBehind = new TestCodeBehind(
                fiveItems: new[] { 111, 222 },
                sixItems: new[] { "AAA", "BBB" },
                sevenItems: new[] { DayOfWeek.Friday, DayOfWeek.Sunday });
            var sequence = new RevertableSequence(codeBehind);

            codeBehind.ThrowFromPerformSixItemIndex = 1;
            codeBehind.ThrowFromRevertFiveItemIndex = 0;
            codeBehind.ThrowFromRevertFour = true;

            try
            {
                sequence.Perform();
            }
            catch ( AggregateException )
            {
            }

            codeBehind.ThrowFromRevertFiveItemIndex = null;
            codeBehind.ThrowFromRevertFour = false;
            codeBehind.TakeLog();

            //-- Act

            sequence.Revert();

            //-- Assert

            Assert.That(sequence.State, Is.EqualTo(RevertableSequenceState.Reverted));
            Assert.That(codeBehind.TakeLog(), Is.EqualTo(new[] {
                "RevertFiveItem(111,index=0,last=F)",
                "RevertFour()",
            }));
        }