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();
        }
Esempio n. 2
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();
        }
Esempio n. 3
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"));
        }
Esempio n. 4
0
            private StateMachineDefinitionBuilder <EnrolleeState, SubmissionAction> InitBuilder()
            {
                var builder = new StateMachineDefinitionBuilder <EnrolleeState, SubmissionAction>();

                builder.In(EnrolleeState.Editable)
                .On(SubmissionAction.LockProfile).If <bool>(isAdmin => isAdmin).Execute(HandleLockProfile)
                .On(SubmissionAction.DeclineProfile).If <bool>(isAdmin => isAdmin).Execute(HandleDeclineProfile);

                builder.In(EnrolleeState.UnderReview)
                .On(SubmissionAction.Approve).If <bool>(isAdmin => isAdmin).Execute(HandleApprove)
                .On(SubmissionAction.EnableEditing).If <bool>(isAdmin => isAdmin).Execute(HandleEnableEditing)
                .On(SubmissionAction.LockProfile).If <bool>(isAdmin => isAdmin).Execute(HandleLockProfile)
                .On(SubmissionAction.DeclineProfile).If <bool>(isAdmin => isAdmin).Execute(HandleDeclineProfile)
                .On(SubmissionAction.RerunRules).If <bool>(isAdmin => isAdmin).Execute(HandleRerunRules);

                builder.In(EnrolleeState.RequiresToa)
                .On(SubmissionAction.AcceptToa).If <bool>(isAdmin => !isAdmin).Execute(HandleAcceptToa)
                .On(SubmissionAction.DeclineToa).If <bool>(isAdmin => !isAdmin).Execute(HandleDeclineToa)
                .On(SubmissionAction.EnableEditing).If <bool>(isAdmin => isAdmin).Execute(HandleEnableEditing)
                .On(SubmissionAction.LockProfile).If <bool>(isAdmin => isAdmin).Execute(HandleLockProfile)
                .On(SubmissionAction.DeclineProfile).If <bool>(isAdmin => isAdmin).Execute(HandleDeclineProfile);

                builder.In(EnrolleeState.Locked)
                .On(SubmissionAction.EnableEditing).If <bool>(isAdmin => isAdmin).Execute(HandleEnableEditing)
                .On(SubmissionAction.DeclineProfile).If <bool>(isAdmin => isAdmin).Execute(HandleDeclineProfile);

                builder.In(EnrolleeState.Declined)
                .On(SubmissionAction.EnableProfile).If <bool>(isAdmin => isAdmin).Execute(HandleEnableEditing);

                return(builder);
            }
        public void EntryActionException(PassiveStateMachine <int, int> machine)
        {
            "establish an entry action throwing an exception".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(Values.Source)
                .On(Values.Event)
                .Goto(Values.Destination);
                stateMachineDefinitionBuilder
                .In(Values.Destination)
                .ExecuteOnEntry(() => throw Values.Exception);
                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();
        }
        private StateMachineDefinitionBuilder <EnrolleeState, SubmissionAction> InitBuilder()
        {
            var builder = new StateMachineDefinitionBuilder <EnrolleeState, SubmissionAction>();

            builder.In(EnrolleeState.Editable)
            .On(SubmissionAction.LockProfile).IfAdmin(AllowAction)
            .On(SubmissionAction.DeclineProfile).IfAdmin(AllowAction);

            builder.In(EnrolleeState.UnderReview)
            .On(SubmissionAction.Approve).IfAdmin(AllowAction)
            .On(SubmissionAction.EnableEditing).IfAdmin(AllowAction)
            .On(SubmissionAction.LockProfile).IfAdmin(AllowAction)
            .On(SubmissionAction.DeclineProfile).IfAdmin(AllowAction)
            .On(SubmissionAction.RerunRules).IfAdmin(AllowAction);

            builder.In(EnrolleeState.RequiresToa)
            .On(SubmissionAction.AcceptToa).IfEnrollee(AllowAction)
            .On(SubmissionAction.DeclineToa).IfEnrollee(AllowAction)
            .On(SubmissionAction.EnableEditing).IfAdmin(AllowAction)
            .On(SubmissionAction.LockProfile).IfAdmin(AllowAction)
            .On(SubmissionAction.DeclineProfile).IfAdmin(AllowAction);

            builder.In(EnrolleeState.Locked)
            .On(SubmissionAction.EnableEditing).IfAdmin(AllowAction)
            .On(SubmissionAction.DeclineProfile).IfAdmin(AllowAction);

            builder.In(EnrolleeState.Declined)
            .On(SubmissionAction.EnableEditing).IfAdmin(AllowAction);

            return(builder);
        }
        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"));
        }
Esempio n. 8
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));
        }
Esempio n. 9
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"));
        }
Esempio n. 10
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");
        }
        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());
        }
Esempio n. 12
0
        public void SavingEventsForActiveStateMachine(
            AsyncActiveStateMachine <string, int> machine,
            StateMachineSaver <string, int> saver)
        {
            "establish a state machine".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, int>();
                stateMachineDefinitionBuilder
                .In("A")
                .On(1)
                .Goto("B");
                stateMachineDefinitionBuilder
                .In("B")
                .On(2)
                .Goto("C");
                stateMachineDefinitionBuilder
                .In("C")
                .On(3)
                .Goto("A");
                machine = stateMachineDefinitionBuilder
                          .WithInitialState("A")
                          .Build()
                          .CreateActiveStateMachine();
            });

            "when events are fired".x(async() =>
            {
                await machine.Fire(1);
                await machine.Fire(2);
                await machine.FirePriority(3);
                await machine.FirePriority(4);
            });

            "and it is saved".x(async() =>
            {
                saver = new StateMachineSaver <string, int>();
                await machine.Save(saver);
            });

            "it should save those events".x(() =>
            {
                saver
                .Events
                .Select(x => x.EventId)
                .Should()
                .HaveCount(2)
                .And
                .ContainInOrder(1, 2);
                saver
                .PriorityEvents
                .Select(x => x.EventId)
                .Should()
                .HaveCount(2)
                .And
                .ContainInOrder(4, 3);
            });
        }
