public void LogInitializeTest()
        {
            _loggerMock.Setup(logger => logger.Debug("Initialized StateMachine Test with initial state On"));

            _stateMachine.Initialize(States.On);

            _loggerMock.VerifyAll();
        }
        private void ConfigureStateMachine()
        {
            mToiletStateMachine    = new PassiveStateMachine <ToiletStates, ToiletEvents>();
            mCurrentStateExtension = new CurrentStateExtension();
            mToiletStateMachine.AddExtension(mCurrentStateExtension);

            mToiletStateMachine.In(ToiletStates.WaitingForStart)
            .ExecuteOnEntry(StopStateMachine)
            .On(ToiletEvents.StartStateMachine).Goto(ToiletStates.WaitingForMan);

            mToiletStateMachine.In(ToiletStates.WaitingForMan)
            .ExecuteOnEntry(WaitForMan)
            .On(ToiletEvents.ManArrived).Goto(ToiletStates.ManInfrontOfToilet)
            .On(ToiletEvents.StopStateMachine).Goto(ToiletStates.WaitingForStart);

            mToiletStateMachine.In(ToiletStates.ManInfrontOfToilet)
            .ExecuteOnEntry(ManArrived)
            .On(ToiletEvents.ManPees).Goto(ToiletStates.ManIsPeeing)
            .On(ToiletEvents.ManLeft).Goto(ToiletStates.WaitingForMan)
            .On(ToiletEvents.StopStateMachine).Goto(ToiletStates.WaitingForStart);

            mToiletStateMachine.In(ToiletStates.ManIsPeeing).
            ExecuteOnEntry(ManIsPeeing)
            .On(ToiletEvents.ManLeft).Goto(ToiletStates.PeeingFinished)
            .On(ToiletEvents.StopStateMachine).Goto(ToiletStates.WaitingForStart);

            mToiletStateMachine.In(ToiletStates.PeeingFinished)
            .ExecuteOnEntry(Flush)
            .On(ToiletEvents.FlushFinished).Goto(ToiletStates.WaitingForMan)
            .On(ToiletEvents.StopStateMachine).Goto(ToiletStates.WaitingForStart);

            mToiletStateMachine.Initialize(ToiletStates.WaitingForStart);
            mToiletStateMachine.Start();
        }
Exemple #3
0
        public void EventsQueueing(
            IStateMachine <string, int> machine)
        {
            const int FirstEvent  = 0;
            const int SecondEvent = 1;

            bool arrived = false;

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

                machine.In("A").On(FirstEvent).Goto("B");
                machine.In("B").On(SecondEvent).Goto("C");
                machine.In("C").ExecuteOnEntry(() => arrived = true);

                machine.Initialize("A");
            });

            "when firing an event onto the state machine"._(() =>
            {
                machine.Fire(FirstEvent);
                machine.Fire(SecondEvent);
                machine.Start();
            });

            "it should queue event at the end"._(() =>
                                                 arrived.Should().BeTrue("state machine should arrive at destination state"));
        }
Exemple #4
0
        public void Start(
            PassiveStateMachine <int, int> machine,
            bool entryActionExecuted)
        {
            "establish an initialized state machine".x(() =>
            {
                machine = new PassiveStateMachine <int, int>();

                machine.AddExtension(this.testExtension);

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

                machine.Initialize(TestState);
            });

            "when starting the state machine".x(() =>
                                                machine.Start());

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

            "should execute entry action of state to which state machine is initialized".x(() =>
                                                                                           entryActionExecuted.Should().BeTrue());
        }
