Ejemplo n.º 1
0
        public void GuardWithASingleArgument()
        {
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.B)
            .If <int>(SingleIntArgumentGuardReturningFalse).Goto(States.C)
            .If(() => false).Goto(States.D)
            .If(() => false).Goto(States.E)
            .If <int>(SingleIntArgumentGuardReturningTrue).Goto(States.B);
            var stateDefinitions = stateDefinitionBuilder
                                   .Build();
            var stateContainer = new StateContainer <States, Events>();

            var testee = new StateMachineBuilder <States, Events>()
                         .WithStateContainer(stateContainer)
                         .Build();

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.B, 3, stateContainer, stateDefinitions);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.B));
        }
Ejemplo n.º 2
0
        public void ExecuteTransitionBetweenStatesOnDifferentLevelsDownwards()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.B2);

            this.ClearRecords();

            testee.Fire(Events.C1B, stateContainer, stateContainer, this.stateDefinitions);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.C1B));

            this.CheckRecord <ExitRecord>(States.B2);
            this.CheckRecord <ExitRecord>(States.B);
            this.CheckRecord <EntryRecord>(States.C);
            this.CheckRecord <EntryRecord>(States.C1);
            this.CheckRecord <EntryRecord>(States.C1B);
            this.CheckNoRemainingRecords();
        }
Ejemplo n.º 3
0
 public override void Loaded(
     IStateMachineInformation <State, Event> stateMachineInformation,
     Initializable <State> loadedCurrentState,
     IDictionary <State, State> loadedHistoryStates)
 {
     this.LoadedCurrentState.Add(loadedCurrentState.Value);
 }
Ejemplo n.º 4
0
        public void MissingTransition()
        {
            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.B)
            .Goto(States.B);
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

            var testee = new StateMachineBuilder <States, Events>()
                         .WithStateContainer(stateContainer)
                         .Build();

            var declined = false;

            testee.TransitionDeclined += (sender, e) => { declined = true; };

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.C, stateContainer, stateContainer, stateDefinitions);

            declined.Should().BeTrue("Declined event was not fired");
            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.A));
        }
Ejemplo n.º 5
0
        public void InternalTransition()
        {
            var executed = false;

            var stateDefinitionBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionBuilder
            .In(States.A)
            .On(Events.A)
            .Execute(() => executed = true);
            var stateDefinitions = stateDefinitionBuilder.Build();
            var stateContainer   = new StateContainer <States, Events>();

            var testee = new StateMachineBuilder <States, Events>()
                         .WithStateContainer(stateContainer)
                         .Build();

            testee.EnterInitialState(stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.A, stateContainer, stateContainer, stateDefinitions);

            executed.Should().BeTrue("internal transition was not executed.");
            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.A));
        }
Ejemplo n.º 6
0
        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 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));
        }
Ejemplo n.º 8
0
 private void InsertEntry(Initializable entry)
 {
     if ((entry != null) && !toInitialize.ContainsKey(entry))
     {
         toInitialize.Add(entry, null);
     }
 }
Ejemplo n.º 9
0
        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();
        }
Ejemplo n.º 10
0
        public void ExecuteTransitionWithHistoryTypeDeep()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.D1B);
            testee.Fire(Events.A, stateContainer, stateContainer, this.stateDefinitions);

            this.ClearRecords();

            testee.Fire(Events.D, stateContainer, stateContainer, this.stateDefinitions);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.D1B));

            this.CheckRecord <ExitRecord>(States.A);
            this.CheckRecord <EntryRecord>(States.D);
            this.CheckRecord <EntryRecord>(States.D1);
            this.CheckRecord <EntryRecord>(States.D1B);
            this.CheckNoRemainingRecords();
        }
Ejemplo n.º 11
0
        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();
            });
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="StateMachine{TState,TEvent}"/> class.
        /// </summary>
        /// <param name="name">The name of this state machine used in log messages.</param>
        /// <param name="factory">The factory used to create internal instances.</param>
        public StateMachine(string name, IFactory <TState, TEvent> factory)
        {
            this.name       = name;
            this.factory    = factory ?? new StandardFactory <TState, TEvent>(this, this);
            this.states     = new StateDictionary <TState, TEvent>(this.factory);
            this.extensions = new List <IExtension <TState, TEvent> >();

            this.initialStateId = new Initializable <TState>();
        }