Esempio n. 13
0
        public void LoadingEvents(
            PassiveStateMachine <string, int> machine)
        {
            "establish a state machine".x(() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, int>();
                stateMachineDefinitionBuilder
                .In("A")
                .On(1)
                .Goto("B");
                stateMachineDefinitionBuilder
                .In("B")
                .On(2)
                .Goto("C");
                stateMachineDefinitionBuilder
                .In("C")
                .On(3)
                .Goto("A");
                machine = stateMachineDefinitionBuilder
                          .WithInitialState("A")
                          .Build()
                          .CreatePassiveStateMachine();
            });

            "when it is loaded with Events".x(() =>
            {
                var loader = new StateMachineLoader <string, int>();
                loader.SetEvents(new List <EventInformation <int> >
                {
                    new EventInformation <int>(1, null),
                    new EventInformation <int>(2, null),
                });
                machine.Load(loader);
            });

            "it should process those events".x(() =>
            {
                var transitionRecords        = new List <TransitionRecord>();
                machine.TransitionCompleted += (sender, args) =>
                                               transitionRecords.Add(
                    new TransitionRecord(args.EventId, args.StateId, args.NewStateId));

                machine.Start();
                transitionRecords
                .Should()
                .HaveCount(2)
                .And
                .IsEquivalentInOrder(new List <TransitionRecord>
                {
                    new TransitionRecord(1, "A", "B"),
                    new TransitionRecord(2, "B", "C")
                });
            });
        }
Esempio n. 14
0
        public Elevator()
        {
            var builder = new StateMachineDefinitionBuilder <States, Events>();

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

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

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

            builder.In(States.Healthy)
            .ExecuteOnEntry(() => {
            })
            .On(Events.Error).Goto(States.Error);

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

            builder.In(States.OnFloor)
            .ExecuteOnEntry(this.AnnounceFloor)
            .ExecuteOnExit(Beep)
            .ExecuteOnExit(Beep)     // just beep a second time
            .On(Events.CloseDoor).Goto(States.DoorClosed)
            .On(Events.OpenDoor).Goto(States.DoorOpen)
            .On(Events.GoUp)
            .If(CheckOverload).Goto(States.MovingUp)
            .Otherwise().Execute(this.AnnounceOverload)
            .On(Events.GoDown)
            .If(CheckOverload).Goto(States.MovingDown)
            .Otherwise().Execute(this.AnnounceOverload);
            builder.In(States.Moving)
            .On(Events.Stop).Goto(States.OnFloor);

            builder.WithInitialState(States.OnFloor);

            var definition = builder
                             .Build();

            elevator = definition
                       .CreatePassiveStateMachine("Elevator");

            elevator.Start();
        }
Esempio n. 15
0
        public void PriorityFire(string dummyName, Func <StateMachineDefinition <States, Events>, IStateMachine <States, Events> > createStateMachine)
        {
            const int Transitions = 3;
            var       exceptions  = new List <EventArgs>();
            var       transitionCompletedMessages = new List <TransitionCompletedEventArgs <States, Events> >();
            var       transitionDeclinedMessages  = new List <TransitionEventArgs <States, Events> >();

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

            stateMachineDefinitionBuilder
            .In(States.A)
            .On(Events.B).Goto(States.B).Execute(() =>
            {
                FireD();
                FirePriorityC();
            });
            stateMachineDefinitionBuilder
            .In(States.B)
            .On(Events.C).Goto(States.C);
            stateMachineDefinitionBuilder
            .In(States.C)
            .On(Events.D).Goto(States.D);
            var stateMachineDefinition = stateMachineDefinitionBuilder
                                         .WithInitialState(States.A)
                                         .Build();

            testee = createStateMachine(stateMachineDefinition);

            void FireD() => testee.Fire(Events.D);
            void FirePriorityC() => testee.FirePriority(Events.C);

            testee.TransitionExceptionThrown += (sender, e) => exceptions.Add(e);
            testee.TransitionCompleted       += (sender, e) => transitionCompletedMessages.Add(e);
            testee.TransitionDeclined        += (sender, e) => transitionDeclinedMessages.Add(e);

            var allTransitionsCompleted = SetUpWaitForAllTransitions(testee, 1);

            testee.Start();

            testee.Fire(Events.B);

            WaitForAllTransitions(allTransitionsCompleted);

            transitionCompletedMessages.Count.Should().Be(Transitions);
            transitionDeclinedMessages.Should().BeEmpty();
            exceptions.Should().BeEmpty();

            testee.Stop();
        }
Esempio n. 16
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);
        }
Esempio n. 17
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());
        }
Esempio n. 18
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());
        }
Esempio n. 19
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());
        }
Esempio n. 20
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));
        }
Esempio n. 21
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"));
        }
Esempio n. 22
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));
        }
Esempio n. 23
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));
        }
Esempio n. 24
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");
            });
        }
Esempio n. 25
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();
        }
Esempio n. 26
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);
            });
        }
Esempio n. 27
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());
        }
        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));
        }
Esempio n. 29
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 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));
        }