Exemple #5
0
        public void CustomTypesForStatesAndEvents(
            PassiveStateMachine <MyState, MyEvent> machine,
            bool arrivedInStateB)
        {
            "establish a state machine with custom types for states and events".x(() =>
            {
                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".x(() =>
                                             machine.Fire(new MyEvent(1)));

            "it should use equals to compare states and events".x(() =>
                                                                  arrivedInStateB.Should().BeTrue("state B should be current state"));
        }
Exemple #6
0
        public void BeforeExecutingEntryActions(
            PassiveStateMachine <string, int> machine,
            IExtension <string, int> extension)
        {
            "establish an extension".x(()
                                       => extension = A.Fake <IExtension <string, int> >());

            "establish a state machine using the extension".x(() =>
            {
                machine = new PassiveStateMachine <string, int>(Name);

                machine.AddExtension(extension);

                machine.In("0")
                .On(1).Goto("1");

                machine.Initialize("0");
                machine.Start();
            });

            "when firing an event onto the state machine".x(()
                                                            => machine.Fire(1));

            "it should call EnteringState on registered extensions for target state".x(()
                                                                                       => A.CallTo(() => extension.EnteringState(
                                                                                                       A <IStateMachineInformation <string, int> > .That.Matches(x => x.Name == Name && x.CurrentStateId == "1"),
                                                                                                       A <IState <string, int> > .That.Matches(x => x.Id == "1"),
                                                                                                       A <ITransitionContext <string, int> > .That.Matches(x => x.EventId.Value == 1)))
                                                                                       .MustHaveHappened());
        }
Exemple #7
0
        public void MatchingGuard(
            PassiveStateMachine <int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            "establish a state machine with guarded transitions".x(() =>
            {
                machine = new PassiveStateMachine <int, int>();

                currentStateExtension = new CurrentStateExtension();
                machine.AddExtension(currentStateExtension);

                machine.In(SourceState)
                .On(Event)
                .If(() => false).Goto(ErrorState)
                .If(() => true).Goto(DestinationState)
                .If(() => true).Goto(ErrorState)
                .Otherwise().Goto(ErrorState);

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

            "when an event is fired".x(() =>
                                       machine.Fire(Event));

            "it should take transition guarded with first matching guard".x(() =>
                                                                            currentStateExtension.CurrentState.Should().Be(DestinationState));
        }
Exemple #8
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"));
        }
Exemple #9
0
        public void OtherwiseGuard(
            PassiveStateMachine <int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            "establish a state machine with otherwise guard and no machting other guard".x(() =>
            {
                machine = new PassiveStateMachine <int, int>();

                currentStateExtension = new CurrentStateExtension();
                machine.AddExtension(currentStateExtension);

                machine.In(SourceState)
                .On(Event)
                .If(() => false).Goto(ErrorState)
                .Otherwise().Goto(DestinationState);

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

            "when an event is fired".x(() =>
                                       machine.Fire(Event));

            "it should_take_transition_guarded_with_otherwise".x(() =>
                                                                 currentStateExtension.CurrentState.Should().Be(DestinationState));
        }
Exemple #10
0
        public void NoMatchingGuard(
            PassiveStateMachine <int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            bool declined = false;

            "establish state machine with no matching guard".x(() =>
            {
                machine = new PassiveStateMachine <int, int>();

                currentStateExtension = new CurrentStateExtension();
                machine.AddExtension(currentStateExtension);

                machine.In(SourceState)
                .On(Event)
                .If(() => false).Goto(ErrorState);

                machine.TransitionDeclined += (sender, e) => declined = true;

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

            "when an event is fired".x(() =>
                                       machine.Fire(Event));

            "it should notify about declined transition".x(() =>
                                                           declined.Should().BeTrue("TransitionDeclined event should be fired"));
        }
Exemple #11
0
        public void MatchingGuard(
            PassiveStateMachine<int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            "establish a state machine with guarded transitions"._(() =>
            {
                machine = new PassiveStateMachine<int, int>();

                currentStateExtension = new CurrentStateExtension();
                machine.AddExtension(currentStateExtension);

                machine.In(SourceState)
                    .On(Event)
                        .If(() => false).Goto(ErrorState)
                        .If(() => true).Goto(DestinationState)
                        .If(() => true).Goto(ErrorState)
                        .Otherwise().Goto(ErrorState);

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

            "when an event is fired"._(() =>
                machine.Fire(Event));

            "it should take transition guarded with first matching guard"._(() =>
                currentStateExtension.CurrentState.Should().Be(DestinationState));
        }
Exemple #12
0
        public void Reinitialization(
            PassiveStateMachine <int, int> machine,
            Exception receivedException)
        {
            "establish an initialized state machine".x(() =>
            {
                machine = new PassiveStateMachine <int, int>();
                machine.Initialize(TestState);
            });

            "when state machine is initialized again".x(() =>
            {
                try
                {
                    machine.Initialize(TestState);
                }
                catch (Exception e)
                {
                    receivedException = e;
                }
            });

            "should throw an invalid operation exception".x(() =>
            {
                receivedException
                .Should().BeAssignableTo <InvalidOperationException>();
                receivedException.Message
                .Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized);
            });
        }
Exemple #13
0
        public void NoMatchingGuard(
            PassiveStateMachine<int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            bool declined = false;

            "establish state machine with no matching guard"._(() =>
                {
                    machine = new PassiveStateMachine<int, int>();

                    currentStateExtension = new CurrentStateExtension();
                    machine.AddExtension(currentStateExtension);

                    machine.In(SourceState)
                        .On(Event)
                            .If(() => false).Goto(ErrorState);

                    machine.TransitionDeclined += (sender, e) => declined = true;

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

            "when an event is fired"._(() =>
                machine.Fire(Event));

            "it should notify about declined transition"._(() =>
                declined.Should().BeTrue("TransitionDeclined event should be fired"));
        }
        public void Report()
        {
            var elevator = new PassiveStateMachine <States, Events>("Elevator");

            elevator.DefineHierarchyOn(States.Healthy, States.OnFloor, HistoryType.Deep, States.OnFloor, States.Moving);
            elevator.DefineHierarchyOn(States.Moving, States.MovingUp, HistoryType.Shallow, States.MovingUp, States.MovingDown);
            elevator.DefineHierarchyOn(States.OnFloor, States.DoorClosed, HistoryType.None, States.DoorClosed, States.DoorOpen);

            elevator.In(States.Healthy)
            .On(Events.ErrorOccured).Goto(States.Error);

            elevator.In(States.Error)
            .On(Events.Reset).Goto(States.Healthy)
            .On(Events.ErrorOccured);

            elevator.In(States.OnFloor)
            .ExecuteOnEntry(AnnounceFloor)
            .ExecuteOnExit(Beep, Beep)
            .On(Events.CloseDoor).Goto(States.DoorClosed)
            .On(Events.OpenDoor).Goto(States.DoorOpen)
            .On(Events.GoUp)
            .If(CheckOverload).Goto(States.MovingUp)
            .Otherwise().Execute(AnnounceOverload, Beep)
            .On(Events.GoDown)
            .If(CheckOverload).Goto(States.MovingDown)
            .Otherwise().Execute(AnnounceOverload);

            elevator.In(States.Moving)
            .On(Events.Stop).Goto(States.OnFloor);

            elevator.Initialize(States.OnFloor);

            elevator.Report(this.testee);

            string statesReport;
            string transitionsReport;

            this.stateStream.Position = 0;
            using (var reader = new StreamReader(this.stateStream))
            {
                statesReport = reader.ReadToEnd();
            }

            this.transitionsStream.Position = 0;
            using (var reader = new StreamReader(this.transitionsStream))
            {
                transitionsReport = reader.ReadToEnd();
            }

            const string ExpectedStatesReport      = "Source;Entry;Exit;ChildrenOnFloor;AnnounceFloor;Beep, Beep;DoorClosed, DoorOpenMoving;;;MovingUp, MovingDownHealthy;;;OnFloor, MovingMovingUp;;;MovingDown;;;DoorClosed;;;DoorOpen;;;Error;;;";
            const string ExpectedTransitionsReport = "Source;Event;Guard;Target;ActionsOnFloor;CloseDoor;;DoorClosed;OnFloor;OpenDoor;;DoorOpen;OnFloor;GoUp;CheckOverload;MovingUp;OnFloor;GoUp;;internal transition;AnnounceOverload, BeepOnFloor;GoDown;CheckOverload;MovingDown;OnFloor;GoDown;;internal transition;AnnounceOverloadMoving;Stop;;OnFloor;Healthy;ErrorOccured;;Error;Error;Reset;;Healthy;Error;ErrorOccured;;internal transition;";

            statesReport.Replace("\n", string.Empty).Replace("\r", string.Empty)
            .Should().Be(ExpectedStatesReport.Replace("\n", string.Empty).Replace("\r", string.Empty));

            transitionsReport.Replace("\n", string.Empty).Replace("\r", string.Empty)
            .Should().Be(ExpectedTransitionsReport.Replace("\n", string.Empty).Replace("\r", string.Empty));
        }
Exemple #15
0
        public void CanStartFSM()
        {
            fsm = new PassiveStateMachine <SM.ProcessState, SM.Command>();

            fsm.Initialize(SM.ProcessState.Initial);
            fsm.Fire(SM.Command.OnOpenBattleFront);
            fsm.Start();

            Assert.IsTrue(fsm.IsRunning);
        }
Exemple #16
0
        public void Loading(
            StateMachineSaver <State> saver,
            StateMachineLoader <State> loader,
            FakeExtension extension,
            State sourceState,
            State targetState)
        {
            "establish a saved state machine with history".x(() =>
            {
                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".x(() =>
            {
                loader.SetCurrentState(saver.CurrentStateId);
                loader.SetHistoryStates(saver.HistoryStates);

                extension         = new FakeExtension();
                var loadedMachine = new PassiveStateMachine <State, Event>();
                loadedMachine.AddExtension(extension);

                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".x(() =>
                                              sourceState.Should().Be(State.B));

            "it should reset all history states of super states".x(() =>
                                                                   targetState.Should().Be(State.S2));

            "it should notify extensions".x(()
                                            => extension.LoadedCurrentState
                                            .Should().BeEquivalentTo(State.B));
        }
Exemple #17
0
        public void SimpleTransition()
        {
            fsm = new PassiveStateMachine <SM.ProcessState, SM.Command>();

            fsm.Initialize(SM.ProcessState.Initial);
            fsm.Fire(SM.Command.OnOpenBattleFront);
            fsm.Start();

            fsm.Fire(SM.Command.OnOuterDoorDown);

            Assert.IsTrue(fsm.IsRunning);
        }
Exemple #18
0
        public static void Main()
        {
            // configure basic logging (all levels enabled, messages are written to the console)
            log4net.Config.BasicConfigurator.Configure();

            var elevator = new PassiveStateMachine <States, Events>("Elevator");

            elevator.AddExtension(new Extensions.Log4NetExtension <States, Events>("Elevator"));

            elevator.DefineHierarchyOn(States.Healthy, States.OnFloor, HistoryType.Deep, States.OnFloor, States.Moving);
            elevator.DefineHierarchyOn(States.Moving, States.MovingUp, HistoryType.Shallow, States.MovingUp, States.MovingDown);
            elevator.DefineHierarchyOn(States.OnFloor, States.DoorClosed, HistoryType.None, States.DoorClosed, States.DoorOpen);

            elevator.In(States.Healthy)
            .On(Events.ErrorOccured).Goto(States.Error);

            elevator.In(States.Error)
            .On(Events.Reset).Goto(States.Healthy);

            elevator.In(States.OnFloor)
            .ExecuteOnEntry(AnnounceFloor)
            .On(Events.CloseDoor).Goto(States.DoorClosed)
            .On(Events.OpenDoor).Goto(States.DoorOpen)
            .On(Events.GoUp)
            .If(CheckOverload).Goto(States.MovingUp)
            .Otherwise().Execute(AnnounceOverload)
            .On(Events.GoDown)
            .If(CheckOverload).Goto(States.MovingDown)
            .Otherwise().Execute(AnnounceOverload);

            elevator.In(States.Moving)
            .On(Events.Stop).Goto(States.OnFloor);

            elevator.Initialize(States.OnFloor);

            elevator.Fire(Events.ErrorOccured);
            elevator.Fire(Events.Reset);

            elevator.Start();

            elevator.Fire(Events.OpenDoor);
            elevator.Fire(Events.CloseDoor);
            elevator.Fire(Events.GoUp);
            elevator.Fire(Events.Stop);
            elevator.Fire(Events.OpenDoor);

            elevator.Stop();

            Console.ReadLine();
        }
        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());
        }
        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());
        }
        public void YEdGraphML()
        {
            var elevator = new PassiveStateMachine <States, Events>("Elevator");

            elevator.DefineHierarchyOn(States.Healthy, States.OnFloor, HistoryType.Deep, States.OnFloor, States.Moving);
            elevator.DefineHierarchyOn(States.Moving, States.MovingUp, HistoryType.Shallow, States.MovingUp, States.MovingDown);
            elevator.DefineHierarchyOn(States.OnFloor, States.DoorClosed, HistoryType.None, States.DoorClosed, States.DoorOpen);

            elevator.In(States.Healthy)
            .On(Events.ErrorOccured).Goto(States.Error);

            elevator.In(States.Error)
            .On(Events.Reset).Goto(States.Healthy)
            .On(Events.ErrorOccured);

            elevator.In(States.OnFloor)
            .ExecuteOnEntry(AnnounceFloor)
            .ExecuteOnExit(Beep, Beep)
            .On(Events.CloseDoor).Goto(States.DoorClosed)
            .On(Events.OpenDoor).Goto(States.DoorOpen)
            .On(Events.GoUp)
            .If(CheckOverload).Goto(States.MovingUp)
            .Otherwise().Execute(AnnounceOverload, Beep)
            .On(Events.GoDown)
            .If(CheckOverload).Goto(States.MovingDown)
            .Otherwise().Execute(AnnounceOverload);

            elevator.In(States.Moving)
            .On(Events.Stop).Goto(States.OnFloor);

            elevator.Initialize(States.OnFloor);

            var stream     = new MemoryStream();
            var textWriter = new StreamWriter(stream);
            var testee     = new YEdStateMachineReportGenerator <States, Events>(textWriter);

            elevator.Report(testee);

            stream.Position = 0;
            var reader = new StreamReader(stream);
            var report = reader.ReadToEnd();

            const string ExpectedReport = "<?xml version=\"1.0\" encoding=\"utf-8\"?><graphml xmlns:y=\"http://www.yworks.com/xml/graphml\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:yed=\"http://www.yworks.com/xml/yed/3\" xmlns:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd\" xmlns=\"http://graphml.graphdrawing.org/xmlns\">  <!--Created by Appccelerate.StateMachine.YEdStateMachineReportGenerator-->  <key for=\"graphml\" id=\"d0\" yfiles.type=\"resources\" />  <key for=\"port\" id=\"d1\" yfiles.type=\"portgraphics\" />  <key for=\"port\" id=\"d2\" yfiles.type=\"portgeometry\" />  <key for=\"port\" id=\"d3\" yfiles.type=\"portuserdata\" />  <key attr.name=\"url\" attr.type=\"string\" for=\"node\" id=\"d4\" />  <key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"d5\" />  <key for=\"node\" id=\"d6\" yfiles.type=\"nodegraphics\" />  <key attr.name=\"Beschreibung\" attr.type=\"string\" for=\"graph\" id=\"d7\">    <default />  </key>  <key attr.name=\"url\" attr.type=\"string\" for=\"edge\" id=\"d8\" />  <key attr.name=\"description\" attr.type=\"string\" for=\"edge\" id=\"d9\" />  <key for=\"edge\" id=\"d10\" yfiles.type=\"edgegraphics\" />  <graph edgedefault=\"directed\" id=\"G\">    <node id=\"Healthy\">      <data key=\"d6\">        <y:ProxyAutoBoundsNode>          <y:Realizers active=\"0\">            <y:GroupNode>              <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">Healthy</y:NodeLabel>              <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" />            </y:GroupNode>          </y:Realizers>        </y:ProxyAutoBoundsNode>      </data>      <graph edgedefault=\"directed\" id=\"Healthy:\">        <node id=\"OnFloor\">          <data key=\"d6\">            <y:ProxyAutoBoundsNode>              <y:Realizers active=\"0\">                <y:GroupNode>                  <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">(AnnounceFloor)OnFloor(Beep, Beep)</y:NodeLabel>                  <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" />                  <y:BorderStyle width=\"2.0\" />                </y:GroupNode>              </y:Realizers>            </y:ProxyAutoBoundsNode>          </data>          <graph edgedefault=\"directed\" id=\"OnFloor:\">            <node id=\"DoorClosed\">              <data key=\"d6\">                <y:ShapeNode>                  <y:NodeLabel>DoorClosed</y:NodeLabel>                  <y:Shape type=\"ellipse\" />                  <y:BorderStyle width=\"2.0\" />                </y:ShapeNode>              </data>            </node>            <node id=\"DoorOpen\">              <data key=\"d6\">                <y:ShapeNode>                  <y:NodeLabel>DoorOpen</y:NodeLabel>                  <y:Shape type=\"ellipse\" />                </y:ShapeNode>              </data>            </node>          </graph>        </node>        <node id=\"Moving\">          <data key=\"d6\">            <y:ProxyAutoBoundsNode>              <y:Realizers active=\"0\">                <y:GroupNode>                  <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">Moving</y:NodeLabel>                  <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" />                </y:GroupNode>              </y:Realizers>            </y:ProxyAutoBoundsNode>          </data>          <graph edgedefault=\"directed\" id=\"Moving:\">            <node id=\"MovingUp\">              <data key=\"d6\">                <y:ShapeNode>                  <y:NodeLabel>MovingUp</y:NodeLabel>                  <y:Shape type=\"ellipse\" />                  <y:BorderStyle width=\"2.0\" />                </y:ShapeNode>              </data>            </node>            <node id=\"MovingDown\">              <data key=\"d6\">                <y:ShapeNode>                  <y:NodeLabel>MovingDown</y:NodeLabel>                  <y:Shape type=\"ellipse\" />                </y:ShapeNode>              </data>            </node>          </graph>        </node>      </graph>    </node>    <node id=\"Error\">      <data key=\"d6\">        <y:ShapeNode>          <y:NodeLabel>Error</y:NodeLabel>          <y:Shape type=\"ellipse\" />        </y:ShapeNode>      </data>    </node>    <edge id=\"CloseDoor0\" source=\"OnFloor\" target=\"DoorClosed\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>CloseDoor</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"OpenDoor1\" source=\"OnFloor\" target=\"DoorOpen\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>OpenDoor</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"GoUp2\" source=\"OnFloor\" target=\"MovingUp\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>[CheckOverload]GoUp</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"GoUp3\" source=\"OnFloor\" target=\"OnFloor\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"dashed\" />          <y:Arrows source=\"none\" target=\"plain\" />          <y:EdgeLabel>GoUp(AnnounceOverload, Beep)</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"GoDown4\" source=\"OnFloor\" target=\"MovingDown\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>[CheckOverload]GoDown</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"GoDown5\" source=\"OnFloor\" target=\"OnFloor\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"dashed\" />          <y:Arrows source=\"none\" target=\"plain\" />          <y:EdgeLabel>GoDown(AnnounceOverload)</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"Stop6\" source=\"Moving\" target=\"OnFloor\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>Stop</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"ErrorOccured7\" source=\"Healthy\" target=\"Error\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>ErrorOccured</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"Reset8\" source=\"Error\" target=\"Healthy\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>Reset</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"ErrorOccured9\" source=\"Error\" target=\"Error\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"dashed\" />          <y:Arrows source=\"none\" target=\"plain\" />          <y:EdgeLabel>ErrorOccured</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>  </graph>  <data key=\"d0\">    <y:Resources />  </data></graphml>";

            var cleanedReport = report.Replace("\n", string.Empty).Replace("\r", string.Empty);

            cleanedReport.Should().Be(ExpectedReport.Replace("\n", string.Empty).Replace("\r", string.Empty));
        }
Exemple #22
0
        private void createStateMachine()
        {
            fsm = new PassiveStateMachine <States, Events>();
            fsm.In(States.Edit)
            .On(Events.InventoryKey).Goto(States.Inventory)
            .On(Events.PlayKey).Goto(States.Play);

            fsm.In(States.Inventory).On(Events.InventoryKey).Goto(States.Edit);

            fsm.In(States.Play).On(Events.PlayKey).Goto(States.Edit);


            foreach (var s in Enum.GetValues(typeof(States)).Cast <States>())
            {
                fsm.In(s).ExecuteOnEntry(new Action(() => ActiveState = s));
            }

            fsm.Initialize(States.Edit);
        }
Exemple #23
0
        public void BeforeExecutingEntryActionsHierarchical(
            PassiveStateMachine <string, string> machine,
            IExtension <string, string> extension)
        {
            "establish an extension".x(()
                                       => extension = A.Fake <IExtension <string, string> >());

            "establish a hierarchical state machine using the extension".x(() =>
            {
                machine = new PassiveStateMachine <string, string>(Name);

                machine.AddExtension(extension);

                machine.DefineHierarchyOn("A")
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState("A0");

                machine.In("0")
                .On("A0").Goto("A0");

                machine.Initialize("0");
                machine.Start();
            });

            "when firing an event onto the state machine".x(()
                                                            => machine.Fire("A0"));

            "it should call EnteringState on registered extensions for entered super states of target state".x(()
                                                                                                               => A.CallTo(() => extension.EnteringState(
                                                                                                                               A <IStateMachineInformation <string, string> > .That.Matches(x => x.Name == Name && x.CurrentStateId == "A0"),
                                                                                                                               A <IState <string, string> > .That.Matches(x => x.Id == "A"),
                                                                                                                               A <ITransitionContext <string, string> > .That.Matches(x => x.EventId.Value == "A0")))
                                                                                                               .MustHaveHappened());

            "it should call EnteringState on registered extensions for entered leaf target state".x(()
                                                                                                    => A.CallTo(() => extension.EnteringState(
                                                                                                                    A <IStateMachineInformation <string, string> > .That.Matches(x => x.Name == Name && x.CurrentStateId == "A0"),
                                                                                                                    A <IState <string, string> > .That.Matches(x => x.Id == "A0"),
                                                                                                                    A <ITransitionContext <string, string> > .That.Matches(x => x.EventId.Value == "A0")))
                                                                                                    .MustHaveHappened());
        }
Exemple #24
0
        public void ExecutingTransition(
            PassiveStateMachine <int, int> machine,
            string actualParameter,
            bool exitActionExecuted,
            bool entryActionExecuted)
        {
            "establish a state machine with transitions".x(() =>
            {
                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".x(() =>
                                                            machine.Fire(Event, Parameter));

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

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

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

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

            "it should_execute_entry_action_of_destination_state".x(() =>
                                                                    entryActionExecuted.Should().BeTrue());
        }
        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());
        }
Exemple #26
0
        public void LoadingAnInitializedStateMachine(
            PassiveStateMachine <string, int> machine,
            Exception receivedException)
        {
            "establish an initialized state machine".x(() =>
            {
                machine = new PassiveStateMachine <string, int>();
                machine.Initialize("initial");
            });

            "when state machine is loaded".x(() =>
            {
                receivedException = Catch.Exception(() => machine.Load(A.Fake <IStateMachineLoader <string> >()));
            });

            "it should throw invalid operation exception".x(() =>
            {
                receivedException.Should().BeOfType <InvalidOperationException>();
                receivedException.Message.Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized);
            });
        }
Exemple #27
0
        public ApplicationStateMachine(ApplicationCommands commands)
        {
            // in uninitialized state
            _fsm.In(ApplicationState.Uninitialized)
            .On(ApplicationStateEvent.ChangeVideoDevice)
            .Goto(ApplicationState.Uninitialized);
            _fsm.In(ApplicationState.Uninitialized)
            .On(ApplicationStateEvent.Start)
            .Goto(ApplicationState.Running)
            .Execute(commands.StartFaceDetection);
            _fsm.In(ApplicationState.Uninitialized)
            .On(ApplicationStateEvent.Stop)
            .Goto(ApplicationState.Uninitialized);
            // in running state
            _fsm.In(ApplicationState.Running)
            .On(ApplicationStateEvent.ChangeVideoDevice)
            .Goto(ApplicationState.Running)
            .Execute(commands.ChangeVideoCaptureDevice);
            _fsm.In(ApplicationState.Running)
            .On(ApplicationStateEvent.Stop)
            .Goto(ApplicationState.Terminated)
            .Execute(commands.StopFaceDetection);
            _fsm.In(ApplicationState.Running)
            .On(ApplicationStateEvent.Start)
            .Goto(ApplicationState.Running);
            // in terminated state
            _fsm.In(ApplicationState.Terminated)
            .On(ApplicationStateEvent.ChangeVideoDevice)
            .Goto(ApplicationState.Terminated);
            _fsm.In(ApplicationState.Terminated)
            .On(ApplicationStateEvent.Stop)
            .Goto(ApplicationState.Terminated);
            _fsm.In(ApplicationState.Terminated)
            .On(ApplicationStateEvent.Start)
            .Goto(ApplicationState.Running)
            .Execute(commands.StartFaceDetection);

            _fsm.Initialize(ApplicationState.Uninitialized);
            _fsm.Start();
        }
        /// <summary>
        ///     Constructor
        /// </summary>
        /// <param name="objective"></param>
        /// <param name="tier"></param>
        public BattlefieldObjective(RegionMgr region, BattleFront_Objective objective)
        {
            Id       = objective.Entry;
            Name     = objective.Name;
            ZoneId   = objective.ZoneId;
            RegionId = objective.RegionId;
            Tier     = (byte)region.GetTier();
            State    = StateFlags.Unsecure;

            _x            = (uint)objective.X;
            _y            = (uint)objective.Y;
            _z            = (ushort)objective.Z;
            _o            = (ushort)objective.O;
            _tokdiscovery = objective.TokDiscovered;
            _tokunlocked  = objective.TokUnlocked;

            Heading         = _o;
            WorldPosition.X = (int)_x;
            WorldPosition.Y = (int)_y;
            WorldPosition.Z = _z;

            CommsEngine   = new ApocCommunications();
            RewardManager = new RVRRewardManager();
            fsm           = new CampaignObjectiveStateMachine(this).fsm;
            fsm.Initialize(CampaignObjectiveStateMachine.ProcessState.Neutral);
            if (objective.Guards != null)
            {
                foreach (BattleFront_Guard Guard in objective.Guards)
                {
                    Guards.Add(new FlagGuard(this, region, objective.ZoneId, Guard.OrderId, Guard.DestroId, Guard.X, Guard.Y, Guard.Z, Guard.O));
                }
            }
            _captureProgress = 20000;
            CaptureDuration  = 10;
            EvtInterface.AddEvent(CheckTimers, 1000, 0);
            BuffId = 0;
        }
Exemple #29
0
        private PassiveStateMachine <States, Events> createStateMachine(Timer timer)
        {
            var fsm = new PassiveStateMachine <States, Events>();

            fsm.AddExtension(new ConsoleLoggingExtension <States, Events>());

            fsm.Initialize(States.None);


            fsm.In(States.None).On(Events.SingleSlotPressed).Goto(States.Holding);

            fsm.In(States.Holding).ExecuteOnEntry(timer.Start);
            fsm.In(States.Holding).ExecuteOnExit(timer.Stop);
            fsm.In(States.Holding)
            .On(Events.MultipleSlotPressed).Goto(States.None);
            fsm.In(States.Holding)
            .On(Events.NoSlotPressed).Goto(States.None);
            fsm.In(States.Holding)
            .On(Events.Timer).Goto(States.Complete).Execute(SelectTargetedInventoryItem);

            fsm.In(States.Complete).On(Events.NoSlotPressed).Goto(States.None);

            return(fsm);
        }
Exemple #30
0
        public static void Main()
        {
            // configure basic logging (all levels enabled, messages are written to the console)
            log4net.Config.BasicConfigurator.Configure();

            var elevator = new PassiveStateMachine<States, Events>("Elevator");
            elevator.AddExtension(new Extensions.Log4NetExtension<States, Events>("Elevator"));

            elevator.DefineHierarchyOn(States.Healthy, States.OnFloor, HistoryType.Deep, States.OnFloor, States.Moving);
            elevator.DefineHierarchyOn(States.Moving, States.MovingUp, HistoryType.Shallow, States.MovingUp, States.MovingDown);
            elevator.DefineHierarchyOn(States.OnFloor, States.DoorClosed, HistoryType.None, States.DoorClosed, States.DoorOpen);

            elevator.In(States.Healthy)
                .On(Events.ErrorOccured).Goto(States.Error);

            elevator.In(States.Error)
                .On(Events.Reset).Goto(States.Healthy);

            elevator.In(States.OnFloor)
                .ExecuteOnEntry(AnnounceFloor)
                .On(Events.CloseDoor).Goto(States.DoorClosed)
                .On(Events.OpenDoor).Goto(States.DoorOpen)
                .On(Events.GoUp)
                    .If(CheckOverload).Goto(States.MovingUp)
                    .Otherwise().Execute(AnnounceOverload)
                .On(Events.GoDown)
                    .If(CheckOverload).Goto(States.MovingDown)
                    .Otherwise().Execute(AnnounceOverload);

            elevator.In(States.Moving)
                .On(Events.Stop).Goto(States.OnFloor);

            elevator.Initialize(States.OnFloor);

            elevator.Fire(Events.ErrorOccured);
            elevator.Fire(Events.Reset);

            elevator.Start();

            elevator.Fire(Events.OpenDoor);
            elevator.Fire(Events.CloseDoor);
            elevator.Fire(Events.GoUp);
            elevator.Fire(Events.Stop);
            elevator.Fire(Events.OpenDoor);

            elevator.Stop();

            Console.ReadLine();
        }
        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);
            });
        }
        public void YEdGraphML()
        {
            var elevator = new PassiveStateMachine<States, Events>("Elevator");

            elevator.DefineHierarchyOn(States.Healthy)
                .WithHistoryType(HistoryType.Deep)
                .WithInitialSubState(States.OnFloor)
                .WithSubState(States.Moving);

            elevator.DefineHierarchyOn(States.Moving)
                .WithHistoryType(HistoryType.Shallow)
                .WithInitialSubState(States.MovingUp)
                .WithSubState(States.MovingDown);

            elevator.DefineHierarchyOn(States.OnFloor)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(States.DoorClosed)
                .WithSubState(States.DoorOpen);

            elevator.In(States.Healthy)
                .On(Events.ErrorOccured).Goto(States.Error);

            elevator.In(States.Error)
                .On(Events.Reset).Goto(States.Healthy)
                .On(Events.ErrorOccured);

            elevator.In(States.OnFloor)
                .ExecuteOnEntry(AnnounceFloor)
                .ExecuteOnExit(Beep)
                .ExecuteOnExit(Beep)
                .On(Events.CloseDoor).Goto(States.DoorClosed)
                .On(Events.OpenDoor).Goto(States.DoorOpen)
                .On(Events.GoUp)
                    .If(CheckOverload).Goto(States.MovingUp)
                    .Otherwise()
                        .Execute(AnnounceOverload)
                        .Execute(Beep)
                .On(Events.GoDown)
                    .If(CheckOverload).Goto(States.MovingDown)
                    .Otherwise().Execute(AnnounceOverload);

            elevator.In(States.Moving)
                .On(Events.Stop).Goto(States.OnFloor);

            elevator.Initialize(States.OnFloor);

            var stream = new MemoryStream();
            var textWriter = new StreamWriter(stream);
            var testee = new YEdStateMachineReportGenerator<States, Events>(textWriter);

            elevator.Report(testee);

            stream.Position = 0;
            var reader = new StreamReader(stream);
            var report = reader.ReadToEnd();

            const string ExpectedReport = "<?xml version=\"1.0\" encoding=\"utf-8\"?><graphml xmlns:y=\"http://www.yworks.com/xml/graphml\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:yed=\"http://www.yworks.com/xml/yed/3\" xmlns:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd\" xmlns=\"http://graphml.graphdrawing.org/xmlns\">  <!--Created by Appccelerate.StateMachine.YEdStateMachineReportGenerator-->  <key for=\"graphml\" id=\"d0\" yfiles.type=\"resources\" />  <key for=\"port\" id=\"d1\" yfiles.type=\"portgraphics\" />  <key for=\"port\" id=\"d2\" yfiles.type=\"portgeometry\" />  <key for=\"port\" id=\"d3\" yfiles.type=\"portuserdata\" />  <key attr.name=\"url\" attr.type=\"string\" for=\"node\" id=\"d4\" />  <key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"d5\" />  <key for=\"node\" id=\"d6\" yfiles.type=\"nodegraphics\" />  <key attr.name=\"Beschreibung\" attr.type=\"string\" for=\"graph\" id=\"d7\">    <default />  </key>  <key attr.name=\"url\" attr.type=\"string\" for=\"edge\" id=\"d8\" />  <key attr.name=\"description\" attr.type=\"string\" for=\"edge\" id=\"d9\" />  <key for=\"edge\" id=\"d10\" yfiles.type=\"edgegraphics\" />  <graph edgedefault=\"directed\" id=\"G\">    <node id=\"Healthy\">      <data key=\"d6\">        <y:ProxyAutoBoundsNode>          <y:Realizers active=\"0\">            <y:GroupNode>              <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">Healthy</y:NodeLabel>              <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" />            </y:GroupNode>          </y:Realizers>        </y:ProxyAutoBoundsNode>      </data>      <graph edgedefault=\"directed\" id=\"Healthy:\">        <node id=\"OnFloor\">          <data key=\"d6\">            <y:ProxyAutoBoundsNode>              <y:Realizers active=\"0\">                <y:GroupNode>                  <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">(AnnounceFloor)OnFloor(Beep, Beep)</y:NodeLabel>                  <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" />                  <y:BorderStyle width=\"2.0\" />                </y:GroupNode>              </y:Realizers>            </y:ProxyAutoBoundsNode>          </data>          <graph edgedefault=\"directed\" id=\"OnFloor:\">            <node id=\"DoorClosed\">              <data key=\"d6\">                <y:ShapeNode>                  <y:NodeLabel>DoorClosed</y:NodeLabel>                  <y:Shape type=\"ellipse\" />                  <y:BorderStyle width=\"2.0\" />                </y:ShapeNode>              </data>            </node>            <node id=\"DoorOpen\">              <data key=\"d6\">                <y:ShapeNode>                  <y:NodeLabel>DoorOpen</y:NodeLabel>                  <y:Shape type=\"ellipse\" />                </y:ShapeNode>              </data>            </node>          </graph>        </node>        <node id=\"Moving\">          <data key=\"d6\">            <y:ProxyAutoBoundsNode>              <y:Realizers active=\"0\">                <y:GroupNode>                  <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">Moving</y:NodeLabel>                  <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" />                </y:GroupNode>              </y:Realizers>            </y:ProxyAutoBoundsNode>          </data>          <graph edgedefault=\"directed\" id=\"Moving:\">            <node id=\"MovingUp\">              <data key=\"d6\">                <y:ShapeNode>                  <y:NodeLabel>MovingUp</y:NodeLabel>                  <y:Shape type=\"ellipse\" />                  <y:BorderStyle width=\"2.0\" />                </y:ShapeNode>              </data>            </node>            <node id=\"MovingDown\">              <data key=\"d6\">                <y:ShapeNode>                  <y:NodeLabel>MovingDown</y:NodeLabel>                  <y:Shape type=\"ellipse\" />                </y:ShapeNode>              </data>            </node>          </graph>        </node>      </graph>    </node>    <node id=\"Error\">      <data key=\"d6\">        <y:ShapeNode>          <y:NodeLabel>Error</y:NodeLabel>          <y:Shape type=\"ellipse\" />        </y:ShapeNode>      </data>    </node>    <edge id=\"ErrorOccured0\" source=\"Healthy\" target=\"Error\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>ErrorOccured</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"CloseDoor1\" source=\"OnFloor\" target=\"DoorClosed\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>CloseDoor</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"OpenDoor2\" source=\"OnFloor\" target=\"DoorOpen\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>OpenDoor</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"GoUp3\" source=\"OnFloor\" target=\"MovingUp\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>[CheckOverload]GoUp</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"GoUp4\" source=\"OnFloor\" target=\"OnFloor\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"dashed\" />          <y:Arrows source=\"none\" target=\"plain\" />          <y:EdgeLabel>GoUp(AnnounceOverload, Beep)</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"GoDown5\" source=\"OnFloor\" target=\"MovingDown\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>[CheckOverload]GoDown</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"GoDown6\" source=\"OnFloor\" target=\"OnFloor\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"dashed\" />          <y:Arrows source=\"none\" target=\"plain\" />          <y:EdgeLabel>GoDown(AnnounceOverload)</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"Stop7\" source=\"Moving\" target=\"OnFloor\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>Stop</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"Reset8\" source=\"Error\" target=\"Healthy\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"line\" />          <y:Arrows source=\"none\" target=\"standard\" />          <y:EdgeLabel>Reset</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>    <edge id=\"ErrorOccured9\" source=\"Error\" target=\"Error\">      <data key=\"d10\">        <y:PolyLineEdge>          <y:LineStyle type=\"dashed\" />          <y:Arrows source=\"none\" target=\"plain\" />          <y:EdgeLabel>ErrorOccured</y:EdgeLabel>        </y:PolyLineEdge>      </data>    </edge>  </graph>  <data key=\"d0\">    <y:Resources />  </data></graphml>";

            var cleanedReport = report.Replace("\n", string.Empty).Replace("\r", string.Empty);

            cleanedReport.Should().Be(ExpectedReport.Replace("\n", string.Empty).Replace("\r", string.Empty));
        }
        public void PriorityEventsQueueing(
            IStateMachine<string, int> machine)
        {
            const int FirstEvent = 0;
            const int SecondEvent = 1;

            bool arrived = false;

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

                machine.In("A").On(SecondEvent).Goto("B");
                machine.In("B").On(FirstEvent).Goto("C");
                machine.In("C").ExecuteOnEntry(() => arrived = true);

                machine.Initialize("A");
            });

            "when firing a priority event onto the state machine"._(() =>
            {
                machine.Fire(FirstEvent);
                machine.FirePriority(SecondEvent);
                machine.Start();
            });

            "it should queue event at the front"._(() =>
                arrived.Should().BeTrue("state machine should arrive at destination state"));
        }
