public void MustOnlyRevertPerformedOperations()
        {
            var operationA = new Mock <IOperation>();
            var operationB = new Mock <IOperation>();
            var operationC = new Mock <IOperation>();
            var operations = new Queue <IOperation>();

            operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
            operationA.Setup(o => o.Revert()).Returns(OperationResult.Success);
            operationB.Setup(o => o.Perform()).Returns(OperationResult.Aborted);
            operationB.Setup(o => o.Revert()).Returns(OperationResult.Success);

            operations.Enqueue(operationA.Object);
            operations.Enqueue(operationB.Object);
            operations.Enqueue(operationC.Object);

            var sut = new OperationSequence(loggerMock.Object, operations);

            sut.TryPerform();

            var result = sut.TryRevert();

            operationA.Verify(o => o.Revert(), Times.Once);
            operationB.Verify(o => o.Revert(), Times.Once);
            operationC.Verify(o => o.Revert(), Times.Never);

            Assert.AreEqual(OperationResult.Success, result);
        }
        public void MustContinueToRevertOperationsInCaseOfError()
        {
            var operationA = new Mock <IOperation>();
            var operationB = new Mock <IOperation>();
            var operationC = new Mock <IOperation>();
            var operations = new Queue <IOperation>();

            operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
            operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
            operationC.Setup(o => o.Perform()).Returns(OperationResult.Success);

            operationA.Setup(o => o.Revert()).Throws <Exception>();
            operationB.Setup(o => o.Revert()).Throws <Exception>();
            operationC.Setup(o => o.Revert()).Throws <Exception>();

            operations.Enqueue(operationA.Object);
            operations.Enqueue(operationB.Object);
            operations.Enqueue(operationC.Object);

            var sut = new OperationSequence(loggerMock.Object, operations);

            sut.TryPerform();

            var result = sut.TryRevert();

            operationA.Verify(o => o.Revert(), Times.Once);
            operationB.Verify(o => o.Revert(), Times.Once);
            operationC.Verify(o => o.Revert(), Times.Once);

            Assert.AreEqual(OperationResult.Failed, result);
        }
        public void MustRevertOperationsInSequence()
        {
            int current = 0, a = 0, b = 0, c = 0;
            var operationA = new Mock <IOperation>();
            var operationB = new Mock <IOperation>();
            var operationC = new Mock <IOperation>();
            var operations = new Queue <IOperation>();

            operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
            operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
            operationC.Setup(o => o.Perform()).Returns(OperationResult.Success);

            operationA.Setup(o => o.Revert()).Returns(OperationResult.Success).Callback(() => a = ++current);
            operationB.Setup(o => o.Revert()).Returns(OperationResult.Success).Callback(() => b = ++current);
            operationC.Setup(o => o.Revert()).Returns(OperationResult.Success).Callback(() => c = ++current);

            operations.Enqueue(operationA.Object);
            operations.Enqueue(operationB.Object);
            operations.Enqueue(operationC.Object);

            var sut = new OperationSequence(loggerMock.Object, operations);

            sut.TryPerform();

            var result = sut.TryRevert();

            Assert.AreEqual(OperationResult.Success, result);
            Assert.IsTrue(c == 1);
            Assert.IsTrue(b == 2);
            Assert.IsTrue(a == 3);
        }
        public void MustCreateCopyOfOperationQueue()
        {
            var operationA = new Mock <IOperation>();
            var operationB = new Mock <IOperation>();
            var operationC = new Mock <IOperation>();
            var operations = new Queue <IOperation>();

            operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
            operationB.Setup(o => o.Perform()).Returns(OperationResult.Success);
            operationC.Setup(o => o.Perform()).Returns(OperationResult.Success);

            operations.Enqueue(operationA.Object);
            operations.Enqueue(operationB.Object);
            operations.Enqueue(operationC.Object);

            var sut = new OperationSequence(loggerMock.Object, operations);

            operations.Clear();

            sut.TryPerform();

            operationA.Verify(o => o.Perform(), Times.Once);
            operationB.Verify(o => o.Perform(), Times.Once);
            operationC.Verify(o => o.Perform(), Times.Once);
        }
        public void MustSucceedWithEmptyQueue()
        {
            var sut    = new OperationSequence(loggerMock.Object, new Queue <IOperation>());
            var result = sut.TryPerform();

            Assert.AreEqual(OperationResult.Success, result);
        }
        public void MustNotFailInCaseOfUnexpectedError()
        {
            var sut = new OperationSequence(loggerMock.Object, new Queue <IOperation>());

            sut.ProgressChanged += (args) => throw new Exception();

            var result = sut.TryPerform();

            Assert.AreEqual(OperationResult.Failed, result);
        }
        public void MustCorrectlyPropagateEventSubscription()
        {
            var actionRequiredCalled  = false;
            var actionRequiredHandler = new ActionRequiredEventHandler(args => actionRequiredCalled = true);
            var statusChangedCalled   = false;
            var statusChangedHandler  = new StatusChangedEventHandler(t => statusChangedCalled = true);
            var operationA            = new Mock <IOperation>();
            var operationB            = new Mock <IOperation>();
            var operationC            = new Mock <IOperation>();
            var operations            = new Queue <IOperation>();

            operationA.Setup(o => o.Perform()).Returns(OperationResult.Success);
            operationB.Setup(o => o.Perform()).Returns(OperationResult.Success).Raises(o => o.ActionRequired += null, new Mock <ActionRequiredEventArgs>().Object);
            operationC.Setup(o => o.Perform()).Returns(OperationResult.Success).Raises(o => o.StatusChanged  += null, default(TextKey));

            operations.Enqueue(operationA.Object);
            operations.Enqueue(operationB.Object);
            operations.Enqueue(operationC.Object);

            var sut = new OperationSequence(loggerMock.Object, operations);

            sut.ActionRequired += actionRequiredHandler;
            sut.StatusChanged  += statusChangedHandler;

            sut.TryPerform();

            Assert.IsTrue(actionRequiredCalled);
            Assert.IsTrue(statusChangedCalled);

            actionRequiredCalled = false;
            statusChangedCalled  = false;
            sut.ActionRequired  -= actionRequiredHandler;
            sut.StatusChanged   -= statusChangedHandler;

            sut.TryPerform();

            Assert.IsFalse(actionRequiredCalled);
            Assert.IsFalse(statusChangedCalled);
        }