Пример #1
0
        public void ExceptionHandling(
            PassiveStateMachine <int, int> machine,
            bool entryAction1Executed,
            bool entryAction2Executed,
            bool entryAction3Executed)
        {
            var exception2         = new Exception();
            var exception3         = new Exception();
            var receivedExceptions = new List <Exception>();

            "establish a state machine with several entry actions on a state and some of them throw an exception".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(State)
                .ExecuteOnEntry(() => entryAction1Executed = true)
                .ExecuteOnEntry(() =>
                {
                    entryAction2Executed = true;
                    throw exception2;
                })
                .ExecuteOnEntry(() =>
                {
                    entryAction3Executed = true;
                    throw exception3;
                });
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();

                machine.TransitionExceptionThrown += (s, e) => receivedExceptions.Add(e.Exception);
            });

            "when entering the state".x(() =>
            {
                machine.Start();
            });

            "it should execute all entry actions on entry".x(() =>
            {
                entryAction1Executed
                .Should().BeTrue("action 1 should be executed");

                entryAction2Executed
                .Should().BeTrue("action 2 should be executed");

                entryAction3Executed
                .Should().BeTrue("action 3 should be executed");
            });

            "it should handle all exceptions of all throwing entry actions by firing the TransitionExceptionThrown event".x(() =>
                                                                                                                            receivedExceptions
                                                                                                                            .Should()
                                                                                                                            .HaveCount(2)
                                                                                                                            .And
                                                                                                                            .Contain(exception2)
                                                                                                                            .And
                                                                                                                            .Contain(exception3));
        }
        public SimpleStateMachine()
        {
            var builder = new StateMachineDefinitionBuilder <States, Events>();

            builder
            .In(States.Off)
            .On(Events.TurnOn)
            .Goto(States.On)
            .Execute(SayHello);

            builder
            .In(States.On)
            .On(Events.TurnOff)
            .Goto(States.Off)
            .Execute(SayBye);

            builder
            .WithInitialState(States.Off);

            machine = builder
                      .Build()
                      .CreatePassiveStateMachine();

            machine.Start();
        }
Пример #3
0
        public void MultipleEntryActions(
            PassiveStateMachine <int, int> machine,
            bool entryAction1Executed,
            bool entryAction2Executed)
        {
            "establish a state machine with several entry actions on a state".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(State)
                .ExecuteOnEntry(() => entryAction1Executed = true)
                .ExecuteOnEntry(() => entryAction2Executed = true);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();
            });

            "when entering the state".x(() =>
            {
                machine.Start();
            });

            "It should execute all entry actions".x(() =>
            {
                entryAction1Executed
                .Should().BeTrue("first action should be executed");

                entryAction2Executed
                .Should().BeTrue("second action should be executed");
            });
        }
Пример #4
0
        public void ThrowsExceptionOnLoading_WhenSettingALastActiveStateThatIsNotASubState(string dummyName, Func <StateMachineDefinition <States, Events>, IStateMachine <States, Events> > createStateMachine)
        {
            var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <States, Events>();

            stateMachineDefinitionBuilder
            .In(States.A);
            stateMachineDefinitionBuilder
            .DefineHierarchyOn(States.B)
            .WithHistoryType(HistoryType.Deep)
            .WithInitialSubState(States.B1)
            .WithSubState(States.B2);
            var stateMachineDefinition = stateMachineDefinitionBuilder
                                         .WithInitialState(States.A)
                                         .Build();

            var testee = createStateMachine(stateMachineDefinition);

            var loader = A.Fake <IStateMachineLoader <States> >();

            A.CallTo(() => loader.LoadHistoryStates())
            .Returns(new Dictionary <States, States>
            {
                { States.B, States.A }
            });

            Action action = () => testee.Load(loader);

            action.Should().Throw <InvalidOperationException>()
            .WithMessage(ExceptionMessages.CannotSetALastActiveStateThatIsNotASubState);
        }