Exemple #34
0
        public Robot()
        {
            #region State machine definition
            StateMachine.In(State.NotInitialized)
            .On(Triggers.InitializationStarts).Goto(State.Initializing);

            StateMachine.In(State.Initializing)
            .On(Triggers.InitializationEnds).Goto(State.PowerOn);

            StateMachine.In(State.PowerOn)
            .On(Triggers.ExecutionStarts).Goto(State.Processing);

            StateMachine.In(State.Processing)
            .On(Triggers.ExecutionEnds).Goto(State.PowerOn);

            StateMachine.In(State.AxesIdle)
            .On(Triggers.AxesBusy).Goto(State.AxesMoving);

            StateMachine.In(State.AxesMoving)
            .On(Triggers.AxesStop).Goto(State.AxesIdle);

            StateMachine.In(State.PowerOn)
            .On(Triggers.PowerOff).Goto(State.PoweringOff);

            StateMachine.In(State.PowerOff)
            .On(Triggers.PowerOn).Goto(State.PoweringOn);

            StateMachine.In(State.PoweringOff)
            .On(Triggers.PowerOffReady).Goto(State.PowerOff);

            StateMachine.In(State.PoweringOn)
            .On(Triggers.PowerOnReady).Goto(State.PowerOn);

            StateMachine.In(State.Error)
            .On(Triggers.InitializationStarts).Goto(State.Initializing);

            StateMachine.In(State.Ready)
            .On(Triggers.Error).Goto(State.Error);

            StateMachine.In(State.Down)
            .On(Triggers.Error).Goto(State.Error);

            StateMachine.In(State.Idle)
            .On(Triggers.Deinitialize).Goto(State.NotInitialized);

            StateMachine.DefineHierarchyOn(State.Processing)
            .WithHistoryType(HistoryType.None)
            .WithInitialSubState(State.AxesMoving)
            .WithSubState(State.AxesIdle);

            StateMachine.DefineHierarchyOn(State.Idle)
            .WithHistoryType(HistoryType.None)
            .WithInitialSubState(State.PowerOn)
            .WithSubState(State.PowerOff)
            .WithSubState(State.PoweringOff)
            .WithSubState(State.PoweringOn);

            StateMachine.DefineHierarchyOn(State.Ready)
            .WithHistoryType(HistoryType.Deep)
            .WithInitialSubState(State.Idle)
            .WithSubState(State.Processing);

            StateMachine.DefineHierarchyOn(State.Down)
            .WithHistoryType(HistoryType.None)
            .WithInitialSubState(State.NotInitialized)
            .WithSubState(State.Initializing)
            .WithSubState(State.Error);

            StateMachine.Initialize(State.NotInitialized);

            StateMachine.Start();

            StateMachine.TransitionCompleted += MyStateMachine_TransitionCompleted;

            using (Stream stream = File.Open("StateDiagram.graphml", FileMode.Create, FileAccess.Write, FileShare.Read))
                using (TextWriter writer = new StreamWriter(stream))
                {
                    var generator = new YEdStateMachineReportGenerator <State, Triggers>(writer);
                    StateMachine.Report(generator);
                }
            StateMachine.Report(customReporter);
        }
