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"._(() => { machine = new PassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnExitParametrized(p => parameter = p, Parameter) .On(Event).Goto(AnotherState); }); "when leaving the state"._(() => { machine.Initialize(State); machine.Start(); machine.Fire(Event); }); "it should execute the exit action"._(() => parameter.Should().NotBeNull()); "it should pass parameter to the exit action"._(() => parameter.Should().Be(Parameter)); }
public void MultipleExitActions( PassiveStateMachine <int, int> machine, bool exitAction1Executed, bool exitAction2Executed) { "establish a state machine with several exit actions on a state"._(() => { machine = new PassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnExit(() => exitAction1Executed = true) .ExecuteOnExit(() => exitAction2Executed = true) .On(Event).Goto(AnotherState); }); "when leaving the state"._(() => { machine.Initialize(State); machine.Start(); machine.Fire(Event); }); "It should execute all exit actions"._(() => { exitAction1Executed .Should().BeTrue("first action should be executed"); exitAction2Executed .Should().BeTrue("second action should be executed"); }); }
public void EventsQueueing( IStateMachine <string, int> machine) { const int FirstEvent = 0; const int SecondEvent = 1; bool arrived = false; "establish a passive state machine with transitions"._(() => { machine = new PassiveStateMachine <string, int>(); machine.In("A").On(FirstEvent).Goto("B"); machine.In("B").On(SecondEvent).Goto("C"); machine.In("C").ExecuteOnEntry(() => arrived = true); machine.Initialize("A"); }); "when firing an event onto the state machine"._(() => { machine.Fire(FirstEvent); machine.Fire(SecondEvent); machine.Start(); }); "it should queue event at the end"._(() => arrived.Should().BeTrue("state machine should arrive at destination state")); }
public void EntryActionWithParameter( PassiveStateMachine <int, int> machine, string parameter) { const string Parameter = "parameter"; "establish a state machine with entry action with parameter on a state"._(() => { machine = new PassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnEntryParametrized(p => parameter = p, Parameter); }); "when entering the state"._(() => { machine.Initialize(State); machine.Start(); }); "it should execute the entry action"._(() => parameter.Should().NotBeNull()); "it should pass parameter to the entry action"._(() => parameter.Should().Be(Parameter)); }
public void CustomTypesForStatesAndEvents( PassiveStateMachine <MyState, MyEvent> machine, bool arrivedInStateB) { "establish a state machine with custom types for states and events"._(() => { machine = new PassiveStateMachine <MyState, MyEvent>(); machine.In(new MyState("A")) .On(new MyEvent(1)).Goto(new MyState("B")); machine.In(new MyState("B")) .ExecuteOnEntry(() => arrivedInStateB = true); machine.Initialize(new MyState("A")); machine.Start(); }); "when using the state machine"._(() => machine.Fire(new MyEvent(1))); "it should use equals to compare states and events"._(() => arrivedInStateB.Should().BeTrue("state B should be current state")); }
public void MatchingGuard( PassiveStateMachine <int, int> machine, CurrentStateExtension currentStateExtension) { "establish a state machine with guarded transitions"._(() => { machine = new PassiveStateMachine <int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState) .If(() => true).Goto(DestinationState) .If(() => true).Goto(ErrorState) .Otherwise().Goto(ErrorState); machine.Initialize(SourceState); machine.Start(); }); "when an event is fired"._(() => machine.Fire(Event)); "it should take transition guarded with first matching guard"._(() => currentStateExtension.CurrentState.Should().Be(DestinationState)); }
public void MultipleEntryActions( PassiveStateMachine <int, int> machine, bool entryAction1Executed, bool entryAction2Executed) { "establish a state machine with several entry actions on a state"._(() => { machine = new PassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnEntry(() => entryAction1Executed = true) .ExecuteOnEntry(() => entryAction2Executed = true); }); "when entering the state"._(() => { machine.Initialize(State); machine.Start(); }); "It should execute all entry actions"._(() => { entryAction1Executed .Should().BeTrue("first action should be executed"); entryAction2Executed .Should().BeTrue("second action should be executed"); }); }
public void Reinitialization( PassiveStateMachine <int, int> machine, Exception receivedException) { "establish an initialized state machine"._(() => { machine = new PassiveStateMachine <int, int>(); machine.Initialize(TestState); }); "when state machine is initialized again"._(() => { try { machine.Initialize(TestState); } catch (Exception e) { receivedException = e; } }); "should throw an invalid operation exception"._(() => { receivedException .Should().BeAssignableTo <InvalidOperationException>(); receivedException.Message .Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized); }); }
public void OtherwiseGuard( PassiveStateMachine <int, int> machine, CurrentStateExtension currentStateExtension) { "establish a state machine with otherwise guard and no machting other guard"._(() => { machine = new PassiveStateMachine <int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState) .Otherwise().Goto(DestinationState); machine.Initialize(SourceState); machine.Start(); }); "when an event is fired"._(() => machine.Fire(Event)); "it should_take_transition_guarded_with_otherwise"._(() => currentStateExtension.CurrentState.Should().Be(DestinationState)); }
public void Start( PassiveStateMachine <int, int> machine, bool entryActionExecuted) { "establish an initialized state machine"._(() => { machine = new PassiveStateMachine <int, int>(); machine.AddExtension(testExtension); machine.In(TestState) .ExecuteOnEntry(() => entryActionExecuted = true); machine.Initialize(TestState); }); "when starting the state machine"._(() => machine.Start()); "should set current state of state machine to state to which it is initialized"._(() => this.testExtension.CurrentState.Should().Be(TestState)); "should execute entry action of state to which state machine is initialized"._(() => entryActionExecuted.Should().BeTrue()); }
public void EventArgument( PassiveStateMachine <int, int> machine, int passedArgument) { const int Event = 3; const int AnotherState = 3; const int Argument = 17; "establish a state machine with an entry action taking an event argument"._(() => { machine = new PassiveStateMachine <int, int>(); machine.In(State) .On(Event).Goto(AnotherState); machine.In(AnotherState) .ExecuteOnEntry((int argument) => passedArgument = argument); }); "when entering the state"._(() => { machine.Initialize(State); machine.Start(); machine.Fire(Event, Argument); }); "it should pass event argument to entry action"._(() => passedArgument.Should().Be(Argument)); }
public void NoMatchingGuard( PassiveStateMachine <int, int> machine, CurrentStateExtension currentStateExtension) { bool declined = false; "establish state machine with no matching guard"._(() => { machine = new PassiveStateMachine <int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState); machine.TransitionDeclined += (sender, e) => declined = true; machine.Initialize(SourceState); machine.Start(); }); "when an event is fired"._(() => machine.Fire(Event)); "it should notify about declined transition"._(() => declined.Should().BeTrue("TransitionDeclined event should be fired")); }
public void Background() { this.receivedTransitionExceptionEventArgs = null; this.machine = new PassiveStateMachine <int, int>(); this.machine.TransitionExceptionThrown += (s, e) => this.receivedTransitionExceptionEventArgs = e; }
public void ExceptionHandling( PassiveStateMachine <int, int> machine, bool exitAction1Executed, bool exitAction2Executed, bool exitAction3Executed) { var exception2 = new Exception(); var exception3 = 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"._(() => { machine = new PassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnExit(() => exitAction1Executed = true) .ExecuteOnExit(() => { exitAction2Executed = true; throw exception2; }) .ExecuteOnExit(() => { exitAction3Executed = true; throw exception3; }) .On(Event).Goto(AnotherState); machine.TransitionExceptionThrown += (s, e) => receivedException.Add(e.Exception); }); "when entering the state"._(() => { machine.Initialize(State); machine.Start(); machine.Fire(Event); }); "it should execute all entry actions on entry"._(() => { exitAction1Executed .Should().BeTrue("action 1 should be executed"); exitAction2Executed .Should().BeTrue("action 2 should be executed"); exitAction3Executed .Should().BeTrue("action 3 should be executed"); }); "it should handle all exceptions of all throwing entry actions by firing the TransitionExceptionThrown event"._(() => receivedException .Should().BeEquivalentTo(new object[] { exception2, exception3 })); }
public void CommonAncestor( PassiveStateMachine <int, int> machine) { const int CommonAncestorState = 0; const int SourceState = 1; const int ParentOfSourceState = 2; const int SiblingOfSourceState = 3; const int DestinationState = 4; const int ParentOfDestinationState = 5; const int SiblingOfDestinationState = 6; const int Event = 0; bool commonAncestorStateLeft = false; "establish a hierarchical state machine"._(() => { machine = new PassiveStateMachine <int, int>(); machine.DefineHierarchyOn(CommonAncestorState) .WithHistoryType(HistoryType.None) .WithInitialSubState(ParentOfSourceState) .WithSubState(ParentOfDestinationState); machine.DefineHierarchyOn(ParentOfSourceState) .WithHistoryType(HistoryType.None) .WithInitialSubState(SourceState) .WithSubState(SiblingOfSourceState); machine.DefineHierarchyOn(ParentOfDestinationState) .WithHistoryType(HistoryType.None) .WithInitialSubState(DestinationState) .WithSubState(SiblingOfDestinationState); machine.In(SourceState) .On(Event).Goto(DestinationState); machine.In(CommonAncestorState) .ExecuteOnExit(() => commonAncestorStateLeft = true); machine.Initialize(SourceState); machine.Start(); }); "when firing an event resulting in a transition with a common ancestor"._(() => machine.Fire(Event)); "the state machine should remain inside common ancestor state"._(() => commonAncestorStateLeft .Should().BeFalse()); }
public void Report( IStateMachine <string, int> machine, IStateMachineReport <string, int> report) { "establish a state machine"._(() => machine = new PassiveStateMachine <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> > ._))); }
public void Loading( StateMachineSaver <State> saver, StateMachineLoader <State> loader, State sourceState, State targetState) { "establish a saved state machine with history"._(() => { var machine = new PassiveStateMachine <State, Event>(); DefineMachine(machine); machine.Initialize(State.A); machine.Start(); machine.Fire(Event.S2); // set history of super state S machine.Fire(Event.B); // set current state to B saver = new StateMachineSaver <State>(); loader = new StateMachineLoader <State>(); machine.Save(saver); }); "when state machine is loaded"._(() => { loader.SetCurrentState(saver.CurrentStateId); loader.SetHistoryStates(saver.HistoryStates); var loadedMachine = new PassiveStateMachine <State, Event>(); DefineMachine(loadedMachine); loadedMachine.Load(loader); loadedMachine.TransitionCompleted += (sender, args) => { sourceState = args.StateId; targetState = args.NewStateId; }; loadedMachine.Start(); loadedMachine.Fire(Event.S); }); "it should reset current state"._(() => sourceState.Should().Be(State.B)); "it should reset all history states of super states"._(() => targetState.Should().Be(State.S2)); }
public void Background() { "establish initialized state machine"._(() => { this.machine = new PassiveStateMachine <int, int>(); this.extension = new RecordEventsExtension(); this.machine.AddExtension(extension); this.machine.In(A) .On(Event).Goto(B); this.machine.In(B) .On(Event).Goto(A); this.machine.Initialize(A); }); }
public void CustomFactory( PassiveStateMachine <string, int> machine, StandardFactory <string, int> factory) { "establish a custom factory"._(() => { factory = A.Fake <StandardFactory <string, int> >(); }); "when creating a passive state machine"._(() => { machine = new PassiveStateMachine <string, int>("_", factory); machine.In("initial").On(42).Goto("answer"); }); "it should use custom factory to create internal instances"._(() => A.CallTo(factory).MustHaveHappened()); }
public void Initialize( PassiveStateMachine <int, int> machine, bool entryActionExecuted) { "establish a state machine"._(() => { machine = new PassiveStateMachine <int, int>(); machine.AddExtension(testExtension); machine.In(TestState) .ExecuteOnEntry(() => entryActionExecuted = true); }); "when state machine is initialized"._(() => machine.Initialize(TestState)); "should not yet execute any entry actions"._(() => entryActionExecuted.Should().BeFalse()); }
public void AddingExtensions( IStateMachine <string, int> machine, IExtension <string, int> extension) { "establish a state machine"._(() => { machine = new PassiveStateMachine <string, int>(); extension = A.Fake <IExtension <string, int> >(); }); "when adding an extension"._(() => { machine.AddExtension(extension); machine.Initialize("initial"); }); "it should notify extension about internal events"._(() => A.CallTo(extension).MustHaveHappened()); }
public void Background() { "establish a hierarchical state machine"._(() => { testExtension = new CurrentStateExtension(); machine = new PassiveStateMachine <int, int>(); machine.AddExtension(testExtension); machine.DefineHierarchyOn(SuperState) .WithHistoryType(HistoryType.None) .WithInitialSubState(LeafState); machine.In(SuperState) .ExecuteOnEntry(() => entryActionOfSuperStateExecuted = true); machine.In(LeafState) .ExecuteOnEntry(() => entryActionOfLeafStateExecuted = true); }); }
public void ExecutingTransition( PassiveStateMachine <int, int> machine, string actualParameter, bool exitActionExecuted, bool entryActionExecuted) { "establish a state machine with transitions"._(() => { machine = new PassiveStateMachine <int, int>(); machine.AddExtension(CurrentStateExtension); machine.In(SourceState) .ExecuteOnExit(() => exitActionExecuted = true) .On(Event).Goto(DestinationState).Execute <string>(p => actualParameter = p); machine.In(DestinationState) .ExecuteOnEntry(() => entryActionExecuted = true); machine.Initialize(SourceState); machine.Start(); }); "when firing an event onto the state machine"._(() => machine.Fire(Event, Parameter)); "it should_execute_transition_by_switching_state"._(() => CurrentStateExtension.CurrentState.Should().Be(DestinationState)); "it should_execute_transition_actions"._(() => actualParameter.Should().NotBeNull()); "it should_pass_parameters_to_transition_action"._(() => actualParameter.Should().Be(Parameter)); "it should_execute_exit_action_of_source_state"._(() => exitActionExecuted.Should().BeTrue()); "it should_execute_entry_action_of_destination_state"._(() => entryActionExecuted.Should().BeTrue()); }
public void StartingAnUninitializedStateMachine( PassiveStateMachine <int, int> machine, Exception receivedException) { "establish an uninitialized state machine"._(() => { machine = new PassiveStateMachine <int, int>(); }); "when starting the state machine"._(() => receivedException = Catch.Exception(() => machine.Start())); "should throw an invalid operation exception"._(() => { receivedException .Should().BeAssignableTo <InvalidOperationException>(); receivedException.Message .Should().Be(ExceptionMessages.StateMachineNotInitialized); }); }
public void EntryAction( PassiveStateMachine <int, int> machine, bool entryActionExecuted) { "establish a state machine with entry action on a state"._(() => { machine = new PassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnEntry(() => entryActionExecuted = true); }); "when entering the state"._(() => { machine.Initialize(State); machine.Start(); }); "it should execute the entry action"._(() => entryActionExecuted.Should().BeTrue()); }
public void DefaultStateMachineName( PassiveStateMachine <string, int> machine, StateMachineNameReporter reporter) { "establish an instantiated passive state machine"._(() => { machine = new PassiveStateMachine <string, int>(); }); "establish a state machine reporter"._(() => { reporter = new StateMachineNameReporter(); }); "when the state machine report is generated"._(() => machine.Report(reporter)); "it should use the type of the state machine as name for state machine"._(() => reporter.StateMachineName .Should().Be("Appccelerate.StateMachine.PassiveStateMachine<System.String,System.Int32>")); }
public void LoadingAnInitializedStateMachine( PassiveStateMachine <string, int> machine, Exception receivedException) { "establish an initialized state machine"._(() => { machine = new PassiveStateMachine <string, int>(); machine.Initialize("initial"); }); "when state machine is loaded"._(() => { receivedException = Catch.Exception(() => machine.Load(A.Fake <IStateMachineLoader <string> >())); }); "it should throw invalid operation exception"._(() => { receivedException.Should().BeOfType <InvalidOperationException>(); receivedException.Message.Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized); }); }
public void ExitAction( PassiveStateMachine <int, int> machine, bool exitActionExecuted) { "establish a state machine with exit action on a state"._(() => { machine = new PassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnExit(() => exitActionExecuted = true) .On(Event).Goto(AnotherState); }); "when leaving the state"._(() => { machine.Initialize(State); machine.Start(); machine.Fire(Event); }); "it should execute the exit action"._(() => exitActionExecuted.Should().BeTrue()); }
public void CustomStateMachineName( PassiveStateMachine <string, int> machine, StateMachineNameReporter reporter) { const string Name = "custom name"; "establish an instantiated passive state machine with custom name"._(() => { machine = new PassiveStateMachine <string, int>(Name); }); "establish a state machine reporter"._(() => { reporter = new StateMachineNameReporter(); }); "when the state machine report is generated"._(() => machine.Report(reporter)); "it should use custom name for state machine"._(() => reporter.StateMachineName .Should().Be(Name)); }
public void InitializeALoadedStateMachine( PassiveStateMachine <int, int> machine, Exception receivedException) { "establish a loaded state machine"._(() => { machine = new PassiveStateMachine <int, int>(); machine.Load(A.Fake <IStateMachineLoader <int> >()); }); "when initializing the state machine"._(() => receivedException = Catch.Exception(() => machine.Initialize(0))); "should throw an invalid operation exception"._(() => { receivedException .Should().BeAssignableTo <InvalidOperationException>(); receivedException.Message .Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized); }); }