示例#1
0
        public void Start(
            AsyncPassiveStateMachine <int, int> machine,
            bool entryActionExecuted)
        {
            "establish an initialized state machine".x(() =>
            {
                machine = new AsyncPassiveStateMachine <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());
        }
示例#2
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 () =>
            {
                machine = new AsyncPassiveStateMachine<string, int>(Name);

                machine.AddExtension(extension);

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

                await machine.Initialize("0");
                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 == "1"),
                        A<IState<string, int>>.That.Matches(x => x.Id == "1"),
                        A<ITransitionContext<string, int>>.That.Matches(x => x.EventId.Value == 1)))
                    .MustHaveHappened());
        }
示例#3
0
        public void Reinitialization(
            AsyncPassiveStateMachine <int, int> machine,
            Exception receivedException)
        {
            "establish an initialized state machine".x(async() =>
            {
                machine = new AsyncPassiveStateMachine <int, int>();
                await machine.Initialize(TestState);
            });

            "when state machine is initialized again".x(async() =>
            {
                try
                {
                    await 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);
            });
        }
示例#4
0
        public void CustomTypesForStatesAndEvents(
            AsyncPassiveStateMachine <MyState, MyEvent> machine,
            bool arrivedInStateB)
        {
            "establish a state machine with custom types for states and events"._(async() =>
            {
                machine = new AsyncPassiveStateMachine <MyState, MyEvent>();

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

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

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

                await machine.Start();
            });

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

            "it should use equals to compare states and events"._(() =>
                                                                  arrivedInStateB.Should().BeTrue("state B should be current state"));
        }
        public void EventsQueueing(
            IAsyncStateMachine <string, int> machine)
        {
            const int firstEvent  = 0;
            const int secondEvent = 1;

            bool arrived = false;

            "establish a passive state machine with transitions".x(() =>
            {
                machine = new AsyncPassiveStateMachine <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".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"));
        }
示例#6
0
        public void OtherwiseGuard(
            AsyncPassiveStateMachine <int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            "establish a state machine with otherwise guard and no machting other guard".x(async() =>
            {
                machine = new AsyncPassiveStateMachine <int, int>();

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

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

                await machine.Initialize(SourceState);
                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));
        }
示例#7
0
        public void EventArgument(
            AsyncPassiveStateMachine <int, int> machine,
            int passedArgument)
        {
            const int argument = 17;

            "establish a state machine with an exit action taking an event argument".x(() =>
            {
                machine = new AsyncPassiveStateMachine <int, int>();

                machine.In(State)
                .ExecuteOnExit((int a) => passedArgument = a)
                .On(Event).Goto(AnotherState);

                machine.In(AnotherState)
                .ExecuteOnEntry((int a) => passedArgument = a);
            });

            "when leaving the state".x(async() =>
            {
                await machine.Initialize(State);
                await machine.Start();
                await machine.Fire(Event, argument);
            });

            "it should pass event argument to exit action".x(() =>
                                                             passedArgument.Should().Be(argument));
        }
示例#8
0
        public void MatchingGuard(
            AsyncPassiveStateMachine <int, int> machine,
            CurrentStateExtension currentStateExtension)
        {
            "establish a state machine with guarded transitions".x(async() =>
            {
                machine = new AsyncPassiveStateMachine <int, int>();

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

                machine.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);

                await machine.Initialize(SourceState);
                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));
        }
示例#9
0
        public void ExitAction(
            AsyncPassiveStateMachine <int, int> machine,
            bool exitActionExecuted,
            bool asyncExitActionExecuted)
        {
            "establish a state machine with exit action on a state".x(() =>
            {
                machine = new AsyncPassiveStateMachine <int, int>();

                machine.In(State)
                .ExecuteOnExit(() => exitActionExecuted = true)
                .ExecuteOnExit(async() =>
                {
                    asyncExitActionExecuted = true;
                    await Task.Yield();
                })
                .On(Event).Goto(AnotherState);
            });

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

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

            "it should execute the asynchronous exit action".x(()
                                                               => asyncExitActionExecuted.Should().BeTrue());
        }
示例#10
0
        public void LoadingNonInitializedStateMachine(
            AsyncPassiveStateMachine <State, Event> loadedMachine)
        {
            "when a non-initialized state machine is loaded".x(async() =>
            {
                var loader = new StateMachineLoader <State>();
                loader.SetCurrentState(new Initializable <State>());
                loader.SetHistoryStates(new Dictionary <State, State>());

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

            "it should not be initialized already".x(async() =>
            {
                var stateMachineSaver = new StateMachineSaver <State>();
                await loadedMachine.Save(stateMachineSaver);
                stateMachineSaver
                .CurrentStateId
                .IsInitialized
                .Should()
                .BeFalse();
            });
        }
        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());
        }