Ejemplo n.º 13
0
        public async Task <bool> Load(IAsyncStateMachineLoader <TState> stateMachineLoader)
        {
            Guard.AgainstNullArgument(nameof(stateMachineLoader), stateMachineLoader);
            this.CheckThatStateMachineIsNotAlreadyInitialized();

            Initializable <TState> loadedCurrentState = await stateMachineLoader.LoadCurrentState().ConfigureAwait(false);

            IDictionary <TState, TState> historyStates = await stateMachineLoader.LoadHistoryStates().ConfigureAwait(false);

            var initialized = SetCurrentState();

            LoadHistoryStates();
            NotifyExtensions();

            return(initialized);

            bool SetCurrentState()
            {
                if (loadedCurrentState.IsInitialized)
                {
                    this.currentState = this.states[loadedCurrentState.Value];
                    return(true);
                }

                this.currentState = null;
                return(false);
            }

            void LoadHistoryStates()
            {
                foreach (KeyValuePair <TState, TState> historyState in historyStates)
                {
                    IState <TState, TEvent> superState      = this.states[historyState.Key];
                    IState <TState, TEvent> lastActiveState = this.states[historyState.Value];

                    if (!superState.SubStates.Contains(lastActiveState))
                    {
                        throw new InvalidOperationException(ExceptionMessages.CannotSetALastActiveStateThatIsNotASubState);
                    }

                    superState.LastActiveState = lastActiveState;
                }
            }

            void NotifyExtensions()
            {
                this.extensions.ForEach(
                    extension => extension.Loaded(
                        this,
                        loadedCurrentState,
                        historyStates));
            }
        }
Ejemplo n.º 14
0
        public void IsInitialized()
        {
            Initializable <SomeClass>
            .Initialized(new SomeClass())
            .IsInitialized
            .Should()
            .BeTrue();

            Initializable <SomeClass>
            .UnInitialized()
            .IsInitialized
            .Should()
            .BeFalse();
        }
Ejemplo n.º 15
0
        public void Map()
        {
            Initializable <SomeClass>
            .Initialized(new SomeClass { SomeValue = "A" })
            .Map(x => x.SomeValue)
            .Should()
            .BeEquivalentTo(Initializable <string> .Initialized("A"));

            Initializable <SomeClass>
            .UnInitialized()
            .Map(x => x.SomeValue)
            .Should()
            .BeEquivalentTo(Initializable <string> .UnInitialized());
        }
Ejemplo n.º 16
0
        public void ExtractOr()
        {
            Initializable <string>
            .Initialized("A")
            .ExtractOr("B")
            .Should()
            .Be("A");

            Initializable <string>
            .UnInitialized()
            .ExtractOr("B")
            .Should()
            .Be("B");
        }
Ejemplo n.º 17
0
        private static async Task SwitchStateTo(
            IStateDefinition <TState, TEvent> newState,
            StateContainer <TState, TEvent> stateContainer,
            IStateMachineInformation <TState, TEvent> stateMachineInformation)
        {
            var oldState = stateContainer.CurrentState.ExtractOr(null);

            stateContainer.CurrentState = Initializable <IStateDefinition <TState, TEvent> > .Initialized(newState);

            await stateContainer
            .ForEach(extension =>
                     extension.SwitchedState(stateMachineInformation, oldState, newState))
            .ConfigureAwait(false);
        }
Ejemplo n.º 18
0
        public void ExtractOrThrow()
        {
            Initializable <string>
            .Initialized("A")
            .ExtractOrThrow()
            .Should()
            .Be("A");

            Initializable <string>
            .UnInitialized()
            .Invoking(x => x.ExtractOrThrow())
            .Should()
            .Throw <InvalidOperationException>()
            .WithMessage(ExceptionMessages.ValueNotInitialized);
        }
        /// <summary>
        /// Generates a report of the state machine.
        /// </summary>
        /// <param name="name">The name of the state machine.</param>
        /// <param name="states">The states.</param>
        /// <param name="initialStateId">The initial state id.</param>
        public void Report(string name, IEnumerable <IState <TState, TEvent> > states, Initializable <TState> initialStateId)
        {
            this.edgeId = 0;

            this.initialStateId = initialStateId;
            Ensure.ArgumentNotNull(states, "states");

            XElement graph = CreateGraph();

            this.AddNodes(graph, states);
            this.AddEdges(graph, states);

            XDocument doc = CreateXmlDocument(graph);

            doc.Save(this.outputStream);
        }
