public void FluentStateMachineBuilder_AfterExit_DefiningState_AddsEvent() { var loggedEvents = new List <string>(); Action <string, TransitionEventArgs <StubStateModel> > logEvent = (message, e) => { loggedEvents.Add(string.Format("{0} from {1} to {2} on {3}", message, e.From, e.To, e.Trigger)); }; var machine = FluentStateMachine <StubStateModel> .Describe() .State("s1") .AfterExit(e => logEvent("AfterExit", e)) .TransitionsTo("s2").On("t") .Initiates() .State("s2") .AfterExit(e => logEvent("AfterExit", e)) .TransitionsTo("s1").On("t") .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; machine.Trigger("t", model); Assert.Equal("s2", model.CurrentState.ToString()); Assert.Equal(1, loggedEvents.Count()); Assert.Equal("AfterExit from s1 to s2 on t", loggedEvents[0]); }
public void IStateModelExtensions_AvailableTriggers_NullMachine_ThrowsNullEx() { var mockModel = new StubStateModel(); Assert.Throws <ArgumentNullException>(() => mockModel.AvailableTriggers((IStateMachine <StubStateModel>)null)); }
public void StateMachine_AvailableTriggers_ConcatsModelsTransWithGlobal_ReturnsDistinctTrigsByName() { var model = new StubStateModel(); var machine = new StateMachine <StubStateModel>(); var trigger1 = new Trigger("t1"); var trigger2 = new Trigger("t2"); var state1 = new State <StubStateModel>("s1"); var state2 = new State <StubStateModel>("s2"); var state3 = new State <StubStateModel>("s3"); var state4 = new State <StubStateModel>("s4"); var statetrans1 = new Transition <StubStateModel>(trigger1, state1, state2); var statetrans2 = new Transition <StubStateModel>(trigger1, state1, state3); var statetrans3 = new Transition <StubStateModel>(trigger2, state1, state3); var globaltrans1 = new Transition <StubStateModel>(trigger2, null, state1); machine.AddGlobalTransition(globaltrans1); state1.AddTransition(statetrans1); state1.AddTransition(statetrans2); state1.AddTransition(statetrans3); model.CurrentState = state1; var result = machine.AvailableTriggers(model); Assert.Equal(2, result.Count()); Assert.Equal(trigger1, result.ToList()[0]); Assert.Equal(trigger2, result.ToList()[1]); }
public void IStateModelExtensions_AvailableTriggers_NullMachine_ThrowsNullEx() { var mockModel = new StubStateModel(); Assert.Throws<ArgumentNullException>(() => IStateModelExtensions.AvailableTriggers(mockModel, (IStateMachine<StubStateModel>)null)); }
public void FluentStateMachine_AvailableStates_ValidParms_CallsReturnsMachineAvailable() { var machineMock = new Mock<IStateMachine<StubStateModel>>(); var state1 = new State<StubStateModel>("s1"); var state2 = new State<StubStateModel>("s2"); var state3 = new State<StubStateModel>("s3"); var allStates = new List<State<StubStateModel>>(); allStates.Add(state1); allStates.Add(state2); allStates.Add(state3); var model = new StubStateModel(); machineMock.Setup(m => m.AvailableStates(model)).Returns(allStates).Verifiable(); var fluentMachine = new FluentStateMachine<StubStateModel>( machineMock.Object, allStates, state2, null, null, null); var result = fluentMachine.AvailableStates(model); Assert.Same(allStates, result); machineMock.VerifyAll(); }
StateMachine_Trigger_TransitionFromCurrentToSame_ConfiggedNotToRaiseExcep_DoesNotRaiseTransitionChangeEvents() { var config = new StateMachineConfiguration { RaiseExceptionBeforeTransitionToSameState = false }; var machine = new StateMachine <StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State <StubStateModel>("state1"); TransitionEventArgs <StubStateModel> transitioningArgs = null; state1.Entered += (s, e) => { transitioningArgs = e; }; TransitionEventArgs <StubStateModel> transitionedArgs = null; state1.Exiting += (s, e) => { transitionedArgs = e; }; state1.AddTransition(trigger1, state1); model.CurrentState = state1; // set up scenario where state would transition from current to same state. // so no true transition would not occur // should not throw exception and that's good enough for us machine.Trigger(trigger1, model); // verify that no transition events occurred Assert.Null(transitioningArgs); Assert.Null(transitionedArgs); }
public void IStateModelExtensions_Trigger_NullMachine_StringTrigger_ThrowsNullEx() { var mockModel = new StubStateModel(); Assert.Throws <ArgumentNullException>(() => mockModel.Trigger("triggerName", (IStateMachine <StubStateModel>)null)); }
public void FluentStateMachine_AvailableStates_ValidParms_CallsReturnsMachineAvailable() { var machineMock = new Mock <IStateMachine <StubStateModel> >(); var state1 = new State <StubStateModel>("s1"); var state2 = new State <StubStateModel>("s2"); var state3 = new State <StubStateModel>("s3"); var allStates = new List <State <StubStateModel> >(); allStates.Add(state1); allStates.Add(state2); allStates.Add(state3); var model = new StubStateModel(); machineMock.Setup(m => m.AvailableStates(model)).Returns(allStates).Verifiable(); var fluentMachine = new FluentStateMachine <StubStateModel>( machineMock.Object, allStates, state2, null, null, null); var result = fluentMachine.AvailableStates(model); Assert.Same(allStates, result); machineMock.VerifyAll(); }
public void FluentStateMachineBuilder_AfterExit_DefiningState_AddsEvent() { var loggedEvents = new List<string>(); Action<string, TransitionEventArgs<StubStateModel>> logEvent = (message, e) => { loggedEvents.Add(String.Format("{0} from {1} to {2} on {3}", message, e.From, e.To, e.Trigger)); }; var machine = FluentStateMachine<StubStateModel>.Describe() .State("s1") .AfterExit(e => logEvent("AfterExit", e)) .TransitionsTo("s2").On("t") .Initiates() .State("s2") .AfterExit(e => logEvent("AfterExit", e)) .TransitionsTo("s1").On("t") .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; machine.Trigger("t", model); Assert.Equal("s2", model.CurrentState.ToString()); Assert.Equal(1, loggedEvents.Count()); Assert.Equal("AfterExit from s1 to s2 on t", loggedEvents[0]); }
public void FluentStateMachine_Trigger_ValidParms_CallsReturnsMachineTrigger() { var machineMock = new Mock <IStateMachine <StubStateModel> >(); var state1 = new State <StubStateModel>("s1"); var state2 = new State <StubStateModel>("s2"); var state3 = new State <StubStateModel>("s3"); var allStates = new List <State <StubStateModel> >(); allStates.Add(state1); allStates.Add(state2); allStates.Add(state3); var model = new StubStateModel(); var fluentMachine = new FluentStateMachine <StubStateModel>( machineMock.Object, allStates, state2, null, null, null); machineMock.Setup(m => m.Trigger(It.Is <Trigger>(t => t.Name == "trigger1"), model)).Verifiable(); fluentMachine.Trigger("trigger1", model); machineMock.VerifyAll(); }
public void StateMachine_AvailableTriggers_ModelStateNotState_ThrowInvalidStateModel() { var model = new StubStateModel(); var machine = new StateMachine <StubStateModel>(); Assert.Throws <InvalidStateModelException>(() => machine.AvailableTriggers(model)); }
public void IStateModelExtensions_Trigger_NullTriggerName_ThrowsNullEx() { var mockModel = new StubStateModel(); var mockMachine = new Mock <IStateMachine <StubStateModel> >(); Assert.Throws <ArgumentNullException>(() => mockModel.Trigger((string)null, mockMachine.Object)); }
StateMachine_Trigger_ValidTriggerAndTrans_ChoosesFirstTranWthPassGuardNonGlobal_SameAsCurrentState_NoRaised() { var model = new StubStateModel(); var machine = new StateMachine <StubStateModel>(); TransitionEventArgs <StubStateModel> transitioningArgs = null; machine.Transitioning += (s, e) => { transitioningArgs = e; }; TransitionEventArgs <StubStateModel> transitionedArgs = null; machine.Transitioned += (s, e) => { transitionedArgs = e; }; var trigger1 = new Trigger("t1"); var trigger2 = new Trigger("t2"); var state1Mock = new Mock <State <StubStateModel> >("s1"); var state2Mock = new Mock <State <StubStateModel> >("s2"); var state3Mock = new Mock <State <StubStateModel> >("s3"); var state4Mock = new Mock <State <StubStateModel> >("s4"); var state1 = state1Mock.Object; var state2 = state2Mock.Object; var state3 = state3Mock.Object; var state4 = state4Mock.Object; var statetrans1 = new Transition <StubStateModel>(trigger1, state1, state2, m => 1 == 2); var statetrans2 = new Transition <StubStateModel>(trigger1, state1, state3, m => 1 == 1); var statetrans3 = new Transition <StubStateModel>(trigger2, state1, state3); var globaltrans1 = new Transition <StubStateModel>(trigger1, null, state1, m => 1 == 1); machine.AddGlobalTransition(globaltrans1); state1.AddTransition(statetrans1); state1.AddTransition(statetrans2); state1.AddTransition(statetrans3); model.CurrentState = state1; // so when trigger1 is triggered on state model whose current state is state1, // it will fall through to the first matching transition with a passing guard, the second state transition to state 1 // but since this is same state as current state, it shouldn't actually transition. no events should be called. machine.Trigger(trigger1, model); // verify that no transition events were calledb state1Mock.Verify(s => s.RaiseEntered( It.IsAny <StubStateModel>(), It.IsAny <State <StubStateModel> >(), It.IsAny <Trigger>()), Times.Never()); state1Mock.Verify(s => s.RaiseExiting( It.IsAny <StubStateModel>(), It.IsAny <State <StubStateModel> >(), It.IsAny <Trigger>()), Times.Never()); Assert.Null(transitioningArgs); Assert.Null(transitionedArgs); }
public void StateMachine_Trigger_ModelStateNotState_ThrowsInvalidStateModel() { var machine = new StateMachine <StubStateModel>(); var model = new StubStateModel(); var trigger = new Trigger("trigger"); Assert.Throws <InvalidStateModelException>(() => machine.Trigger(trigger, model)); }
public void IStateModelExtensions_Trigger_ValidParms_ObjTrigger_CallsTriggerOnMachine() { var mockModel = new StubStateModel(); var trigger = new Trigger("trigger"); var mockMachine = new Mock <IStateMachine <StubStateModel> >(); mockMachine.Setup(m => m.Trigger(trigger, mockModel)).Verifiable(); mockModel.Trigger(trigger, mockMachine.Object); mockMachine.VerifyAll(); }
public void IStateModelExtensions_Trigger_ValidParms_StringTrigger_CallsTriggerOnMachine() { var mockModel = new StubStateModel(); var mockMachine = new Mock <IStateMachine <StubStateModel> >(); mockMachine.Setup(m => m.Trigger(It.Is <Trigger>(t => t.Name == "triggerName"), mockModel)).Verifiable(); mockModel.Trigger("triggerName", mockMachine.Object); mockMachine.VerifyAll(); }
public void IStateModelExtensions_AvailableStates_ValidParms_CallsReturnsMachineAvailable() { var mockModel = new StubStateModel(); var mockMachine = new Mock<IStateMachine<StubStateModel>>(); var mockStates = new Mock<IEnumerable<State<StubStateModel>>>().Object; mockMachine.Setup(m => m.AvailableStates(mockModel)).Returns(mockStates).Verifiable(); var result = IStateModelExtensions.AvailableStates(mockModel, mockMachine.Object); mockMachine.VerifyAll(); Assert.Same(mockStates, result); }
public void IStateMachineExtensinos_ValidParms_CallsTriggerOnMachineWithParms() { var mockMachine = new Mock<IStateMachine<StubStateModel>>(); var mockModel = new StubStateModel(); mockMachine.Setup(m => m.Trigger(It.Is<Trigger>(t => t.Name == "trigger"), mockModel)).Verifiable(); IStateMachineExtensions.Trigger(mockMachine.Object, "trigger", mockModel); mockMachine.VerifyAll(); }
public void IStateMachineExtensinos_ValidParms_CallsTriggerOnMachineWithParms() { var mockMachine = new Mock <IStateMachine <StubStateModel> >(); var mockModel = new StubStateModel(); mockMachine.Setup(m => m.Trigger(It.Is <Trigger>(t => t.Name == "trigger"), mockModel)).Verifiable(); mockMachine.Object.Trigger("trigger", mockModel); mockMachine.VerifyAll(); }
public void TransitionEventArgs_ValidParms_VerifyAssigns() { var model = new StubStateModel(); var from = new State <StubStateModel>("from"); var to = new State <StubStateModel>("to"); var trigger = new Trigger("trigger"); var args = new TransitionEventArgs <StubStateModel>(model, from, to, trigger); Assert.Same(from, args.From); Assert.Same(to, args.To); Assert.Same(model, args.Model); Assert.Same(trigger, args.Trigger); }
public void IStateModelExtensions_AvailableTriggers_ValidParms_CallsReturnsTriggersAvailable() { var mockModel = new StubStateModel(); var mockTriggers = new Mock <IEnumerable <Trigger> >().Object; var mockMachine = new Mock <IStateMachine <StubStateModel> >(); mockMachine.Setup(m => m.AvailableTriggers(mockModel)).Returns(mockTriggers).Verifiable(); var result = mockModel.AvailableTriggers(mockMachine.Object); mockMachine.VerifyAll(); Assert.Same(mockTriggers, result); }
public void FluentStateMachineBuilder_State_ValidParms_CreatesNewState() { var machine = FluentStateMachine <StubStateModel> .Describe() .State("s1") .Initiates() .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; Assert.Equal("s1", model.CurrentState.ToString()); }
public void FluentStateMachineBuilder_On_SetsTriggerForATransition() { var machine = FluentStateMachine <StubStateModel> .Describe() .State("s1") .TransitionsTo("s2").On("t") .Initiates() .State("s2") .TransitionsTo("s1").On("t") .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; Assert.Equal("s1", model.CurrentState.ToString()); machine.Trigger("t", model); Assert.Equal("s2", model.CurrentState.ToString()); }
StateMachine_Trigger_NoStateOrGlobalTransOnTrigger_ConfigRaiseOnNoTransFalse_NotThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionOnTriggerMatchingNoTransition = false }; var machine = new StateMachine <StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var trigger2 = new Trigger("trigger2"); var state1 = new State <StubStateModel>("state1"); var state2 = new State <StubStateModel>("state2"); state1.AddTransition(trigger1, state2); model.CurrentState = state1; // no exception shoudl happen, and that's good enough for us. machine.Trigger(trigger2, model); }
public void State_RaiseExiting_ValidParms_Handler_TriggersHandlerPassesParmsAndSelf() { var model = new StubStateModel(); var fromState = new State <StubStateModel>("from"); var toState = new State <StubStateModel>("to"); var trigger = new Trigger("trigger"); TransitionEventArgs <StubStateModel> args = null; fromState.Exiting += (s, e) => { args = e; }; fromState.RaiseExiting(model, toState, trigger); Assert.Equal(model, args.Model); Assert.Equal(fromState, args.From); Assert.Equal(toState, args.To); Assert.Equal(trigger, args.Trigger); }
public void FluentStateMachineBuilder_When_WhileDefTrans_AddsGuardToTransition() { var machine = FluentStateMachine <StubStateModel> .Describe() .State("s1") .Initiates() .TransitionsTo("s2").On("t").When(m => false) .TransitionsTo("s3").On("t").When(m => true) .State("s2") .State("s3") .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; Assert.Equal("s1", model.CurrentState.ToString()); machine.Trigger("t", model); Assert.Equal("s3", model.CurrentState.ToString()); }
StateMachine_Trigger_NoPassingTransitionOnTrigger_ConfigRaiseOnNoPassingTranTrue_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionOnTriggerMatchingNoPassingTransition = true }; var machine = new StateMachine <StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State <StubStateModel>("state1"); var state2 = new State <StubStateModel>("state2"); state1.AddTransition(trigger1, state2, m => 1 == 2); model.CurrentState = state1; // set up so that there's a matching transition, but the guard would fail when run Assert.Throws <InvalidTriggerException>(() => machine.Trigger(trigger1, model)); }
StateMachine_Trigger_NoPassingTransitionOnTrigger_ConfigRaiseOnNoPassingTranFalse_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionOnTriggerMatchingNoPassingTransition = false }; var machine = new StateMachine <StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State <StubStateModel>("state1"); var state2 = new State <StubStateModel>("state2"); state1.AddTransition(trigger1, state2, m => 1 == 2); model.CurrentState = state1; // set up so that there's a matching transition, but the guard would fail when run // no exceptions should happen, and that's good enough for us machine.Trigger(trigger1, model); }
public void StateMachine_Trigger_NoStateOrGlobalTransOnTrigger_ConfigRaiseOnNoTransTrue_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionOnTriggerMatchingNoTransition = true }; var machine = new StateMachine <StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var trigger2 = new Trigger("trigger2"); var state1 = new State <StubStateModel>("state1"); var state2 = new State <StubStateModel>("state2"); state1.AddTransition(trigger1, state2); model.CurrentState = state1; // set up so that current state of state 1 doesn't' define a trans for "trigger2", only "trigger1" Assert.Throws <InvalidTriggerException>(() => machine.Trigger(trigger2, model)); }
public void StateMachine_Trigger_TransitionsToSameState_ConfigRaiseOnSameStateTranFalse_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionBeforeTransitionToSameState = false }; var machine = new StateMachine <StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State <StubStateModel>("state1"); var state2 = new State <StubStateModel>("state2"); state1.AddTransition(trigger1, state1); model.CurrentState = state1; // set up scenario where state would transition from current to same state. // so no true transition would not occur // should not throw exception and that's good enough for us machine.Trigger(trigger1, model); }
public void StateMachine_Trigger_TransitionsToSameState_ConfigRaiseOnSameStateTranTrue_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionBeforeTransitionToSameState = true }; var machine = new StateMachine <StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State <StubStateModel>("state1"); var state2 = new State <StubStateModel>("state2"); state1.AddTransition(trigger1, state1); model.CurrentState = state1; // set up scenario where state would transition from current to same state. // so no true transition would not occur Assert.Throws <InvalidTriggerException>(() => machine.Trigger(trigger1, model)); }
public void FluentStateMachineBuilder_DefiningCallbacksOnAll_AllCallbacksCalledInOrder() { var loggedEvents = new List <string>(); Action <string, TransitionEventArgs <StubStateModel> > logEvent = (message, e) => { loggedEvents.Add(string.Format("{0} from {1} to {2} on {3}", message, e.From, e.To, e.Trigger)); }; var machine = FluentStateMachine <StubStateModel> .Describe() .State("s1") .BeforeEntry(e => logEvent("beforeEntry", e)) .AfterEntry(e => logEvent("afterEntry", e)) .BeforeExit(e => logEvent("beforeExit", e)) .AfterExit(e => logEvent("afterExit", e)) .TransitionsTo("s2").On("t") .Initiates() .State("s2") .BeforeEntry(e => logEvent("beforeEntry", e)) .AfterEntry(e => logEvent("afterEntry", e)) .BeforeExit(e => logEvent("beforeExit", e)) .AfterExit(e => logEvent("afterExit", e)) .TransitionsTo("s1").On("t") .BeforeTransition(e => logEvent("beforeTransition", e)) .AfterTransition(e => logEvent("afterTransition", e)) .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; machine.Trigger("t", model); Assert.Equal("s2", model.CurrentState.ToString()); Assert.Equal(6, loggedEvents.Count()); Assert.Equal("beforeTransition from s1 to s2 on t", loggedEvents[0]); Assert.Equal("beforeExit from s1 to s2 on t", loggedEvents[1]); Assert.Equal("beforeEntry from s1 to s2 on t", loggedEvents[2]); Assert.Equal("afterExit from s1 to s2 on t", loggedEvents[3]); Assert.Equal("afterEntry from s1 to s2 on t", loggedEvents[4]); Assert.Equal("afterTransition from s1 to s2 on t", loggedEvents[5]); }
public void StateMachine_Trigger_ValidTriggerAndTrans_ChoosesFirstTranWthPassGuard_SameAsCurrentState_NoRaised() { var model = new StubStateModel(); var machine = new StateMachine<StubStateModel>(); TransitionEventArgs<StubStateModel> transitioningArgs = null; machine.Transitioning += (s, e) => { transitioningArgs = e; }; TransitionEventArgs<StubStateModel> transitionedArgs = null; machine.Transitioned += (s, e) => { transitionedArgs = e; }; var trigger1 = new Trigger("t1"); var trigger2 = new Trigger("t2"); var state1Mock = new Mock<State<StubStateModel>>("s1"); var state2Mock = new Mock<State<StubStateModel>>("s2"); var state3Mock = new Mock<State<StubStateModel>>("s3"); var state4Mock = new Mock<State<StubStateModel>>("s4"); var state1 = state1Mock.Object; var state2 = state2Mock.Object; var state3 = state3Mock.Object; var state4 = state4Mock.Object; var statetrans1 = new Transition<StubStateModel>(trigger1, state1, state2, m => 1 == 2); var statetrans2 = new Transition<StubStateModel>(trigger1, state1, state3, m => 1 == 3); var statetrans3 = new Transition<StubStateModel>(trigger2, state1, state3); var globaltrans1 = new Transition<StubStateModel>(trigger1, null, state1, m => 1 == 1); machine.AddGlobalTransition(globaltrans1); state1.AddTransition(statetrans1); state1.AddTransition(statetrans2); state1.AddTransition(statetrans3); model.CurrentState = state1; // so when trigger1 is triggered on state model whose current state is state1, // it will fall through to the first matching transition with a passing guard, the global transition to state 1 // but since this is same state as current state, it shouldn't actually transition. no events should be called. machine.Trigger(trigger1, model); // verify that no transition events were calledb state1Mock.Verify(s => s.RaiseEntered( It.IsAny<StubStateModel>(), It.IsAny<State<StubStateModel>>(), It.IsAny<Trigger>()), Times.Never()); state1Mock.Verify(s => s.RaiseExiting( It.IsAny<StubStateModel>(), It.IsAny<State<StubStateModel>>(), It.IsAny<Trigger>()), Times.Never()); Assert.Null(transitioningArgs); Assert.Null(transitionedArgs); }
public void FluentStateMachine_Trigger_ValidParms_CallsReturnsMachineTrigger() { var machineMock = new Mock<IStateMachine<StubStateModel>>(); var state1 = new State<StubStateModel>("s1"); var state2 = new State<StubStateModel>("s2"); var state3 = new State<StubStateModel>("s3"); var allStates = new List<State<StubStateModel>>(); allStates.Add(state1); allStates.Add(state2); allStates.Add(state3); var model = new StubStateModel(); var fluentMachine = new FluentStateMachine<StubStateModel>( machineMock.Object, allStates, state2, null, null, null); machineMock.Setup(m => m.Trigger(It.Is<Trigger>(t => t.Name == "trigger1"), model)).Verifiable(); fluentMachine.Trigger("trigger1", model); machineMock.VerifyAll(); }
public void StateMachine_Trigger_NoPassingTransitionOnTrigger_ConfigRaiseOnNoPassingTranFalse_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionOnTriggerMatchingNoPassingTransition = false }; var machine = new StateMachine<StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State<StubStateModel>("state1"); var state2 = new State<StubStateModel>("state2"); state1.AddTransition(trigger1, state2, m => 1 == 2); model.CurrentState = state1; // set up so that there's a matching transition, but the guard would fail when run // no exceptions should happen, and that's good enough for us machine.Trigger(trigger1, model); }
public void StateMachine_Trigger_ValidTriggerAndTrans_ChoosesFirstTranWthPassGuard_DiffAsCurrentState_Raised_Sets() { var model = new StubStateModel(); var machine = new StateMachine<StubStateModel>(); var transitioningEventArgs = new List<TransitionEventArgs<StubStateModel>>(); machine.Transitioning += (s, e) => { transitioningEventArgs.Add(e); }; var transitionedEventArgs = new List<TransitionEventArgs<StubStateModel>>(); machine.Transitioned += (s, e) => { transitionedEventArgs.Add(e); }; var trigger1 = new Trigger("t1"); var trigger2 = new Trigger("t2"); var state1Mock = new Mock<State<StubStateModel>>("s1"); var state2Mock = new Mock<State<StubStateModel>>("s2"); var state3Mock = new Mock<State<StubStateModel>>("s3"); var state4Mock = new Mock<State<StubStateModel>>("s4"); var state1 = state1Mock.Object; var state2 = state2Mock.Object; var state3 = state3Mock.Object; var state4 = state4Mock.Object; var statetrans1 = new Transition<StubStateModel>(trigger1, state1, state2, m => 1 == 2); var statetrans2 = new Transition<StubStateModel>(trigger1, state1, state3, m => 1 == 3); var statetrans3 = new Transition<StubStateModel>(trigger2, state1, state3); var globaltrans1 = new Transition<StubStateModel>(trigger1, null, state2, m => 1 == 1); machine.AddGlobalTransition(globaltrans1); state1.AddTransition(statetrans1); state1.AddTransition(statetrans2); state1.AddTransition(statetrans3); model.CurrentState = state1; // so when trigger 1 is triggered on state model whose current state is state1, // it will fall through to the first maching transition with a passing guard, the global transition to state 2 // it will then transition to state2. // make sure that transition events are called for moving from state 1 to state 2 state1Mock.Setup(s => s.RaiseExiting(model, state2, trigger1)).Verifiable(); state2Mock.Setup(s => s.RaiseEntered(model, state1, trigger1)).Verifiable(); machine.Trigger(trigger1, model); // verify that no transition events were called that shouldn't have been state1Mock.Verify(s => s.RaiseEntered( It.IsAny<StubStateModel>(), It.IsAny<State<StubStateModel>>(), It.IsAny<Trigger>()), Times.Never()); state2Mock.Verify(s => s.RaiseExiting( It.IsAny<StubStateModel>(), It.IsAny<State<StubStateModel>>(), It.IsAny<Trigger>()), Times.Never()); Assert.Equal(1, transitioningEventArgs.Count); Assert.Equal(1, transitionedEventArgs.Count); Assert.Equal(state1, transitioningEventArgs[0].From); Assert.Equal(state2, transitioningEventArgs[0].To); Assert.Equal(trigger1, transitioningEventArgs[0].Trigger); Assert.Equal(model, transitioningEventArgs[0].Model); Assert.Equal(state1, transitionedEventArgs[0].From); Assert.Equal(state2, transitionedEventArgs[0].To); Assert.Equal(trigger1, transitionedEventArgs[0].Trigger); Assert.Equal(model, transitionedEventArgs[0].Model); Assert.Equal(state2, model.CurrentState); }
public void StateMachine_Trigger_TransitionsToSameState_ConfigRaiseOnSameStateTranFalse_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionBeforeTransitionToSameState = false }; var machine = new StateMachine<StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State<StubStateModel>("state1"); var state2 = new State<StubStateModel>("state2"); state1.AddTransition(trigger1, state1); model.CurrentState = state1; // set up scenario where state would transition from current to same state. // so no true transition would not occur // should not throw exception and that's good enough for us machine.Trigger(trigger1, model); }
public void StateMachine_Trigger_NoPassingTransitionOnTrigger_ConfigRaiseOnNoPassingTranTrue_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionOnTriggerMatchingNoPassingTransition = true }; var machine = new StateMachine<StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State<StubStateModel>("state1"); var state2 = new State<StubStateModel>("state2"); state1.AddTransition(trigger1, state2, m => 1 == 2); model.CurrentState = state1; // set up so that there's a matching transition, but the guard would fail when run Assert.Throws<InvalidTriggerException>(() => machine.Trigger(trigger1, model)); }
public void FluentStateMachineBuilder_TransitionsTo_Valid_CreatesNewTransition() { var machine = FluentStateMachine<StubStateModel>.Describe() .State("s1") .Initiates() .TransitionsTo("s2").On("t") .State("s2") .TransitionsTo("s1").On("t") .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; Assert.Equal("s1", model.CurrentState.ToString()); machine.Trigger("t", model); Assert.Equal("s2", model.CurrentState.ToString()); machine.Trigger("t", model); Assert.Equal("s1", model.CurrentState.ToString()); }
public void FluentStateMachineBuilder_When_WhileDefTrans_AddsGuardToTransition() { var machine = FluentStateMachine<StubStateModel>.Describe() .State("s1") .Initiates() .TransitionsTo("s2").On("t").When(m => false) .TransitionsTo("s3").On("t").When(m => true) .State("s2") .State("s3") .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; Assert.Equal("s1", model.CurrentState.ToString()); machine.Trigger("t", model); Assert.Equal("s3", model.CurrentState.ToString()); }
StateMachine_Trigger_ValidTriggerAndTrans_ChoosesFirstTranWthPassGuardNonGlobal_DiffAsCurrentState_Raised_Sets() { var model = new StubStateModel(); var machine = new StateMachine <StubStateModel>(); var transitioningEventArgs = new List <TransitionEventArgs <StubStateModel> >(); machine.Transitioning += (s, e) => { transitioningEventArgs.Add(e); }; var transitionedEventArgs = new List <TransitionEventArgs <StubStateModel> >(); machine.Transitioned += (s, e) => { transitionedEventArgs.Add(e); }; var trigger1 = new Trigger("t1"); var trigger2 = new Trigger("t2"); var state1Mock = new Mock <State <StubStateModel> >("s1"); var state2Mock = new Mock <State <StubStateModel> >("s2"); var state3Mock = new Mock <State <StubStateModel> >("s3"); var state4Mock = new Mock <State <StubStateModel> >("s4"); var state1 = state1Mock.Object; var state2 = state2Mock.Object; var state3 = state3Mock.Object; var state4 = state4Mock.Object; var statetrans1 = new Transition <StubStateModel>(trigger1, state1, state2, m => 1 == 2); var statetrans2 = new Transition <StubStateModel>(trigger1, state2, state3, m => 1 == 1); var statetrans3 = new Transition <StubStateModel>(trigger2, state1, state3); var globaltrans1 = new Transition <StubStateModel>(trigger1, null, state2, m => 1 == 1); machine.AddGlobalTransition(globaltrans1); state1.AddTransition(statetrans1); state1.AddTransition(statetrans2); state1.AddTransition(statetrans3); model.CurrentState = state1; // so when trigger 1 is triggered on state model whose current state is state1, // it will fall through to the first maching transition with a passing guard, the second state transition to state 2 // it will then transition to state2. // make sure that transition events are called for moving from state 1 to state 2 state1Mock.Setup(s => s.RaiseExiting(model, state2, trigger1)).Verifiable(); state2Mock.Setup(s => s.RaiseEntered(model, state1, trigger1)).Verifiable(); machine.Trigger(trigger1, model); // verify that no transition events were called that shouldn't have been state1Mock.Verify(s => s.RaiseEntered( It.IsAny <StubStateModel>(), It.IsAny <State <StubStateModel> >(), It.IsAny <Trigger>()), Times.Never()); state2Mock.Verify(s => s.RaiseExiting( It.IsAny <StubStateModel>(), It.IsAny <State <StubStateModel> >(), It.IsAny <Trigger>()), Times.Never()); Assert.Equal(1, transitioningEventArgs.Count); Assert.Equal(1, transitionedEventArgs.Count); Assert.Equal(state1, transitioningEventArgs[0].From); Assert.Equal(state2, transitioningEventArgs[0].To); Assert.Equal(trigger1, transitioningEventArgs[0].Trigger); Assert.Equal(model, transitioningEventArgs[0].Model); Assert.Equal(state1, transitionedEventArgs[0].From); Assert.Equal(state2, transitionedEventArgs[0].To); Assert.Equal(trigger1, transitionedEventArgs[0].Trigger); Assert.Equal(model, transitionedEventArgs[0].Model); Assert.Equal(state2, model.CurrentState); }
public void StateMachine_AvailableTriggers_ConcatsModelsTransWithGlobal_ReturnsDistinctTrigsByName() { var model = new StubStateModel(); var machine = new StateMachine<StubStateModel>(); var trigger1 = new Trigger("t1"); var trigger2 = new Trigger("t2"); var state1 = new State<StubStateModel>("s1"); var state2 = new State<StubStateModel>("s2"); var state3 = new State<StubStateModel>("s3"); var state4 = new State<StubStateModel>("s4"); var statetrans1 = new Transition<StubStateModel>(trigger1, state1, state2); var statetrans2 = new Transition<StubStateModel>(trigger1, state1, state3); var statetrans3 = new Transition<StubStateModel>(trigger2, state1, state3); var globaltrans1 = new Transition<StubStateModel>(trigger2, null, state1); machine.AddGlobalTransition(globaltrans1); state1.AddTransition(statetrans1); state1.AddTransition(statetrans2); state1.AddTransition(statetrans3); model.CurrentState = state1; var result = machine.AvailableTriggers(model); Assert.Equal(2, result.Count()); Assert.Equal(trigger1, result.ToList()[0]); Assert.Equal(trigger2, result.ToList()[1]); }
public void IStateModelExtensions_Trigger_NullTrigger_ThrowsNullEx() { var mockModel = new StubStateModel(); var mockMachine = new Mock<IStateMachine<StubStateModel>>(); Assert.Throws<ArgumentNullException>(() => IStateModelExtensions.Trigger(mockModel, (Trigger)null, mockMachine.Object)); }
public void IStateModelExtensions_Trigger_NullMachine_StringTrigger_ThrowsNullEx() { var mockModel = new StubStateModel(); Assert.Throws<ArgumentNullException>(() => IStateModelExtensions.Trigger(mockModel, "triggerName", (IStateMachine<StubStateModel>)null)); }
public void IStateModelExtensions_Trigger_NullMachine_ObjTrigger_ThrowsNullEx() { var mockModel = new StubStateModel(); var trigger = new Trigger("trigger"); Assert.Throws<ArgumentNullException>(() => IStateModelExtensions.Trigger(mockModel, trigger, (IStateMachine<StubStateModel>)null)); }
public void FluentStateMachineBuilder_DefiningCallbacksOnAll_AllCallbacksCalledInOrder() { var loggedEvents = new List<string>(); Action<string, TransitionEventArgs<StubStateModel>> logEvent = (message, e) => { loggedEvents.Add(String.Format("{0} from {1} to {2} on {3}", message, e.From, e.To, e.Trigger)); }; var machine = FluentStateMachine<StubStateModel>.Describe() .State("s1") .BeforeEntry(e => logEvent("beforeEntry", e)) .AfterEntry(e => logEvent("afterEntry", e)) .BeforeExit(e => logEvent("beforeExit", e)) .AfterExit(e => logEvent("afterExit", e)) .TransitionsTo("s2").On("t") .Initiates() .State("s2") .BeforeEntry(e => logEvent("beforeEntry", e)) .AfterEntry(e => logEvent("afterEntry", e)) .BeforeExit(e => logEvent("beforeExit", e)) .AfterExit(e => logEvent("afterExit", e)) .TransitionsTo("s1").On("t") .BeforeTransition(e => logEvent("beforeTransition", e)) .AfterTransition(e => logEvent("afterTransition", e)) .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; machine.Trigger("t", model); Assert.Equal("s2", model.CurrentState.ToString()); Assert.Equal(6, loggedEvents.Count()); Assert.Equal("beforeTransition from s1 to s2 on t", loggedEvents[0]); Assert.Equal("beforeExit from s1 to s2 on t", loggedEvents[1]); Assert.Equal("beforeEntry from s1 to s2 on t", loggedEvents[2]); Assert.Equal("afterExit from s1 to s2 on t", loggedEvents[3]); Assert.Equal("afterEntry from s1 to s2 on t", loggedEvents[4]); Assert.Equal("afterTransition from s1 to s2 on t", loggedEvents[5]); }
public void StateMachine_Trigger_NoStateOrGlobalTransOnTrigger_ConfigRaiseOnNoTransTrue_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionOnTriggerMatchingNoTransition = true }; var machine = new StateMachine<StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var trigger2 = new Trigger("trigger2"); var state1 = new State<StubStateModel>("state1"); var state2 = new State<StubStateModel>("state2"); state1.AddTransition(trigger1, state2); model.CurrentState = state1; // set up so that current state of state 1 doesn't' define a trans for "trigger2", only "trigger1" Assert.Throws<InvalidTriggerException>(() => machine.Trigger(trigger2, model)); }
public void StateMachine_Trigger_ModelStateNotState_ThrowsInvalidStateModel() { var machine = new StateMachine<StubStateModel>(); var model = new StubStateModel(); var trigger = new Trigger("trigger"); Assert.Throws<InvalidStateModelException>(() => machine.Trigger(trigger, model)); }
public void StateMachine_Trigger_NoStateOrGlobalTransOnTrigger_ConfigRaiseOnNoTransFalse_NotThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionOnTriggerMatchingNoTransition = false }; var machine = new StateMachine<StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var trigger2 = new Trigger("trigger2"); var state1 = new State<StubStateModel>("state1"); var state2 = new State<StubStateModel>("state2"); state1.AddTransition(trigger1, state2); model.CurrentState = state1; // no exception shoudl happen, and that's good enough for us. machine.Trigger(trigger2, model); }
public void IStateModelExtensions_Trigger_ValidParms_ObjTrigger_CallsTriggerOnMachine() { var mockModel = new StubStateModel(); var trigger = new Trigger("trigger"); var mockMachine = new Mock<IStateMachine<StubStateModel>>(); mockMachine.Setup(m => m.Trigger(trigger, mockModel)).Verifiable(); IStateModelExtensions.Trigger(mockModel, trigger, mockMachine.Object); mockMachine.VerifyAll(); }
public void StateMachine_Trigger_TransitionsToSameState_ConfigRaiseOnSameStateTranTrue_ThrowsInvalidTrigger() { var config = new StateMachineConfiguration { RaiseExceptionBeforeTransitionToSameState = true }; var machine = new StateMachine<StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State<StubStateModel>("state1"); var state2 = new State<StubStateModel>("state2"); state1.AddTransition(trigger1, state1); model.CurrentState = state1; // set up scenario where state would transition from current to same state. // so no true transition would not occur Assert.Throws<InvalidTriggerException>(() => machine.Trigger(trigger1, model)); }
public void StateMachine_AvailableTriggers_ModelStateNotState_ThrowInvalidStateModel() { var model = new StubStateModel(); var machine = new StateMachine<StubStateModel>(); Assert.Throws<InvalidStateModelException>(() => machine.AvailableTriggers(model)); }
public void IStateModelExtensions_Trigger_ValidParms_StringTrigger_CallsTriggerOnMachine() { var mockModel = new StubStateModel(); var mockMachine = new Mock<IStateMachine<StubStateModel>>(); mockMachine.Setup(m => m.Trigger(It.Is<Trigger>(t => t.Name == "triggerName"), mockModel)).Verifiable(); IStateModelExtensions.Trigger(mockModel, "triggerName", mockMachine.Object); mockMachine.VerifyAll(); }
public void StateMachine_Trigger_TransitionFromCurrentToSame_ConfiggedNotToRaiseExcep_DoesNotRaiseTransitionChangeEvents() { var config = new StateMachineConfiguration { RaiseExceptionBeforeTransitionToSameState = false }; var machine = new StateMachine<StubStateModel>(config); var model = new StubStateModel(); var trigger1 = new Trigger("trigger1"); var state1 = new State<StubStateModel>("state1"); TransitionEventArgs<StubStateModel> transitioningArgs = null; state1.Entered += (s, e) => { transitioningArgs = e; }; TransitionEventArgs<StubStateModel> transitionedArgs = null; state1.Exiting += (s, e) => { transitionedArgs = e; }; state1.AddTransition(trigger1, state1); model.CurrentState = state1; // set up scenario where state would transition from current to same state. // so no true transition would not occur // should not throw exception and that's good enough for us machine.Trigger(trigger1, model); // verify that no transition events occurred Assert.Null(transitioningArgs); Assert.Null(transitionedArgs); }
public void FluentStateMachineBuilder_State_ValidParms_CreatesNewState() { var machine = FluentStateMachine<StubStateModel>.Describe() .State("s1") .Initiates() .Compile(); var model = new StubStateModel(); model.CurrentState = machine.InitialState; Assert.Equal("s1", model.CurrentState.ToString()); }
public void TransitionEventArgs_ValidParms_VerifyAssigns() { var model = new StubStateModel(); var from = new State<StubStateModel>("from"); var to = new State<StubStateModel>("to"); var trigger = new Trigger("trigger"); var args = new TransitionEventArgs<StubStateModel>(model, from, to, trigger); Assert.Same(from, args.From); Assert.Same(to, args.To); Assert.Same(model, args.Model); Assert.Same(trigger, args.Trigger); }
public void State_RaiseExiting_ValidParms_Handler_TriggersHandlerPassesParmsAndSelf() { var model = new StubStateModel(); var fromState = new State<StubStateModel>("from"); var toState = new State<StubStateModel>("to"); var trigger = new Trigger("trigger"); TransitionEventArgs<StubStateModel> args = null; fromState.Exiting += (s, e) => { args = e; }; fromState.RaiseExiting(model, toState, trigger); Assert.Equal(model, args.Model); Assert.Equal(fromState, args.From); Assert.Equal(toState, args.To); Assert.Equal(trigger, args.Trigger); }