Пример #5
0
        public void EventsQueueing(
            IStateMachine <string, int> machine,
            AutoResetEvent signal)
        {
            const int FirstEvent  = 0;
            const int SecondEvent = 1;

            "establish an active state machine with transitions".x(() =>
            {
                signal = new AutoResetEvent(false);

                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, int>();
                stateMachineDefinitionBuilder.In("A").On(FirstEvent).Goto("B");
                stateMachineDefinitionBuilder.In("B").On(SecondEvent).Goto("C");
                stateMachineDefinitionBuilder.In("C").ExecuteOnEntry(() => signal.Set());
                machine = stateMachineDefinitionBuilder
                          .WithInitialState("A")
                          .Build()
                          .CreateActiveStateMachine();
            });

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

            "it should queue event at the end".x(() =>
                                                 signal
                                                 .WaitOne(1000)
                                                 .Should()
                                                 .BeTrue("state machine should arrive at destination state"));
        }
Пример #6
0
        public void ClearingExtensions(
            IStateMachine <string, int> machine,
            IExtension <string, int> extension)
        {
            "establish a state machine with an extension".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, int>();
                stateMachineDefinitionBuilder.In("initial");
                machine = stateMachineDefinitionBuilder
                          .WithInitialState("initial")
                          .Build()
                          .CreatePassiveStateMachine();

                extension = A.Fake <IExtension <string, int> >();
                machine.AddExtension(extension);
            });

            "when clearing all extensions from the state machine".x(() =>
            {
                machine.ClearExtensions();
                machine.Start();
            });

            "it should not anymore notify extension about internal events".x(() =>
                                                                             A.CallTo(extension)
                                                                             .MustNotHaveHappened());
        }
        public void ExitActionException(PassiveStateMachine <int, int> machine)
        {
            "establish an exit action throwing an exception".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(Values.Source)
                .ExecuteOnExit(() => throw Values.Exception)
                .On(Values.Event)
                .Goto(Values.Destination);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(Values.Source)
                          .Build()
                          .CreatePassiveStateMachine();

                machine.TransitionExceptionThrown += (s, e) => this.receivedTransitionExceptionEventArgs = e;
            });

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

            this.ItShouldHandleTransitionException();
        }
Пример #8
0
        public void SetsCurrentStateOnLoadingFromPersistedState(string dummyName, Func <StateMachineDefinition <States, Events>, IStateMachine <States, Events> > createStateMachine)
        {
            var loader    = A.Fake <IStateMachineLoader <States> >();
            var extension = A.Fake <IExtension <States, Events> >();

            A.CallTo(() => loader.LoadCurrentState())
            .Returns(Initializable <States> .Initialized(States.C));

            var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <States, Events>();

            stateMachineDefinitionBuilder
            .In(States.A);
            stateMachineDefinitionBuilder
            .In(States.C);
            var stateMachineDefinition = stateMachineDefinitionBuilder
                                         .WithInitialState(States.A)
                                         .Build();

            var testee = createStateMachine(stateMachineDefinition);

            testee.AddExtension(extension);

            testee.Load(loader);

            A.CallTo(() =>
                     extension.Loaded(
                         A <IStateMachineInformation <States, Events> > .Ignored,
                         A <Initializable <States> >
                         .That
                         .Matches(currentState =>
                                  currentState.IsInitialized &&
                                  currentState.ExtractOrThrow() == States.C),
                         A <IReadOnlyDictionary <States, States> > .Ignored))
            .MustHaveHappenedOnceExactly();
        }
Пример #9
0
        private void startFSM(FSMConfiguration fsmConfiguration)
        {
            mainFSMConfiguration = fsmConfiguration;
            fSMData.tcaTSLPath   = fsmConfiguration.tslPath;
            fSMData.comPortName  = fsmConfiguration.defaultComPortName;
            fSMData.ruSerialPort = new RuSerialPort();
            fSMData.tCACommand   = new TCAControl.TCACommandWarpper(fSMData.tcaTSLPath);
            proxyRunMachine      = new StateMachineDefinitionBuilder <States, Events>();
            proxyRunMachine.WithInitialState(States.Connncted);
            proxyRunMachine.In(States.Connncted).On(Events.CT11Command).Goto(States.CT11Mode).Execute(ct11Mode);
            proxyRunMachine.In(States.Connncted).On(Events.RuCommand).Goto(States.RuMode).Execute(ruMode);
            proxyRunMachine.In(States.Connncted).On(Events.TCAIcolishCommand).Goto(States.TCAIcolishMode).Execute(tCAIcolishMode);
            proxyRunMachine.In(States.TCAIcolishMode).On(Events.GoBack).Goto(States.Connncted).Execute(connected);
            proxyRunMachine.In(States.CT11Mode).On(Events.RuCommand).Goto(States.RuMode).Execute(ruMode);
            proxyRunMachine.In(States.CT11Mode).On(Events.GoBack).Goto(States.Connncted).Execute(connected);
            proxyRunMachine.In(States.RuMode).On(Events.CT11Command).Goto(States.CT11Mode).Execute(ct11Mode);
            proxyRunMachine.In(States.RuMode).On(Events.GoBack).Goto(States.Connncted).Execute(connected);
            var definition = proxyRunMachine.Build();

            fSMData.elevator = definition.CreateActiveStateMachine();
            fSMData.elevator.Start();

            //Action must Instantiate after FSM member Instantiate
            connectedAction  = new ConnectedAction(ref fSMData);
            ruModeAction     = new RuModeAction(ref fSMData);
            ct11ModeAction   = new CT11ModeAction(ref fSMData);
            tCAIcolishAction = new TCAIcolishAction(ref fSMData);
        }