Ejemplo n.º 20
0
        public void InternalTransition()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.A);
            this.ClearRecords();

            testee.Fire(Events.A, stateContainer, stateContainer, this.stateDefinitions);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.A));
        }
Ejemplo n.º 21
0
        private static async Task SwitchStateTo(
            IStateDefinition <TState, TEvent> newState,
            StateContainer <TState, TEvent> stateContainer,
            IStateDefinitionDictionary <TState, TEvent> stateDefinitions)
        {
            var oldState = stateContainer
                           .CurrentStateId
                           .Map(x => stateDefinitions[x])
                           .ExtractOr(null);

            stateContainer.CurrentStateId = Initializable <TState> .Initialized(newState.Id);

            await stateContainer
            .ForEach(extension =>
                     extension.SwitchedState(oldState, newState))
            .ConfigureAwait(false);
        }
Ejemplo n.º 22
0
        public void InitializeToTopLevelState()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.A);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.A));

            this.CheckRecord <EntryRecord>(States.A);
            this.CheckNoRemainingRecords();
        }
Ejemplo n.º 23
0
    private void FlattenNode(List <Initializable> initOrder, Initializable node)
    {
        if (!initOrder.Contains(node))
        {
            var dependencies = toInitialize[node];
            var index        = initOrder.Count;
            initOrder.Add(node);

            foreach (var dependency in dependencies)
            {
                FlattenNode(initOrder, dependency);
            }

            initOrder.Add(node);
            initOrder.RemoveAt(index);
        }
    }
Ejemplo n.º 24
0
    public void Register(Initializable target, params Initializable[] dependencies)
    {
        var first = toInitialize.Count == 0;

        InsertEntry(target);
        toInitialize[target] = dependencies;

        foreach (var dependency in dependencies)
        {
            InsertEntry(dependency);
        }

        if (first)
        {
            state.RunCoroutine(InitializeAll());
        }
    }
Ejemplo n.º 25
0
        public void ExceptionThrowingGuard()
        {
            var       eventArguments        = new object[] { 1, 2, "test" };
            var       exception             = new Exception();
            States?   recordedStateId       = null;
            Events?   recordedEventId       = null;
            object    recordedEventArgument = null;
            Exception recordedException     = null;

            var stateDefinitionsBuilder = new StateDefinitionsBuilder <States, Events>();

            stateDefinitionsBuilder.In(States.A)
            .On(Events.B)
            .If(() => throw exception)
            .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) =>
            {
                recordedStateId       = eventArgs.StateId;
                recordedEventId       = eventArgs.EventId;
                recordedEventArgument = eventArgs.EventArgument;
                recordedException     = eventArgs.Exception;
            };

            testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.B, eventArguments, stateContainer, stateContainer, stateDefinitions);

            recordedStateId.Should().Be(States.A);
            recordedEventId.Should().Be(Events.B);
            recordedEventArgument.Should().Be(eventArguments);
            recordedException.Should().Be(exception);
            stateContainer.CurrentStateId.Should().BeEquivalentTo(Initializable <States> .Initialized(States.A));
            transitionDeclined.Should().BeTrue("transition was not declined.");
        }
Ejemplo n.º 26
0
 // Start is called before the first frame update
 public void Init()
 {
     for (int i = 0; i < initializable.Length; i++)
     {
         if (!initializable[i])
         {
             Debug.LogError("initializable[" + i + "]Not found");
             continue;
         }
         Initializable init = initializable[i].GetComponent <Initializable>();
         if (init == null)
         {
             Debug.LogError("initializable[" + i + "] Init Script Not found");
             continue;
         }
         init.Init();
     }
 }
