public void ExecuteActions()
        {
            const int EventArgument = 17;

            int?action1Argument = null;
            int?action2Argument = null;

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

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.B)
            .Goto(States.B)
            .Execute <int>(argument => { action1Argument = argument; })
            .Execute((int argument) => { action2Argument = argument; });
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.B, EventArgument, stateContainer, stateDefinitions);

            action1Argument.Should().Be(EventArgument);
            action2Argument.Should().Be(EventArgument);
        }
示例#2
0
        public void ExitActions()
        {
            var exit1 = false;
            var exit2 = false;

            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 stateContainer   = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.B, stateContainer, stateContainer, stateDefinitions);

            exit1.Should().BeTrue("exit action was not executed.");
            exit2.Should().BeTrue("exit action was not executed.");
        }
示例#3
0
        public void EventArgumentIsPassedToTheGuard()
        {
            const string EventArgument       = "test";
            string       actualEventArgument = null;

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

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.A)
            .If <string>(argument =>
            {
                actualEventArgument = argument;
                return(true);
            })
            .Goto(States.B);
            var stateDefinitions = stateDefinitionBuilder
                                   .Build();
            var stateContainer = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.A, EventArgument, stateContainer, stateDefinitions);

            actualEventArgument.Should().Be(EventArgument);
        }
示例#4
0
        public void GuardWithASingleArgument()
        {
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.B)
            .If <int>(SingleIntArgumentGuardReturningFalse).Goto(States.C)
            .If(() => false).Goto(States.D)
            .If(() => false).Goto(States.E)
            .If <int>(SingleIntArgumentGuardReturningTrue).Goto(States.B);
            var stateDefinitions = stateDefinitionBuilder
                                   .Build();
            var stateContainer = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

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

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.B));
        }
        public void InternalTransition()
        {
            var executed = false;

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

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.A)
            .Execute(() => executed = true);
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.A, stateContainer, stateContainer, stateDefinitions);

            executed.Should().BeTrue("internal transition was not executed.");
            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.A));
        }
示例#6
0
        public void ExecuteTransitionBetweenStatesOnDifferentLevelsDownwards()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.B2);

            this.ClearRecords();

            testee.Fire(Events.C1B, stateContainer, stateContainer, this.stateDefinitions);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.C1B));

            this.CheckRecord <ExitRecord>(States.B2);
            this.CheckRecord <ExitRecord>(States.B);
            this.CheckRecord <EntryRecord>(States.C);
            this.CheckRecord <EntryRecord>(States.C1);
            this.CheckRecord <EntryRecord>(States.C1B);
            this.CheckNoRemainingRecords();
        }
示例#7
0
        public void ParametrizedExitAction()
        {
            const int Parameter = 3;

            var receivedValue = 0;

            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 stateContainer   = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.B, stateContainer, stateContainer, stateDefinitions);

            receivedValue.Should().Be(Parameter);
        }
        public void ExecutesActions_WhenActionsWithAndWithoutArgumentAreDefined()
        {
            const int EventArgument = 17;

            var action1Executed = false;
            var action2Executed = false;

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

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.B)
            .Goto(States.B)
            .Execute <int>(argument => { action1Executed = true; })
            .Execute((int argument) => { action2Executed = true; });
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.B, EventArgument, stateContainer, stateDefinitions);

            action1Executed.Should().BeTrue("action with argument should be executed");
            action2Executed.Should().BeTrue("action without argument should be executed");
        }
        public void MissingTransition()
        {
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.B)
            .Goto(States.B);
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

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

            var declined = false;

            testee.TransitionDeclined += (sender, e) => { declined = true; };

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.C, stateContainer, stateContainer, stateDefinitions);

            declined.Should().BeTrue("Declined event was not fired");
            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.A));
        }
示例#10
0
        public void ExecuteTransitionWithHistoryTypeDeep()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.D1B);
            testee.Fire(Events.A, stateContainer, stateContainer, this.stateDefinitions);

            this.ClearRecords();

            testee.Fire(Events.D, stateContainer, stateContainer, this.stateDefinitions);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.D1B));

            this.CheckRecord <ExitRecord>(States.A);
            this.CheckRecord <EntryRecord>(States.D);
            this.CheckRecord <EntryRecord>(States.D1);
            this.CheckRecord <EntryRecord>(States.D1B);
            this.CheckNoRemainingRecords();
        }
示例#11
0
        public void ExceptionIfNotInitialized()
        {
            var stateContainer   = new StateContainer <States, Events>();
            var stateDefinitions = new StateDefinitionsBuilder <States, Events>().Build();

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

            Action action = () => testee.Fire(Events.A, stateContainer, stateContainer, stateDefinitions);

            action.Should().Throw <InvalidOperationException>();
        }