Пример #10
0
        public void MatchingGuard(
            AsyncPassiveStateMachine <int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            "establish a state machine with guarded transitions".x(async() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(SourceState)
                .On(Event)
                .If(() => false).Goto(ErrorState)
                .If(async() => await Task.FromResult(false)).Goto(ErrorState)
                .If(async() => await Task.FromResult(true)).Goto(DestinationState)
                .If(() => true).Goto(ErrorState)
                .Otherwise().Goto(ErrorState);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(SourceState)
                          .Build()
                          .CreatePassiveStateMachine();

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

                await 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));
        }
Пример #11
0
        public void NoMatchingGuard(
            AsyncPassiveStateMachine <int, int> machine)
        {
            var declined = false;

            "establish state machine with no matching guard".x(async() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(SourceState)
                .On(Event)
                .If(() => Task.FromResult(false)).Goto(ErrorState);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(SourceState)
                          .Build()
                          .CreatePassiveStateMachine();

                var currentStateExtension = new CurrentStateExtension();
                machine.AddExtension(currentStateExtension);
                machine.TransitionDeclined += (sender, e) => declined = true;

                await 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"));
        }
Пример #12
0
        public void EntryAction(
            AsyncPassiveStateMachine <int, int> machine,
            bool entryActionExecuted,
            bool asyncEntryActionExecuted)
        {
            "establish a state machine with entry action on a state".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(State)
                .ExecuteOnEntry(() => entryActionExecuted = true)
                .ExecuteOnEntry(async() =>
                {
                    asyncEntryActionExecuted = true;
                    await Task.Yield();
                });

                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();
            });

            "when entering the state".x(async() =>
                                        await machine.Start());

            "it should execute the synchronous entry action".x(()
                                                               => entryActionExecuted.Should().BeTrue());

            "it should execute the asynchronous entry action".x(()
                                                                => asyncEntryActionExecuted.Should().BeTrue());
        }
Пример #13
0
        public void OtherwiseGuard(
            AsyncPassiveStateMachine <int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            "establish a state machine with otherwise guard and no machting other guard".x(async() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(SourceState)
                .On(Event)
                .If(() => Task.FromResult(false)).Goto(ErrorState)
                .Otherwise().Goto(DestinationState);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(SourceState)
                          .Build()
                          .CreatePassiveStateMachine();

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

                await machine.Start();
            });

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

            "it should_take_transition_guarded_with_otherwise".x(()
                                                                 => currentStateExtension.CurrentState.Should().Be(DestinationState));
        }
Пример #14
0
        public void Start(
            AsyncPassiveStateMachine <int, int> machine,
            bool entryActionExecuted,
            CurrentStateExtension currentStateExtension)
        {
            "establish an initialized state machine".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(TestState)
                .ExecuteOnEntry(() => entryActionExecuted = true);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(TestState)
                          .Build()
                          .CreatePassiveStateMachine();

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

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

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

            "should execute entry action of state to which state machine is initialized".x(() =>
                                                                                           entryActionExecuted.Should().BeTrue());
        }