Ejemplo n.º 27
0
        /// <summary>
        /// Generates a report of the state machine.
        /// </summary>
        /// <param name="name">The name of the state machine.</param>
        /// <param name="states">The states.</param>
        /// <param name="initialState">The initial state id.</param>
        public void Report(string name, IEnumerable<IState<TState, TEvent>> states, Initializable<TState> initialState)
        {
            var statesList = states.ToList();

            this.edgeId = 0;

            this.initialStateId = initialState;
            Ensure.ArgumentNotNull(statesList, "states");

            XElement graph = CreateGraph();

            this.AddNodes(graph, statesList);
            this.AddEdges(graph, statesList);
            
            XDocument doc = CreateXmlDocument(graph);

            doc.Save(this.textWriter);
        }
Ejemplo n.º 28
0
        public void SetsHistoryStatesOnLoadingFromPersistedState()
        {
            var exitedD2 = false;

            var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <States, Events>();

            stateMachineDefinitionBuilder
            .DefineHierarchyOn(States.D)
            .WithHistoryType(HistoryType.Deep)
            .WithInitialSubState(States.D1)
            .WithSubState(States.D2);
            stateMachineDefinitionBuilder
            .In(States.A)
            .On(Events.D).Goto(States.D)
            .On(Events.A);
            stateMachineDefinitionBuilder
            .In(States.D2)
            .ExecuteOnExit(() => exitedD2 = true)
            .On(Events.A).Goto(States.A);
            var testee = stateMachineDefinitionBuilder
                         .WithInitialState(States.A)
                         .Build()
                         .CreatePassiveStateMachine();

            var loader = A.Fake <IStateMachineLoader <States, Events> >();

            A.CallTo(() => loader.LoadHistoryStates())
            .Returns(new Dictionary <States, States>
            {
                { States.D, States.D2 }
            });
            A.CallTo(() => loader.LoadCurrentState())
            .Returns(Initializable <States> .UnInitialized());

            testee.Load(loader);
            testee.Start();
            testee.Fire(Events.D); // should go to loaded last active state D2, not initial state D1
            exitedD2 = false;
            testee.Fire(Events.A);

            testee.Stop();

            exitedD2.Should().BeTrue();
        }
Ejemplo n.º 29
0
        public void EntryActionWhenThrowingExceptionThenNotificationAndStateIsEntered()
        {
            var       eventArguments        = new object[] { 1, 2, "test" };
            var       exception             = new Exception();
            States?   recordedStateId       = null;
            Events?   recordedEventId       = null;
            object    recordedEventArgument = null;
            Exception recordedException     = null;

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

            testee.TransitionExceptionThrown += (sender, eventArgs) =>
            {
                recordedStateId       = eventArgs.StateId;
                recordedEventId       = eventArgs.EventId;
                recordedEventArgument = eventArgs.EventArgument;
                recordedException     = eventArgs.Exception;
            };

            testee.EnterInitialState(stateContainer, stateContainer, stateDefinitions, States.A);

            testee.Fire(Events.B, eventArguments, stateContainer, stateContainer, stateDefinitions);

            recordedStateId.Should().Be(States.A);
            recordedEventId.Should().Be(Events.B);
            recordedEventArgument.Should().Be(eventArguments);
            recordedException.Should().Be(exception);
            stateContainer.CurrentStateId.Should().BeEquivalentTo(Initializable <States> .Initialized(States.B));
        }
Ejemplo n.º 30
0
        public void InitializeStateWithSubStates()
        {
            var stateContainer = new StateContainer <States, Events>();
            var testee         = new StateMachineBuilder <States, Events>()
                                 .WithStateContainer(stateContainer)
                                 .Build();

            stateContainer.SetLastActiveStateFor(States.D, this.stateDefinitions[States.D1]);
            stateContainer.SetLastActiveStateFor(States.D1, this.stateDefinitions[States.D1A]);

            testee.EnterInitialState(stateContainer, stateContainer, this.stateDefinitions, States.D);

            stateContainer
            .CurrentStateId
            .Should()
            .BeEquivalentTo(Initializable <States> .Initialized(States.D1A));

            this.CheckRecord <EntryRecord>(States.D);
            this.CheckRecord <EntryRecord>(States.D1);
            this.CheckRecord <EntryRecord>(States.D1A);
            this.CheckNoRemainingRecords();
        }
 public X1(Initializable initializable)
 {
     this.initializable = initializable;
 }