Exemple #35
0
        public void OtherwiseGuard(
            PassiveStateMachine<int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            "establish a state machine with otherwise guard and no machting other guard"._(() =>
                {
                    machine = new PassiveStateMachine<int, int>();

                    currentStateExtension = new CurrentStateExtension();
                    machine.AddExtension(currentStateExtension);

                    machine.In(SourceState)
                        .On(Event)
                            .If(() => false).Goto(ErrorState)
                            .Otherwise().Goto(DestinationState);

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

            "when an event is fired"._(() =>
                machine.Fire(Event));

            "it should_take_transition_guarded_with_otherwise"._(() =>
                currentStateExtension.CurrentState.Should().Be(DestinationState));
        }
        public void Start(
            PassiveStateMachine<int, int> machine,
            bool entryActionExecuted)
        {
            "establish an initialized state machine"._(() =>
                {
                    machine = new PassiveStateMachine<int, int>();

                    machine.AddExtension(this.testExtension);

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

                    machine.Initialize(TestState);
                });

            "when starting the state machine"._(() =>
                machine.Start());

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

            "should execute entry action of state to which state machine is initialized"._(() =>
                entryActionExecuted.Should().BeTrue());
        }
        public SpeechInteraction(Hpi.Hci.Bachelorproject1617.PhotoBooth.MainWindow mainWindow, SpeechSynthesizer reader)
        {
            this.mainWindow = mainWindow;


            this.reader = reader;

            this.reader.SpeakStarted   += reader_SpeakStarted;
            this.reader.SpeakCompleted += reader_SpeakCompleted;

            //SpeakText(@"Welcome to this magical Kinect Photobooth, the camera that produces tactile snapshots of your gestures. If you want a picture just position yourself 1 meter in front of the Kinect-Camera and spread your arms away from you to get recognized");
            //SpeakText(@"Hey there, if you want a tactile snapshot of your gesture just position yourself 1 meter in front of the Kinect-Camera and spread your arms away from you to get recognized. I can detect two persons at the time so get a mate and let's go");

            fsm = new PassiveStateMachine <ProcessState, Command>();
            fsm.In(ProcessState.NoPersonRecognized)
            .On(Command.Repeat).Execute(() =>
            {
                SpeakText(NoPersonRecognizedRepeat);
                StartTimer(35000);
            })     //reader.Speak(NoPersonRecognizedRepeat)
            .On(Command.FramesReady).Goto(ProcessState.PersonRecognized).Execute(() =>
            {
                SpeakText(PersonRecognizedTransition);
                Console.WriteLine("Frames ready");
                StartTimer(35000);
            }).On(Command.Test).Goto(ProcessState.PictureTaken);
            fsm.In(ProcessState.PersonRecognized)
            .On(Command.Repeat).Execute(() => { SpeakText(PersonRecognizedRepeat);
                                                StartTimer(35000); })
            .On(Command.FramesNotReady).Goto(ProcessState.NoPersonRecognized).Execute(() => {
                SpeakText(PersonLeft);
                Console.WriteLine("Frames not ready");
                StartTimer(35000);
            })
            .On(Command.Outlines).Goto(ProcessState.PictureTaken).Execute(() =>
            {
                outlines = true;
                new Thread(PreparePicture).Start();

                StartTimer(45000);
            })
            .On(Command.Skeleton).Goto(ProcessState.PictureTaken).Execute(() =>
            {
                outlines = false;
                new Thread(PreparePicture).Start();

                StartTimer(45000);
            });
            fsm.In(ProcessState.PictureTaken)
            .On(Command.Print).Goto(ProcessState.Connected).Execute(() => {
                SpeakText(ConnectingString);
                if (mainWindow.BluetoothOn)
                {
                    mainWindow.BluetoothConnect();
                }
                else
                {
                    fsm.Fire(Command.Connected);
                }
            })
            .On(Command.Yes).Goto(ProcessState.Connected).Execute(() =>
            {
                SpeakText(ConnectingString);
                if (mainWindow.BluetoothOn)
                {
                    mainWindow.BluetoothConnect();
                }
                else
                {
                    fsm.Fire(Command.Connected);
                }
            })
            .On(Command.Repeat).Execute(() =>
            {
                SpeakText(PictureTakenRepeat);
                StartTimer(35000);
            })
            .On(Command.Back).Goto(ProcessState.PersonRecognized).Execute(() =>
            {
                SpeakText(BackToPersonRecognized);
                mainWindow.pictureTaken          = false;
                mainWindow.AlreadyConvertedToSVG = false;
                StartTimer(35000);
            });
            fsm.In(ProcessState.Connected)
            .On(Command.Connected).Goto(ProcessState.Printed).Execute(() => {
                SpeakText(PrintingString);
                if (mainWindow.BluetoothOn)
                {
                    mainWindow.SendSvgBluetooth(mainWindow.svgImage);
                }
                else
                {
                    mainWindow.SendSvgTCP(mainWindow.svgImage);
                }
            });
            fsm.In(ProcessState.Printed)
            .On(Command.Printed).Goto(ProcessState.NoPersonRecognized).Execute(() => { SpeakText(PrintedString); });

            fsm.In(ProcessState.Connected);
            fsm.Initialize(ProcessState.NoPersonRecognized);
            fsm.Start();
            StartTimer(35000);
        }
        public void Report()
        {
            var elevator = new PassiveStateMachine<States, Events>("Elevator");

            elevator.DefineHierarchyOn(States.Healthy)
                .WithHistoryType(HistoryType.Deep)
                .WithInitialSubState(States.OnFloor)
                .WithSubState(States.Moving);

            elevator.DefineHierarchyOn(States.Moving)
                .WithHistoryType(HistoryType.Shallow)
                .WithInitialSubState(States.MovingUp)
                .WithSubState(States.MovingDown);

            elevator.DefineHierarchyOn(States.OnFloor)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(States.DoorClosed)
                .WithSubState(States.DoorOpen);

            elevator.In(States.Healthy)
                .On(Events.ErrorOccured).Goto(States.Error);

            elevator.In(States.Error)
                .On(Events.Reset).Goto(States.Healthy)
                .On(Events.ErrorOccured);

            elevator.In(States.OnFloor)
                .ExecuteOnEntry(AnnounceFloor)
                .ExecuteOnExit(Beep)
                .ExecuteOnExit(Beep)
                .On(Events.CloseDoor).Goto(States.DoorClosed)
                .On(Events.OpenDoor).Goto(States.DoorOpen)
                .On(Events.GoUp)
                    .If(CheckOverload).Goto(States.MovingUp)
                    .Otherwise()
                        .Execute(AnnounceOverload)
                        .Execute(Beep)
                .On(Events.GoDown)
                    .If(CheckOverload).Goto(States.MovingDown)
                    .Otherwise().Execute(AnnounceOverload);

            elevator.In(States.Moving)
                .On(Events.Stop).Goto(States.OnFloor);

            elevator.Initialize(States.OnFloor);

            elevator.Report(this.testee);

            string statesReport;
            string transitionsReport;
            this.stateStream.Position = 0;
            using (var reader = new StreamReader(this.stateStream))
            {
                statesReport = reader.ReadToEnd();
            }

            this.transitionsStream.Position = 0;
            using (var reader = new StreamReader(this.transitionsStream))
            {
                transitionsReport = reader.ReadToEnd();
            }

            const string ExpectedTransitionsReport = "Source;Event;Guard;Target;ActionsHealthy;ErrorOccured;;Error;OnFloor;CloseDoor;;DoorClosed;OnFloor;OpenDoor;;DoorOpen;OnFloor;GoUp;CheckOverload;MovingUp;OnFloor;GoUp;;internal transition;AnnounceOverload, BeepOnFloor;GoDown;CheckOverload;MovingDown;OnFloor;GoDown;;internal transition;AnnounceOverloadMoving;Stop;;OnFloor;Error;Reset;;Healthy;Error;ErrorOccured;;internal transition;";
            const string ExpectedStatesReport = "Source;Entry;Exit;ChildrenHealthy;;;OnFloor, MovingOnFloor;AnnounceFloor;Beep, Beep;DoorClosed, DoorOpenMoving;;;MovingUp, MovingDownMovingUp;;;MovingDown;;;DoorClosed;;;DoorOpen;;;Error;;;";

            statesReport.Replace("\n", string.Empty).Replace("\r", string.Empty)
                .Should().Be(ExpectedStatesReport.Replace("\n", string.Empty).Replace("\r", string.Empty));

            transitionsReport.Replace("\n", string.Empty).Replace("\r", string.Empty)
                .Should().Be(ExpectedTransitionsReport.Replace("\n", string.Empty).Replace("\r", string.Empty));
        }
        public void Reinitialization(
            PassiveStateMachine<int, int> machine,
            Exception receivedException)
        {
            "establish an initialized state machine"._(() =>
                {
                    machine = new PassiveStateMachine<int, int>();
                    machine.Initialize(TestState);
                });

            "when state machine is initialized again"._(() =>
                {
                    try
                    {
                        machine.Initialize(TestState);
                    }
                    catch (Exception e)
                    {
                        receivedException = e;
                    }
                });

            "should throw an invalid operation exception"._(() =>
                {
                    receivedException
                        .Should().BeAssignableTo<InvalidOperationException>();
                    receivedException.Message
                        .Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized);
                });
        }
        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);
            });
        }
        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));
        }