public async Task StaysInCurrentState_WhenAGuardThrowsAnException() { var eventArguments = new object[] { 1, 2, "test" }; var exception = new Exception(); bool ThrowingGuard() => throw exception; var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionsBuilder .In(States.A) .On(Events.B) .If(ThrowingGuard).Goto(States.B); var stateDefinitions = stateDefinitionsBuilder.Build(); var stateContainer = new StateContainer <States, Events>(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); testee.TransitionExceptionThrown += (sender, eventArgs) => { }; await testee.EnterInitialState(stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); await testee.Fire(Events.B, eventArguments, stateContainer, stateDefinitions) .ConfigureAwait(false); stateContainer .CurrentStateId .Should() .BeEquivalentTo(Initializable <States> .Initialized(States.A)); }
public async Task DeclinesTransition_WhenAGuardThrowsAnException() { var eventArguments = new object[] { 1, 2, "test" }; var exception = new Exception(); bool ThrowingGuard() => throw exception; var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionsBuilder .In(States.A) .On(Events.B) .If(ThrowingGuard).Goto(States.B); var stateDefinitions = stateDefinitionsBuilder.Build(); var stateContainer = new StateContainer <States, Events>(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); var transitionDeclined = false; testee.TransitionDeclined += (sender, e) => transitionDeclined = true; testee.TransitionExceptionThrown += (sender, eventArgs) => { }; await testee.EnterInitialState(stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); await testee.Fire(Events.B, eventArguments, stateContainer, stateDefinitions) .ConfigureAwait(false); transitionDeclined .Should() .BeTrue("transition was not declined."); }
public async Task ParametrizedExitAction() { const int Parameter = 3; var receivedValue = 0; var stateContainer = new StateContainer <States, Events>(); var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionBuilder .In(States.A) .ExecuteOnExitParametrized(value => receivedValue = value, Parameter) .On(Events.B).Goto(States.B); var stateDefinitions = stateDefinitionBuilder.Build(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); await testee.EnterInitialState(stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); await testee.Fire(Events.B, null, stateContainer, stateDefinitions) .ConfigureAwait(false); receivedValue.Should().Be(Parameter); }
public async Task ParameterizedEntryAction() { const int Parameter = 3; var receivedValue = 0; var stateContainer = new StateContainer <States, Events>(); var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionBuilder .In(States.A) .ExecuteOnEntryParametrized(parameter => receivedValue = parameter, Parameter); var stateDefinitions = stateDefinitionBuilder.Build(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); await testee.EnterInitialState(stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); receivedValue .Should() .Be(Parameter); }
public async Task ExitActions() { var exit1 = false; var exit2 = false; var stateContainer = new StateContainer <States, Events>(); var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionBuilder .In(States.A) .ExecuteOnExit(() => exit1 = true) .ExecuteOnExit(() => exit2 = true) .On(Events.B).Goto(States.B); var stateDefinitions = stateDefinitionBuilder.Build(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); await testee.EnterInitialState(stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); await testee.Fire(Events.B, null, stateContainer, stateDefinitions) .ConfigureAwait(false); exit1.Should().BeTrue("exit action was not executed."); exit2.Should().BeTrue("exit action was not executed."); }
public async Task EventArgumentIsPassedToTheGuard_AsyncUsage() { const string ExpectedEventArgument = "test"; string actualEventArgument = null; var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionsBuilder .In(States.A) .On(Events.A) .If((string argument) => { actualEventArgument = argument; return(Task.FromResult(true)); }) .Goto(States.B); var stateDefinitions = stateDefinitionsBuilder.Build(); var stateContainer = new StateContainer <States, Events>(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); await testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); await testee.Fire(Events.A, ExpectedEventArgument, stateContainer, stateContainer, stateDefinitions) .ConfigureAwait(false); actualEventArgument .Should() .Be(ExpectedEventArgument); }
public async Task GuardWithASingleArgument() { var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionsBuilder .In(States.A) .On(Events.B) .If((Func <int, bool>)SingleIntArgumentGuardReturningFalse).Goto(States.C) .If(() => false).Goto(States.D) .If(() => false).Goto(States.E) .If((Func <int, bool>)SingleIntArgumentGuardReturningTrue).Goto(States.B); var stateDefinitions = stateDefinitionsBuilder.Build(); var stateContainer = new StateContainer <States, Events>(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); await testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); await testee.Fire(Events.B, 3, stateContainer, stateContainer, stateDefinitions) .ConfigureAwait(false); stateContainer .CurrentStateId .Should() .BeEquivalentTo(Initializable <States> .Initialized(States.B)); }
public async Task GuardWithoutArguments() { var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionsBuilder .In(States.A) .On(Events.B) .If(() => false).Goto(States.C) .If(() => true).Goto(States.B); var stateDefinitions = stateDefinitionsBuilder.Build(); var stateContainer = new StateContainer <States, Events>(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); await testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); await testee.Fire(Events.B, Missing.Value, stateContainer, stateContainer, stateDefinitions) .ConfigureAwait(false); stateContainer .CurrentStateId .Should() .BeEquivalentTo(Initializable <States> .Initialized(States.B)); }
public void ThrowsException_WhenInitialStateIsSuperStateItselfInAnHierarchy() { var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>(); Action action = () => stateDefinitionsBuilder .DefineHierarchyOn(States.B) .WithHistoryType(HistoryType.None) .WithInitialSubState(States.B) .WithSubState(States.B1) .WithSubState(States.B2); action.Should().Throw <ArgumentException>(); }
public void ThrowsException_WhenFiringAnEventOntoAnNotInitializedStateMachine() { var stateDefinitions = new StateDefinitionsBuilder <States, Events>().Build(); var stateContainer = new StateContainer <States, Events>(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); Func <Task> action = async() => await testee.Fire(Events.B, Missing.Value, stateContainer, stateDefinitions) .ConfigureAwait(false); action.Should().Throw <InvalidOperationException>(); }
public void ThrowsException_WhenTransitionWithoutGuardIsNotDefinedLast() { var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionsBuilder .In(States.A) .On(Events.B).Goto(States.B); Action action = () => stateDefinitionsBuilder .In(States.A) .On(Events.B).If(() => false).Execute(() => { }); action .Should() .Throw <InvalidOperationException>() .WithMessage(ExceptionMessages.TransitionWithoutGuardHasToBeLast); }
public void ThrowsException_WhenMultipleTransitionsWithoutGuardsAreDefined_ExecuteCase() { var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionsBuilder .In(States.A) .On(Events.B).Goto(States.B); Action action = () => stateDefinitionsBuilder .In(States.A) .On(Events.B).Execute(() => { }); action .Should() .Throw <InvalidOperationException>() .WithMessage(ExceptionMessages.OnlyOneTransitionMayHaveNoGuard); }
public void ThrowsException_WhenDefiningNonTreeHierarchy() { var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionBuilder .DefineHierarchyOn(States.A) .WithHistoryType(HistoryType.None) .WithInitialSubState(States.B); Action action = () => { stateDefinitionBuilder .DefineHierarchyOn(States.C) .WithHistoryType(HistoryType.None) .WithInitialSubState(States.B); }; action.Should().Throw <InvalidOperationException>(); }
public async Task CapturesException_WhenEntryActionThrowsAnException() { var eventArguments = new object[] { 1, 2, "test" }; var exception = new Exception(); var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionsBuilder .In(States.A) .On(Events.B).Goto(States.B); stateDefinitionsBuilder .In(States.B) .ExecuteOnEntry(() => throw exception); var stateDefinitions = stateDefinitionsBuilder.Build(); var stateContainer = new StateContainer <States, Events>(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); CapturedException capturedException = null; testee.TransitionExceptionThrown += (sender, eventArgs) => { capturedException = new CapturedException( eventArgs.StateId, eventArgs.EventId, eventArgs.EventArgument, eventArgs.Exception); }; await testee.EnterInitialState(stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); await testee.Fire(Events.B, eventArguments, stateContainer, stateDefinitions) .ConfigureAwait(false); capturedException .Should() .Be(new CapturedException(States.A, Events.B, eventArguments, exception)); }
public async Task EntryAction() { var entered = false; var stateContainer = new StateContainer <States, Events>(); var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>(); stateDefinitionBuilder .In(States.A) .ExecuteOnEntry(() => entered = true); var stateDefinitions = stateDefinitionBuilder.Build(); var testee = new StateMachineBuilder <States, Events>() .WithStateContainer(stateContainer) .Build(); await testee.EnterInitialState(stateContainer, stateDefinitions, States.A) .ConfigureAwait(false); entered .Should() .BeTrue("entry action was not executed."); }