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);
        }
        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));
        }
        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));
        }
Beispiel #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 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");
        }
Beispiel #6
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);
        }
Beispiel #7
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);
        }
Beispiel #8
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.");
        }
        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>();
        }
        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.");
        }
        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));
        }
Beispiel #12
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.");
        }
Beispiel #13
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);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="StateMachineTest"/> class.
        /// </summary>
        public StateMachineTest()
        {
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .DefineHierarchyOn(States.B)
            .WithHistoryType(HistoryType.None)
            .WithInitialSubState(States.B1)
            .WithSubState(States.B2);
            stateDefinitionBuilder
            .DefineHierarchyOn(States.C)
            .WithHistoryType(HistoryType.Shallow)
            .WithInitialSubState(States.C2)
            .WithSubState(States.C1);
            stateDefinitionBuilder
            .DefineHierarchyOn(States.C1)
            .WithHistoryType(HistoryType.Shallow)
            .WithInitialSubState(States.C1A)
            .WithSubState(States.C1B);
            stateDefinitionBuilder
            .DefineHierarchyOn(States.D)
            .WithHistoryType(HistoryType.Deep)
            .WithInitialSubState(States.D1)
            .WithSubState(States.D2);
            stateDefinitionBuilder
            .DefineHierarchyOn(States.D1)
            .WithHistoryType(HistoryType.Deep)
            .WithInitialSubState(States.D1A)
            .WithSubState(States.D1B);
            stateDefinitionBuilder
            .In(States.A)
            .ExecuteOnEntry(() => this.RecordEntry(States.A))
            .ExecuteOnExit(() => this.RecordExit(States.A))
            .On(Events.B).Goto(States.B)
            .On(Events.C).Goto(States.C)
            .On(Events.D).Goto(States.D)
            .On(Events.A);
            stateDefinitionBuilder
            .In(States.B)
            .ExecuteOnEntry(() => this.RecordEntry(States.B))
            .ExecuteOnExit(() => this.RecordExit(States.B))
            .On(Events.D).Goto(States.D);
            stateDefinitionBuilder
            .In(States.B1)
            .ExecuteOnEntry(() => this.RecordEntry(States.B1))
            .ExecuteOnExit(() => this.RecordExit(States.B1))
            .On(Events.B2).Goto(States.B2);
            stateDefinitionBuilder
            .In(States.B2)
            .ExecuteOnEntry(() => this.RecordEntry(States.B2))
            .ExecuteOnExit(() => this.RecordExit(States.B2))
            .On(Events.A).Goto(States.A)
            .On(Events.C1B).Goto(States.C1B);
            stateDefinitionBuilder
            .In(States.C)
            .ExecuteOnEntry(() => this.RecordEntry(States.C))
            .ExecuteOnExit(() => this.RecordExit(States.C))
            .On(Events.A).Goto(States.A);
            stateDefinitionBuilder
            .In(States.C1)
            .ExecuteOnEntry(() => this.RecordEntry(States.C1))
            .ExecuteOnExit(() => this.RecordExit(States.C1))
            .On(Events.C1B).Goto(States.C1B);
            stateDefinitionBuilder
            .In(States.C2)
            .ExecuteOnEntry(() => this.RecordEntry(States.C2))
            .ExecuteOnExit(() => this.RecordExit(States.C2));
            stateDefinitionBuilder
            .In(States.C1A)
            .ExecuteOnEntry(() => this.RecordEntry(States.C1A))
            .ExecuteOnExit(() => this.RecordExit(States.C1A));
            stateDefinitionBuilder
            .In(States.C1B)
            .ExecuteOnEntry(() => this.RecordEntry(States.C1B))
            .ExecuteOnExit(() => this.RecordExit(States.C1B));
            stateDefinitionBuilder
            .In(States.D)
            .ExecuteOnEntry(() => this.RecordEntry(States.D))
            .ExecuteOnExit(() => this.RecordExit(States.D));
            stateDefinitionBuilder
            .In(States.D1)
            .ExecuteOnEntry(() => this.RecordEntry(States.D1))
            .ExecuteOnExit(() => this.RecordExit(States.D1));
            stateDefinitionBuilder
            .In(States.D1A)
            .ExecuteOnEntry(() => this.RecordEntry(States.D1A))
            .ExecuteOnExit(() => this.RecordExit(States.D1A));
            stateDefinitionBuilder
            .In(States.D1B)
            .ExecuteOnEntry(() => this.RecordEntry(States.D1B))
            .ExecuteOnExit(() => this.RecordExit(States.D1B))
            .On(Events.A).Goto(States.A)
            .On(Events.B1).Goto(States.B1);
            stateDefinitionBuilder
            .In(States.D2)
            .ExecuteOnEntry(() => this.RecordEntry(States.D2))
            .ExecuteOnExit(() => this.RecordExit(States.D2))
            .On(Events.A).Goto(States.A);
            stateDefinitionBuilder
            .In(States.E)
            .ExecuteOnEntry(() => this.RecordEntry(States.E))
            .ExecuteOnExit(() => this.RecordExit(States.E))
            .On(Events.A).Goto(States.A)
            .On(Events.E).Goto(States.E);
            this.stateDefinitions = stateDefinitionBuilder.Build();
        }