示例#12
0
        public void InternalTransition()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.A);
            this.ClearRecords();

            testee.Fire(Events.A, stateContainer, stateContainer, this.stateDefinitions);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.A));
        }
示例#13
0
        public void InitializeToTopLevelState()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.A);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.A));

            this.CheckRecord <EntryRecord>(States.A);
            this.CheckNoRemainingRecords();
        }
示例#14
0
        public void ExceptionThrowingGuard()
        {
            var       eventArguments        = new object[] { 1, 2, "test" };
            var       exception             = new Exception();
            States?   recordedStateId       = null;
            Events?   recordedEventId       = null;
            object    recordedEventArgument = null;
            Exception recordedException     = null;

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

            stateDefinitionsBuilder.In(States.A)
            .On(Events.B)
            .If(() => throw exception)
            .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) =>
            {
                recordedStateId       = eventArgs.StateId;
                recordedEventId       = eventArgs.EventId;
                recordedEventArgument = eventArgs.EventArgument;
                recordedException     = eventArgs.Exception;
            };

            testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A);

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

            recordedStateId.Should().Be(States.A);
            recordedEventId.Should().Be(Events.B);
            recordedEventArgument.Should().Be(eventArguments);
            recordedException.Should().Be(exception);
            stateContainer.CurrentStateId.Should().BeEquivalentTo(Initializable <States> .Initialized(States.A));
            transitionDeclined.Should().BeTrue("transition was not declined.");
        }
示例#15
0
        public void EntryActionWhenThrowingExceptionThenNotificationAndStateIsEntered()
        {
            var       eventArguments        = new object[] { 1, 2, "test" };
            var       exception             = new Exception();
            States?   recordedStateId       = null;
            Events?   recordedEventId       = null;
            object    recordedEventArgument = null;
            Exception recordedException     = null;

            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();

            testee.TransitionExceptionThrown += (sender, eventArgs) =>
            {
                recordedStateId       = eventArgs.StateId;
                recordedEventId       = eventArgs.EventId;
                recordedEventArgument = eventArgs.EventArgument;
                recordedException     = eventArgs.Exception;
            };

            testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A);

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

            recordedStateId.Should().Be(States.A);
            recordedEventId.Should().Be(Events.B);
            recordedEventArgument.Should().Be(eventArguments);
            recordedException.Should().Be(exception);
            stateContainer.CurrentStateId.Should().BeEquivalentTo(Initializable <States> .Initialized(States.B));
        }
示例#16
0
        public void ExecuteTransitionWithHistoryTypeNone()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.B2);
            testee.Fire(Events.A, stateContainer, stateContainer, this.stateDefinitions);

            this.ClearRecords();

            testee.Fire(Events.B, stateContainer, stateContainer, this.stateDefinitions);

            this.CheckRecord <ExitRecord>(States.A);
            this.CheckRecord <EntryRecord>(States.B);
            this.CheckRecord <EntryRecord>(States.B1);
            this.CheckNoRemainingRecords();
        }
示例#17
0
        public void EntryAction()
        {
            var entered = false;

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

            stateDefinitionBuilder
            .In(States.A)
            .ExecuteOnEntry(() => entered = true);
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A);

            entered.Should().BeTrue("entry action was not executed.");
        }
示例#18
0
        public void InitializeStateWithSubStates()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            stateContainer.SetLastActiveStateFor(States.D, this.stateDefinitions[States.D1]);
            stateContainer.SetLastActiveStateFor(States.D1, this.stateDefinitions[States.D1A]);

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.D);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.D1A));

            this.CheckRecord <EntryRecord>(States.D);
            this.CheckRecord <EntryRecord>(States.D1);
            this.CheckRecord <EntryRecord>(States.D1A);
            this.CheckNoRemainingRecords();
        }
示例#19
0
        public void ParameterizedEntryAction()
        {
            const int Parameter = 3;

            var receivedValue = 0;

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

            stateDefinitionBuilder
            .In(States.A)
            .ExecuteOnEntryParametrized(parameter => receivedValue = parameter, Parameter);
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A);

            receivedValue.Should().Be(Parameter);
        }
        public void ActionsWithoutArguments()
        {
            var executed = false;

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

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.B)
            .Execute(() => executed = true);
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.B, stateContainer, stateContainer, stateDefinitions);

            executed.Should().BeTrue();
        }
        public void ActionsWithOneArgument()
        {
            const int ExpectedValue = 1;
            var       value         = 0;

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

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.B)
            .Execute <int>(v => value = v);
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

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

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.B, ExpectedValue, stateContainer, stateDefinitions);

            value.Should().Be(ExpectedValue);
        }