Пример #15
0
        public void InitialStateSetViaDefinitionBuilder()
        {
            var stateMachineSaver = new StateMachineSaver <string>();

            var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, int>();

            stateMachineDefinitionBuilder
            .In("A")
            .On(1)
            .Goto("B");
            stateMachineDefinitionBuilder
            .In("B")
            .On(2)
            .Goto("C");
            stateMachineDefinitionBuilder
            .WithInitialState("A");
            var machine = stateMachineDefinitionBuilder
                          .Build()
                          .CreatePassiveStateMachine();

            machine.Start();

            machine.Fire(1);

            machine.Save(stateMachineSaver);

            stateMachineSaver
            .CurrentStateId
            .Should()
            .Match <Initializable <string> >(currentState =>
                                             currentState.IsInitialized &&
                                             currentState.ExtractOrThrow() == "B");
        }
Пример #16
0
        public void ThrowsExceptionOnLoading_WhenAlreadyStarted()
        {
            var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <States, Events>();

            stateMachineDefinitionBuilder.In(States.A);
            var testee = stateMachineDefinitionBuilder
                         .WithInitialState(States.A)
                         .Build()
                         .CreateActiveStateMachine();

            var signal    = new AutoResetEvent(false);
            var extension = A.Fake <IExtension <States, Events> >();

            A.CallTo(() =>
                     extension.EnteredInitialState(
                         A <IStateMachineInformation <States, Events> > .Ignored,
                         A <States> .Ignored,
                         A <ITransitionContext <States, Events> > .Ignored))
            .Invokes(() => signal.Set());
            testee.AddExtension(extension);

            testee.Start();

            var stateMachineWasStarted = signal.WaitOne(500);

            stateMachineWasStarted.Should().BeTrue();

            Action action = () => testee.Load(A.Fake <IStateMachineLoader <States> >());

            action
            .Should()
            .Throw <InvalidOperationException>()
            .WithMessage(ExceptionMessages.StateMachineIsAlreadyInitialized);
        }
        public void StartingException(PassiveStateMachine <int, int> machine)
        {
            const int State = 1;

            "establish a entry action for the initial state that throws an exception".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(State)
                .ExecuteOnEntry(() => throw Values.Exception);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();

                machine.TransitionExceptionThrown += (s, e) => this.receivedTransitionExceptionEventArgs = e;
            });

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

            "should catch exception and fire transition exception event".x(() =>
                                                                           this.receivedTransitionExceptionEventArgs.Exception.Should().NotBeNull());

            "should pass thrown exception to event arguments of transition exception event".x(() =>
                                                                                              this.receivedTransitionExceptionEventArgs.Exception.Should().BeSameAs(Values.Exception));
        }
Пример #18
0
        public void MultipleExitActions(
            PassiveStateMachine <int, int> machine,
            bool exitAction1Executed,
            bool exitAction2Executed)
        {
            "establish a state machine with several exit actions on a state".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(State)
                .ExecuteOnExit(() => exitAction1Executed = true)
                .ExecuteOnExit(() => exitAction2Executed = true)
                .On(Event).Goto(AnotherState);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();
            });

            "when leaving the state".x(() =>
            {
                machine.Start();
                machine.Fire(Event);
            });

            "It should execute all exit actions".x(() =>
            {
                exitAction1Executed
                .Should().BeTrue("first action should be executed");

                exitAction2Executed
                .Should().BeTrue("second action should be executed");
            });
        }
Пример #19
0
        public void GuardException(AsyncPassiveStateMachine <int, int> machine)
        {
            "establish a guard throwing an exception".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(Values.Source)
                .On(Values.Event)
                .If((Func <Task <bool> >)(() => throw Values.Exception))
                .Goto(Values.Destination);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(Values.Source)
                          .Build()
                          .CreatePassiveStateMachine();

                machine.TransitionExceptionThrown += (s, e) => this.receivedTransitionExceptionEventArgs = e;
            });

            "when executing the transition".x(async() =>
            {
                await machine.Start();
                await machine.Fire(Values.Event, Values.Parameter);
            });

            this.ItShouldHandleTransitionException();
        }
Пример #20
0
        public void ExitActionWithParameter(
            PassiveStateMachine <int, int> machine,
            string parameter)
        {
            const string Parameter = "parameter";

            "establish a state machine with exit action with parameter on a state".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(State)
                .ExecuteOnExitParametrized(p => parameter = p, Parameter)
                .On(Event).Goto(AnotherState);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();
            });

            "when leaving the state".x(() =>
            {
                machine.Start();
                machine.Fire(Event);
            });

            "it should execute the exit action".x(() =>
                                                  parameter.Should().NotBeNull());

            "it should pass parameter to the exit action".x(() =>
                                                            parameter.Should().Be(Parameter));
        }
