public async Task StaysInCurrentState_WhenAGuardThrowsAnException()
        {
            var eventArguments = new object[] { 1, 2, "test" };
            var exception      = new Exception();

            bool ThrowingGuard() => throw exception;

            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionsBuilder
            .In(States.A)
            .On(Events.B)
            .If(ThrowingGuard).Goto(States.B);
            var stateDefinitions = stateDefinitionsBuilder.Build();

            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.TransitionExceptionThrown += (sender, eventArgs) => { };

            await testee.EnterInitialState(stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            await testee.Fire(Events.B, eventArguments, stateContainer, stateDefinitions)
            .ConfigureAwait(false);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.A));
        }
        public async Task DeclinesTransition_WhenAGuardThrowsAnException()
        {
            var eventArguments = new object[] { 1, 2, "test" };
            var exception      = new Exception();

            bool ThrowingGuard() => throw exception;

            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionsBuilder
            .In(States.A)
            .On(Events.B)
            .If(ThrowingGuard).Goto(States.B);
            var stateDefinitions = stateDefinitionsBuilder.Build();

            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            var transitionDeclined = false;

            testee.TransitionDeclined        += (sender, e) => transitionDeclined = true;
            testee.TransitionExceptionThrown += (sender, eventArgs) => { };

            await testee.EnterInitialState(stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            await testee.Fire(Events.B, eventArguments, stateContainer, stateDefinitions)
            .ConfigureAwait(false);

            transitionDeclined
            .Should()
            .BeTrue("transition was not declined.");
        }
示例#3
0
        public async Task ParametrizedExitAction()
        {
            const int Parameter = 3;

            var receivedValue = 0;

            var stateContainer         = new StateContainer <States, Events>();
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .In(States.A)
            .ExecuteOnExitParametrized(value => receivedValue = value, Parameter)
            .On(Events.B).Goto(States.B);
            var stateDefinitions = stateDefinitionBuilder.Build();

            var testee = new StateMachineBuilder <States, Events>()
                         .WithStateContainer(stateContainer)
                         .Build();

            await testee.EnterInitialState(stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            await testee.Fire(Events.B, null, stateContainer, stateDefinitions)
            .ConfigureAwait(false);

            receivedValue.Should().Be(Parameter);
        }
示例#4
0
        public async Task ParameterizedEntryAction()
        {
            const int Parameter = 3;

            var receivedValue = 0;

            var stateContainer         = new StateContainer <States, Events>();
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .In(States.A)
            .ExecuteOnEntryParametrized(parameter => receivedValue = parameter, Parameter);
            var stateDefinitions = stateDefinitionBuilder.Build();

            var testee = new StateMachineBuilder <States, Events>()
                         .WithStateContainer(stateContainer)
                         .Build();

            await testee.EnterInitialState(stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            receivedValue
            .Should()
            .Be(Parameter);
        }
示例#5
0
        public async Task ExitActions()
        {
            var exit1 = false;
            var exit2 = false;

            var stateContainer         = new StateContainer <States, Events>();
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .In(States.A)
            .ExecuteOnExit(() => exit1 = true)
            .ExecuteOnExit(() => exit2 = true)
            .On(Events.B).Goto(States.B);
            var stateDefinitions = stateDefinitionBuilder.Build();

            var testee = new StateMachineBuilder <States, Events>()
                         .WithStateContainer(stateContainer)
                         .Build();

            await testee.EnterInitialState(stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            await testee.Fire(Events.B, null, stateContainer, stateDefinitions)
            .ConfigureAwait(false);

            exit1.Should().BeTrue("exit action was not executed.");
            exit2.Should().BeTrue("exit action was not executed.");
        }
示例#6
0
        public async Task EventArgumentIsPassedToTheGuard_AsyncUsage()
        {
            const string ExpectedEventArgument = "test";
            string       actualEventArgument   = null;

            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionsBuilder
            .In(States.A)
            .On(Events.A)
            .If((string argument) =>
            {
                actualEventArgument = argument;
                return(Task.FromResult(true));
            })
            .Goto(States.B);
            var stateDefinitions = stateDefinitionsBuilder.Build();

            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            await testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            await testee.Fire(Events.A, ExpectedEventArgument, stateContainer, stateContainer, stateDefinitions)
            .ConfigureAwait(false);

            actualEventArgument
            .Should()
            .Be(ExpectedEventArgument);
        }
示例#7
0
        public async Task GuardWithASingleArgument()
        {
            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionsBuilder
            .In(States.A)
            .On(Events.B)
            .If((Func <int, bool>)SingleIntArgumentGuardReturningFalse).Goto(States.C)
            .If(() => false).Goto(States.D)
            .If(() => false).Goto(States.E)
            .If((Func <int, bool>)SingleIntArgumentGuardReturningTrue).Goto(States.B);
            var stateDefinitions = stateDefinitionsBuilder.Build();

            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            await testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            await testee.Fire(Events.B, 3, stateContainer, stateContainer, stateDefinitions)
            .ConfigureAwait(false);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.B));
        }
示例#8
0
        public async Task GuardWithoutArguments()
        {
            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionsBuilder
            .In(States.A)
            .On(Events.B)
            .If(() => false).Goto(States.C)
            .If(() => true).Goto(States.B);
            var stateDefinitions = stateDefinitionsBuilder.Build();

            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            await testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            await testee.Fire(Events.B, Missing.Value, stateContainer, stateContainer, stateDefinitions)
            .ConfigureAwait(false);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.B));
        }
        public void ThrowsException_WhenInitialStateIsSuperStateItselfInAnHierarchy()
        {
            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            Action action = () => stateDefinitionsBuilder
                            .DefineHierarchyOn(States.B)
                            .WithHistoryType(HistoryType.None)
                            .WithInitialSubState(States.B)
                            .WithSubState(States.B1)
                            .WithSubState(States.B2);

            action.Should().Throw <ArgumentException>();
        }
        public void ThrowsException_WhenFiringAnEventOntoAnNotInitializedStateMachine()
        {
            var stateDefinitions = new StateDefinitionsBuilder <States, Events>().Build();

            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            Func <Task> action = async() =>
                                 await testee.Fire(Events.B, Missing.Value, stateContainer, stateDefinitions)
                                 .ConfigureAwait(false);

            action.Should().Throw <InvalidOperationException>();
        }
        public void ThrowsException_WhenTransitionWithoutGuardIsNotDefinedLast()
        {
            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionsBuilder
            .In(States.A)
            .On(Events.B).Goto(States.B);

            Action action = () =>
                            stateDefinitionsBuilder
                            .In(States.A)
                            .On(Events.B).If(() => false).Execute(() => { });

            action
            .Should()
            .Throw <InvalidOperationException>()
            .WithMessage(ExceptionMessages.TransitionWithoutGuardHasToBeLast);
        }
        public void ThrowsException_WhenMultipleTransitionsWithoutGuardsAreDefined_ExecuteCase()
        {
            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionsBuilder
            .In(States.A)
            .On(Events.B).Goto(States.B);

            Action action = () =>
                            stateDefinitionsBuilder
                            .In(States.A)
                            .On(Events.B).Execute(() => { });

            action
            .Should()
            .Throw <InvalidOperationException>()
            .WithMessage(ExceptionMessages.OnlyOneTransitionMayHaveNoGuard);
        }
        public void ThrowsException_WhenDefiningNonTreeHierarchy()
        {
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .DefineHierarchyOn(States.A)
            .WithHistoryType(HistoryType.None)
            .WithInitialSubState(States.B);

            Action action = () =>
            {
                stateDefinitionBuilder
                .DefineHierarchyOn(States.C)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(States.B);
            };

            action.Should().Throw <InvalidOperationException>();
        }
        public async Task CapturesException_WhenEntryActionThrowsAnException()
        {
            var eventArguments = new object[] { 1, 2, "test" };
            var exception      = new Exception();

            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionsBuilder
            .In(States.A)
            .On(Events.B).Goto(States.B);
            stateDefinitionsBuilder
            .In(States.B)
            .ExecuteOnEntry(() => throw exception);
            var stateDefinitions = stateDefinitionsBuilder.Build();

            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            CapturedException capturedException = null;

            testee.TransitionExceptionThrown += (sender, eventArgs) =>
            {
                capturedException = new CapturedException(
                    eventArgs.StateId,
                    eventArgs.EventId,
                    eventArgs.EventArgument,
                    eventArgs.Exception);
            };

            await testee.EnterInitialState(stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            await testee.Fire(Events.B, eventArguments, stateContainer, stateDefinitions)
            .ConfigureAwait(false);

            capturedException
            .Should()
            .Be(new CapturedException(States.A, Events.B, eventArguments, exception));
        }
示例#15
0
        public async Task EntryAction()
        {
            var entered = false;

            var stateContainer         = new StateContainer <States, Events>();
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .In(States.A)
            .ExecuteOnEntry(() => entered = true);
            var stateDefinitions = stateDefinitionBuilder.Build();

            var testee = new StateMachineBuilder <States, Events>()
                         .WithStateContainer(stateContainer)
                         .Build();

            await testee.EnterInitialState(stateContainer, stateDefinitions, States.A)
            .ConfigureAwait(false);

            entered
            .Should()
            .BeTrue("entry action was not executed.");
        }