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(); }
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 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"); }
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); }
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 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 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)); }
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")); }
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()); }
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 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"); }); }
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(); }
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); }
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 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)); }
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)); }
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(); }
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()); }
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)); }
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)); }
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")); }
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"); }); }
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 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(); }
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); }); }
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")); }
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 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)); }
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()); }
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); }