Пример #21
0
        public void ExitAction(
            PassiveStateMachine <int, int> machine,
            bool exitActionExecuted)
        {
            "establish a state machine with exit action on a state".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(State)
                .ExecuteOnExit(() => exitActionExecuted = true)
                .On(Event).Goto(AnotherState);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();
            });

            "when leaving the state".x(() =>
            {
                machine.Start();
                machine.Fire(Event);
            });

            "it should execute the exit action".x(() =>
                                                  exitActionExecuted.Should().BeTrue());
        }
Пример #22
0
        public void EventArgument(
            PassiveStateMachine <int, int> machine,
            int passedArgument)
        {
            const int Argument = 17;

            "establish a state machine with an exit action taking an event argument".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(State)
                .ExecuteOnExit((int argument) => passedArgument = argument)
                .On(Event).Goto(AnotherState);
                stateMachineDefinitionBuilder
                .In(AnotherState)
                .ExecuteOnEntry((int argument) => passedArgument = argument);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();
            });

            "when leaving the state".x(() =>
            {
                machine.Start();
                machine.Fire(Event, Argument);
            });

            "it should pass event argument to exit action".x(() =>
                                                             passedArgument.Should().Be(Argument));
        }
Пример #23
0
        public void BeforeExecutingEntryActions(
            AsyncPassiveStateMachine <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(async() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, int>();
                stateMachineDefinitionBuilder
                .In("0")
                .On(1)
                .Goto("1");
                machine = stateMachineDefinitionBuilder
                          .WithInitialState("0")
                          .Build()
                          .CreatePassiveStateMachine(Name);

                machine.AddExtension(extension);

                await 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.ExtractOrThrow() == "1"),
                                                                                                       A <IStateDefinition <string, int> > .That.Matches(x => x.Id == "1"),
                                                                                                       A <ITransitionContext <string, int> > .That.Matches(x => x.EventId.Value == 1)))
                                                                                       .MustHaveHappened());
        }
        public void NoExceptionHandlerRegistered(
            PassiveStateMachine <int, int> machine,
            Exception catchedException)
        {
            "establish an exception throwing state machine without a registered exception handler".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(Values.Source)
                .On(Values.Event)
                .Execute(() => throw Values.Exception);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(Values.Source)
                          .Build()
                          .CreatePassiveStateMachine();

                machine.Start();
            });

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

            "should (re-)throw exception".x(() =>
                                            catchedException.InnerException
                                            .Should().BeSameAs(Values.Exception));
        }
Пример #25
0
        public void LoadingAnInitializedStateMachine(
            IAsyncStateMachine <string, int> machine,
            Exception receivedException)
        {
            "establish an started state machine".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, int>();
                stateMachineDefinitionBuilder.In("initial");
                machine = stateMachineDefinitionBuilder
                          .WithInitialState("initial")
                          .Build()
                          .CreatePassiveStateMachine();
                machine.Start();
            });

            "when state machine is loaded".x(async() =>
                                             receivedException = await Catch.Exception(async() =>
                                                                                       await machine.Load(A.Fake <IAsyncStateMachineLoader <string> >())));

            "it should throw invalid operation exception".x(() =>
            {
                receivedException.Should().BeOfType <InvalidOperationException>();
                receivedException.Message.Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized);
            });
        }
