Exemple #1
0
        public void CustomTypesForStatesAndEvents(
            PassiveStateMachine <MyState, MyEvent> machine,
            bool arrivedInStateB)
        {
            "establish a state machine with custom types for states and events"._(() =>
            {
                machine = new PassiveStateMachine <MyState, MyEvent>();

                machine.In(new MyState("A"))
                .On(new MyEvent(1)).Goto(new MyState("B"));

                machine.In(new MyState("B"))
                .ExecuteOnEntry(() => arrivedInStateB = true);

                machine.Initialize(new MyState("A"));

                machine.Start();
            });

            "when using the state machine"._(() =>
                                             machine.Fire(new MyEvent(1)));

            "it should use equals to compare states and events"._(() =>
                                                                  arrivedInStateB.Should().BeTrue("state B should be current state"));
        }
        public void TransitionActionException()
        {
            "establish a transition action throwing an exception"._(() =>
                                                                    this.machine.In(Values.Source)
                                                                    .On(Values.Event).Goto(Values.Destination).Execute(() =>
            {
                throw Values.Exception;
            }));

            "when executing the transition"._(() =>
            {
                machine.Initialize(Values.Source);
                machine.Start();
                machine.Fire(Values.Event, Values.Parameter);
            });

            this.ItShouldHandleTransitionException();
        }
        public void InitializationInLeafState()
        {
            "when initializing to a leaf state and starting the state machine"._(() =>
            {
                machine.Initialize(LeafState);
                machine.Start();
            });

            "it should set current state of state machine to state to which it is initialized"._(() =>
                                                                                                 this.testExtension.CurrentState
                                                                                                 .Should().Be(LeafState));

            "it should execute entry action of state to which state machine is initialized"._(() =>
                                                                                              this.entryActionOfLeafStateExecuted
                                                                                              .Should().BeTrue());

            "it should execute entry action of super states of the state to which state machine is initialized"._(() =>
                                                                                                                  this.entryActionOfSuperStateExecuted
                                                                                                                  .Should().BeTrue());
        }
        public void CommonAncestor(
            PassiveStateMachine <int, int> machine)
        {
            const int CommonAncestorState       = 0;
            const int SourceState               = 1;
            const int ParentOfSourceState       = 2;
            const int SiblingOfSourceState      = 3;
            const int DestinationState          = 4;
            const int ParentOfDestinationState  = 5;
            const int SiblingOfDestinationState = 6;
            const int Event = 0;

            bool commonAncestorStateLeft = false;

            "establish a hierarchical state machine"._(() =>
            {
                machine = new PassiveStateMachine <int, int>();

                machine.DefineHierarchyOn(CommonAncestorState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(ParentOfSourceState)
                .WithSubState(ParentOfDestinationState);

                machine.DefineHierarchyOn(ParentOfSourceState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(SourceState)
                .WithSubState(SiblingOfSourceState);

                machine.DefineHierarchyOn(ParentOfDestinationState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(DestinationState)
                .WithSubState(SiblingOfDestinationState);

                machine.In(SourceState)
                .On(Event).Goto(DestinationState);

                machine.In(CommonAncestorState)
                .ExecuteOnExit(() => commonAncestorStateLeft = true);

                machine.Initialize(SourceState);
                machine.Start();
            });

            "when firing an event resulting in a transition with a common ancestor"._(() =>
                                                                                      machine.Fire(Event));

            "the state machine should remain inside common ancestor state"._(() =>
                                                                             commonAncestorStateLeft
                                                                             .Should().BeFalse());
        }
Exemple #5
0
        public void Loading(
            StateMachineSaver <State> saver,
            StateMachineLoader <State> loader,
            State sourceState,
            State targetState)
        {
            "establish a saved state machine with history"._(() =>
            {
                var machine = new PassiveStateMachine <State, Event>();
                DefineMachine(machine);
                machine.Initialize(State.A);
                machine.Start();
                machine.Fire(Event.S2);     // set history of super state S
                machine.Fire(Event.B);      // set current state to B

                saver  = new StateMachineSaver <State>();
                loader = new StateMachineLoader <State>();

                machine.Save(saver);
            });

            "when state machine is loaded"._(() =>
            {
                loader.SetCurrentState(saver.CurrentStateId);
                loader.SetHistoryStates(saver.HistoryStates);

                var loadedMachine = new PassiveStateMachine <State, Event>();
                DefineMachine(loadedMachine);
                loadedMachine.Load(loader);

                loadedMachine.TransitionCompleted += (sender, args) =>
                {
                    sourceState = args.StateId;
                    targetState = args.NewStateId;
                };

                loadedMachine.Start();
                loadedMachine.Fire(Event.S);
            });

            "it should reset current state"._(() =>
                                              sourceState.Should().Be(State.B));

            "it should reset all history states of super states"._(() =>
                                                                   targetState.Should().Be(State.S2));
        }
        public void ExecutingTransition(
            PassiveStateMachine <int, int> machine,
            string actualParameter,
            bool exitActionExecuted,
            bool entryActionExecuted)
        {
            "establish a state machine with transitions"._(() =>
            {
                machine = new PassiveStateMachine <int, int>();

                machine.AddExtension(CurrentStateExtension);

                machine.In(SourceState)
                .ExecuteOnExit(() => exitActionExecuted = true)
                .On(Event).Goto(DestinationState).Execute <string>(p => actualParameter = p);

                machine.In(DestinationState)
                .ExecuteOnEntry(() => entryActionExecuted = true);

                machine.Initialize(SourceState);
                machine.Start();
            });

            "when firing an event onto the state machine"._(() =>
                                                            machine.Fire(Event, Parameter));

            "it should_execute_transition_by_switching_state"._(() =>
                                                                CurrentStateExtension.CurrentState.Should().Be(DestinationState));

            "it should_execute_transition_actions"._(() =>
                                                     actualParameter.Should().NotBeNull());

            "it should_pass_parameters_to_transition_action"._(() =>
                                                               actualParameter.Should().Be(Parameter));

            "it should_execute_exit_action_of_source_state"._(() =>
                                                              exitActionExecuted.Should().BeTrue());

            "it should_execute_entry_action_of_destination_state"._(() =>
                                                                    entryActionExecuted.Should().BeTrue());
        }
        public void NoExceptionHandlerRegistered(
            Exception catchedException)
        {
            "establish an exception throwing state machine without a registered exception handler"._(() =>
            {
                machine = new PassiveStateMachine <int, int>();

                machine.In(Values.Source)
                .On(Values.Event).Execute(() =>
                {
                    throw Values.Exception;
                });

                machine.Initialize(Values.Source);
                machine.Start();
            });

            "when an exception occurs"._(() =>
                                         catchedException = Catch.Exception(() => this.machine.Fire(Values.Event)));

            "should (re-)throw exception"._(() =>
                                            catchedException.InnerException
                                            .Should().BeSameAs(Values.Exception));
        }
        public void NoCommonAncestor(
            PassiveStateMachine <string, int> machine)
        {
            const string SourceState                   = "SourceState";
            const string ParentOfSourceState           = "ParentOfSourceState";
            const string SiblingOfSourceState          = "SiblingOfSourceState";
            const string DestinationState              = "DestinationState";
            const string ParentOfDestinationState      = "ParentOfDestinationState";
            const string SiblingOfDestinationState     = "SiblingOfDestinationState";
            const string GrandParentOfSourceState      = "GrandParentOfSourceState";
            const string GrandParentOfDestinationState = "GrandParentOfDestinationState";
            const int    Event = 0;

            string log = string.Empty;

            "establish a hierarchical state machine"._(() =>
            {
                machine = new PassiveStateMachine <string, int>();

                machine.DefineHierarchyOn(ParentOfSourceState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(SourceState)
                .WithSubState(SiblingOfSourceState);

                machine.DefineHierarchyOn(ParentOfDestinationState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(DestinationState)
                .WithSubState(SiblingOfDestinationState);

                machine.DefineHierarchyOn(GrandParentOfSourceState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(ParentOfSourceState);

                machine.DefineHierarchyOn(GrandParentOfDestinationState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(ParentOfDestinationState);

                machine.In(SourceState)
                .ExecuteOnExit(() => log += "exit" + SourceState)
                .On(Event).Goto(DestinationState);

                machine.In(ParentOfSourceState)
                .ExecuteOnExit(() => log += "exit" + ParentOfSourceState);

                machine.In(DestinationState)
                .ExecuteOnEntry(() => log += "enter" + DestinationState);

                machine.In(ParentOfDestinationState)
                .ExecuteOnEntry(() => log += "enter" + ParentOfDestinationState);

                machine.In(GrandParentOfSourceState)
                .ExecuteOnExit(() => log += "exit" + GrandParentOfSourceState);

                machine.In(GrandParentOfDestinationState)
                .ExecuteOnEntry(() => log += "enter" + GrandParentOfDestinationState);

                machine.Initialize(SourceState);
                machine.Start();
            });

            "when firing an event resulting in a transition without a common ancestor"._(() =>
                                                                                         machine.Fire(Event));

            "it should execute exit action of source state"._(() =>
                                                              log.Should().Contain("exit" + SourceState));

            "it should execute exit action of parents of source state (recursively)"._(() =>
                                                                                       log
                                                                                       .Should().Contain("exit" + ParentOfSourceState)
                                                                                       .And.Contain("exit" + GrandParentOfSourceState));

            "it should execute entry action of parents of destination state (recursively)"._(() =>
                                                                                             log.Should().Contain("enter" + ParentOfDestinationState)
                                                                                             .And.Contain("enter" + GrandParentOfDestinationState));

            "it should execute entry action of destination state"._(() =>
                                                                    log.Should().Contain("enter" + DestinationState));

            "it should execute actions from source upwards and then downwards to destination state"._(() =>
            {
                string[] states =
                {
                    SourceState,
                    ParentOfSourceState,
                    GrandParentOfSourceState,
                    GrandParentOfDestinationState,
                    ParentOfDestinationState,
                    DestinationState
                };

                var statesInOrderOfAppearanceInLog = states
                                                     .OrderBy(s => log.IndexOf(s.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal));
                statesInOrderOfAppearanceInLog
                .Should().Equal(states);
            });
        }