示例#12
0
        public void EntryAction(
            AsyncPassiveStateMachine <int, int> machine,
            bool entryActionExecuted,
            bool asyncEntryActionExecuted)
        {
            "establish a state machine with entry action on a state".x(() =>
            {
                machine = new AsyncPassiveStateMachine <int, int>();

                machine.In(State)
                .ExecuteOnEntry(() => entryActionExecuted = true)
                .ExecuteOnEntry(async() =>
                {
                    asyncEntryActionExecuted = true;
                    await Task.Yield();
                });
            });

            "when entering the state".x(async() =>
            {
                await machine.Initialize(State);
                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 InitializeALoadedStateMachine(
            AsyncPassiveStateMachine <int, int> machine,
            Exception receivedException)
        {
            "establish a loaded initialized state machine".x(async() =>
            {
                machine = new AsyncPassiveStateMachine <int, int>();

                var loader = new Persisting.StateMachineLoader <int>();

                loader.SetCurrentState(new Initializable <int> {
                    Value = 1
                });
                loader.SetHistoryStates(new Dictionary <int, int>());

                await machine.Load(loader);
            });

            "when initializing the state machine".x(async() =>
                                                    receivedException = await Catch.Exception(async() =>
                                                                                              await machine.Initialize(0)));

            "should throw an invalid operation exception".x(() =>
            {
                receivedException
                .Should().BeAssignableTo <InvalidOperationException>();
                receivedException.Message
                .Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized);
            });
        }
示例#14
0
        public void ExitActionException(AsyncPassiveStateMachine <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(async() =>
            {
                await machine.Start();
                await machine.Fire(Values.Event, Values.Parameter);
            });

            this.ItShouldHandleTransitionException();
        }
示例#15
0
        public void NoExceptionHandlerRegistered(
            AsyncPassiveStateMachine <int, int> machine,
            Exception catchedException)
        {
            "establish an exception throwing state machine without a registered exception handler".x(async() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>();
                stateMachineDefinitionBuilder
                .In(Values.Source)
                .On(Values.Event).Execute(() => throw Values.Exception);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(Values.Source)
                          .Build()
                          .CreatePassiveStateMachine();

                await machine.Start();
            });

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

            "should (re-)throw exception".x(() =>
                                            catchedException.InnerException
                                            .Should().BeSameAs(Values.Exception));
        }
示例#16
0
        public void StartingException(AsyncPassiveStateMachine <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(Values.Source)
                          .Build()
                          .CreatePassiveStateMachine();

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

            "when starting the state machine".x(async() =>
            {
                await 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));
        }
示例#17
0
        public void NoMatchingGuard(
            AsyncPassiveStateMachine <int, int> machine)
        {
            bool declined = false;

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

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

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

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

                await machine.Initialize(SourceState);
                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"));
        }
示例#18
0
        public void ExceptionHandling(
            AsyncPassiveStateMachine <int, int> machine,
            bool exitAction1Executed,
            bool exitAction2Executed,
            bool exitAction3Executed,
            bool exitAction4Executed)
        {
            var exception2        = new Exception();
            var exception3        = new Exception();
            var exception4        = new Exception();
            var receivedException = new List <Exception>();

            "establish a state machine with several exit actions on a state and some of them throw an exception".x(() =>
            {
                machine = new AsyncPassiveStateMachine <int, int>();

                machine.In(State)
                .ExecuteOnExit(() => exitAction1Executed = true)
                .ExecuteOnExit(() =>
                {
                    exitAction2Executed = true;
                    throw exception2;
                })
                .ExecuteOnExit(() =>
                {
                    exitAction3Executed = true;
                    throw exception3;
                })
                .ExecuteOnExit(async() =>
                {
                    exitAction4Executed = true;
                    await Task.Yield();
                    throw exception4;
                })
                .On(Event).Goto(AnotherState);

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

            "when entering the state".x(async() =>
            {
                await machine.Initialize(State);
                await machine.Start();
                await machine.Fire(Event);
            });

            "it should execute all entry actions on entry".x(()
                                                             => new[]
            {
                exitAction1Executed,
                exitAction2Executed,
                exitAction3Executed,
                exitAction4Executed
            }.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));
        }
        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());
        }
示例#20
0
        public void Background()
        {
            this.receivedTransitionExceptionEventArgs = null;

            this.machine = new AsyncPassiveStateMachine <int, int>();

            this.machine.TransitionExceptionThrown += (s, e) => this.receivedTransitionExceptionEventArgs = e;
        }
示例#21
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));
        }
示例#22
0
        public void SavingEventsForPassiveStateMachine(
            AsyncPassiveStateMachine <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()
                          .CreatePassiveStateMachine();
            });

            "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);
            });
        }
示例#23
0
        public void Loading(
            StateMachineSaver <State> saver,
            StateMachineLoader <State> loader,
            FakeExtension extension,
            State sourceState,
            State targetState)
        {
            "establish a saved state machine with history"._(async() =>
            {
                var machine = new AsyncPassiveStateMachine <State, Event>();
                DefineMachine(machine);
                await machine.Initialize(State.A);
                await machine.Start();
                await machine.Fire(Event.S2);     // set history of super state S
                await machine.Fire(Event.B);      // set current state to B

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

                await machine.Save(saver);
            });

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

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

                DefineMachine(loadedMachine);
                await loadedMachine.Load(loader);

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

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

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

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

            "it should notify extensions"._(()
                                            => extension.LoadedCurrentState
                                            .Should().BeEquivalentTo(State.B));
        }