Пример #26
0
        public void CustomTypesForStatesAndEvents(
            AsyncPassiveStateMachine <MyState, MyEvent> machine,
            bool arrivedInStateB)
        {
            "establish a state machine with custom types for states and events".x(async() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <MyState, MyEvent>();
                stateMachineDefinitionBuilder
                .In(new MyState("A"))
                .On(new MyEvent(1)).Goto(new MyState("B"));
                stateMachineDefinitionBuilder
                .In(new MyState("B"))
                .ExecuteOnEntry(() => arrivedInStateB = true);

                machine = stateMachineDefinitionBuilder
                          .WithInitialState(new MyState("A"))
                          .Build()
                          .CreatePassiveStateMachine();

                await 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"));
        }
Пример #27
0
        public void LoadingNonInitializedStateMachine(
            PassiveStateMachine <State, Event> loadedMachine)
        {
            "when a not started state machine is loaded".x(() =>
            {
                var loader = new StateMachineLoader <State>();
                loader.SetCurrentState(Initializable <State> .UnInitialized());
                loader.SetHistoryStates(new Dictionary <State, State>());

                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <State, Event>();
                SetupStates(stateMachineDefinitionBuilder);
                loadedMachine = stateMachineDefinitionBuilder
                                .WithInitialState(State.A)
                                .Build()
                                .CreatePassiveStateMachine();
                loadedMachine.Load(loader);
            });

            "it should not be initialized already".x(() =>
            {
                var stateMachineSaver = new StateMachineSaver <State>();
                loadedMachine.Save(stateMachineSaver);
                stateMachineSaver
                .CurrentStateId
                .IsInitialized
                .Should()
                .BeFalse();
            });
        }
        public void EventsQueueing(
            IStateMachine <string, int> machine)
        {
            const int FirstEvent  = 0;
            const int SecondEvent = 1;

            var arrived = false;

            "establish a passive state machine with transitions".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, int>();
                stateMachineDefinitionBuilder.In("A").On(FirstEvent).Goto("B");
                stateMachineDefinitionBuilder.In("B").On(SecondEvent).Goto("C");
                stateMachineDefinitionBuilder.In("C").ExecuteOnEntry(() => arrived = true);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState("A")
                          .Build()
                          .CreatePassiveStateMachine();
            });

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

            "it should queue event at the end".x(() =>
                                                 arrived
                                                 .Should()
                                                 .BeTrue("state machine should arrive at destination state"));
        }
        public void CommonAncestor(
            AsyncPassiveStateMachine <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;

            var commonAncestorStateLeft = false;

            "establish a hierarchical state machine".x(async() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();

                stateMachineDefinitionBuilder
                .DefineHierarchyOn(commonAncestorState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(parentOfSourceState)
                .WithSubState(parentOfDestinationState);

                stateMachineDefinitionBuilder
                .DefineHierarchyOn(parentOfSourceState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(sourceState)
                .WithSubState(siblingOfSourceState);

                stateMachineDefinitionBuilder
                .DefineHierarchyOn(parentOfDestinationState)
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState(destinationState)
                .WithSubState(siblingOfDestinationState);

                stateMachineDefinitionBuilder
                .In(sourceState)
                .On(Event).Goto(destinationState);

                stateMachineDefinitionBuilder
                .In(commonAncestorState)
                .ExecuteOnExit(() => commonAncestorStateLeft = true);

                machine = stateMachineDefinitionBuilder
                          .WithInitialState(sourceState)
                          .Build()
                          .CreatePassiveStateMachine();

                await machine.Start();
            });

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

            "the state machine should remain inside common ancestor state".x(()
                                                                             => commonAncestorStateLeft
                                                                             .Should().BeFalse());
        }
Пример #30
0
        public void ExceptionHandling(
            AsyncPassiveStateMachine <int, int> machine,
            bool entryAction1Executed,
            bool entryAction2Executed,
            bool entryAction3Executed,
            bool entryAction4Executed)
        {
            var exception2        = new Exception();
            var exception3        = new Exception();
            var exception4        = new Exception();
            var receivedException = new List <Exception>();

            "establish a state machine with several entry actions on a state and some of them throw an exception".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(State)
                .ExecuteOnEntry(() => entryAction1Executed = true)
                .ExecuteOnEntry(() =>
                {
                    entryAction2Executed = true;
                    throw exception2;
                })
                .ExecuteOnEntry(() =>
                {
                    entryAction3Executed = true;
                    throw exception3;
                })
                .ExecuteOnEntry(async() =>
                {
                    entryAction4Executed = true;
                    await Task.Yield();
                    throw exception4;
                });
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();

                machine.TransitionExceptionThrown += (s, e) => receivedException.Add(e.Exception);
            });

            "when entering the state".x(async() =>
                                        await machine.Start());

            "it should execute all entry actions on entry".x(()
                                                             => new[]
            {
                entryAction1Executed,
                entryAction2Executed,
                entryAction3Executed,
                entryAction4Executed
            }.Should().Equal(true, true, true, true));

            "it should handle all exceptions of all throwing entry actions by firing the TransitionExceptionThrown event".x(()
                                                                                                                            => receivedException
                                                                                                                            .Should().BeEquivalentTo(exception2, exception3, exception4));
        }