示例#24
0
            public SubmissionStateMachine(Enrollee enrollee, SubmissionService submissionService)
            {
                _enrollee          = enrollee;
                _submissionService = submissionService;

                var stateMachineBuilder = InitBuilder();

                stateMachineBuilder.WithInitialState(FromEnrollee(enrollee));

                _machine = stateMachineBuilder.Build().CreatePassiveStateMachine();
                _machine.TransitionDeclined += (sender, e) => { throw new InvalidActionException(); };

                _machine.Start();
            }
        public void CustomFactory(
            StandardFactory <string, int> factory)
        {
            "establish a custom factory".x(()
                                           => factory = A.Fake <StandardFactory <string, int> >());

            "when creating a passive state machine".x(() =>
            {
                var machine = new AsyncPassiveStateMachine <string, int>("_", factory);

                machine.In("initial").On(42).Goto("answer");
            });

            "it should use custom factory to create internal instances".x(()
                                                                          => A.CallTo(factory).MustHaveHappened());
        }
        public void DefaultStateMachineName(
            AsyncPassiveStateMachine <string, int> machine,
            StateMachineNameReporter reporter)
        {
            "establish an instantiated passive state machine".x(()
                                                                => machine = new AsyncPassiveStateMachine <string, int>());

            "establish a state machine reporter".x(()
                                                   => reporter = new StateMachineNameReporter());

            "when the state machine report is generated".x(()
                                                           => machine.Report(reporter));

            "it should use the type of the state machine as name for state machine".x(()
                                                                                      => reporter.StateMachineName
                                                                                      .Should().Be("Appccelerate.StateMachine.AsyncPassiveStateMachine<System.String,System.Int32>"));
        }
示例#27
0
        public void Report(
            IAsyncStateMachine <string, int> machine,
            IStateMachineReport <string, int> report)
        {
            "establish a state machine"._(()
                                          => machine = new AsyncPassiveStateMachine <string, int>());

            "establish a state machine reporter"._(()
                                                   => report = A.Fake <IStateMachineReport <string, int> >());

            "when creating a report"._(()
                                       => machine.Report(report));

            "it should call the passed reporter"._(()
                                                   => A.CallTo(() => report.Report(A <string> ._, A <IEnumerable <IState <string, int> > > ._, A <Initializable <string> > ._))
                                                   .MustHaveHappened());
        }
示例#28
0
        public void MultipleExitActions(
            AsyncPassiveStateMachine <int, int> machine,
            bool exitAction1Executed,
            bool exitAction2Executed,
            bool asyncExitAction1Executed,
            bool asyncExitAction2Executed)
        {
            "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)
                .ExecuteOnExit(async() =>
                {
                    asyncExitAction1Executed = true;
                    await Task.Yield();
                })
                .ExecuteOnExit(async() =>
                {
                    asyncExitAction2Executed = true;
                    await Task.Yield();
                })
                .On(Event).Goto(AnotherState);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();
            });

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

            "it should execute all exit actions".x(()
                                                   => new[]
            {
                exitAction1Executed,
                exitAction2Executed,
                asyncExitAction1Executed,
                asyncExitAction2Executed
            }.Should().Equal(true, true, true, true));
        }
示例#29
0
        public void ExitActionWithParameter(
            AsyncPassiveStateMachine <int, int> machine,
            string receivedParameter,
            string asyncReceivedParameter)
        {
            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 => receivedParameter = p, parameter)
                .ExecuteOnExitParametrized(
                    async p =>
                {
                    asyncReceivedParameter = p;
                    await Task.Yield();
                },
                    parameter)
                .On(Event).Goto(AnotherState);
                machine = stateMachineDefinitionBuilder
                          .WithInitialState(State)
                          .Build()
                          .CreatePassiveStateMachine();
            });

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

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

            "it should pass parameter to the synchronous exit action".x(() =>
                                                                        receivedParameter.Should().Be(parameter));

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

            "it should pass parameter to the asynchronous exit action".x(() =>
                                                                         asyncReceivedParameter.Should().Be(parameter));
        }
示例#30
0
        public void BeforeExecutingEntryActionsHierarchical(
            AsyncPassiveStateMachine <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(async() =>
            {
                var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, string>();
                stateMachineDefinitionBuilder
                .DefineHierarchyOn("A")
                .WithHistoryType(HistoryType.None)
                .WithInitialSubState("A0");
                stateMachineDefinitionBuilder
                .In("0")
                .On("A0")
                .Goto("A0");
                machine = stateMachineDefinitionBuilder
                          .WithInitialState("0")
                          .Build()
                          .CreatePassiveStateMachine(Name);

                machine.AddExtension(extension);

                await 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.ExtractOrThrow() == "A0"),
                                                                                                                               A <IStateDefinition <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.ExtractOrThrow() == "A0"),
                                                                                                                    A <IStateDefinition <string, string> > .That.Matches(x => x.Id == "A0"),
                                                                                                                    A <ITransitionContext <string, string> > .That.Matches(x => x.EventId.Value == "A0")))
                                                                                                    .MustHaveHappened());
        }