Ejemplo n.º 1
0
        private void SendTriggerEvent_NoTransition_ExecutesExpected(bool useDoActions)
#endif
        {
            // Arrange
            string[] expectedExec;
            if (useDoActions)
            {
                expectedExec = new string[] { "EnS1", "DoS1",
                                              "CHK", "DoS1", "CHK",
                                              "CHK", "DoS1", "CHK",
                                              "CHK", "DoS1", "CHK",
                                              "CHK", "DoS1", "CHK",
                                              "CHK", "DoS1", "CHK" };
            }
            else
            {
                expectedExec = new string[] { "EnS1",
                                              "CHK",
                                              "CHK",
                                              "CHK",
                                              "CHK",
                                              "CHK" };
            }

            ActionRecorder recorder = new ActionRecorder();

            StateMachineTemplate t = new StateMachineTemplate(useDoActions ? StateMachineOptions.UseDoActions : StateMachineOptions.None);

            t.Region("S1", false);
            t.State("S1", recorder.CreateAction("EnS1"), recorder.CreateAction("ExS1"), useDoActions ? recorder.CreateDoAction("DoS1") : NullDo);
            t.EndState();
            t.EndRegion();
            StateMachine stateMachine = t.CreateStateMachine();

            stateMachine.TraceDispatchTriggerEvent = recorder.CreateTraceMethod("CHK");
            stateMachine.Startup();

            // Act
            for (int i = 0; i < 5; i++)
            {
                stateMachine.SendTriggerEvent(null);
            }

            // Assert
            Assert.That(recorder.RecordedActions, Is.EqualTo(expectedExec), "Unexpected action invocations");
        }
Ejemplo n.º 2
0
        public void SendTriggerEvent_WithOneTransitionsAndDoChangesGuard_ExecutesExpected()
        {
            // Arrange
            string[] expectedExec;
            expectedExec = new string[] { "EnS1", "DoS1",
                                          "CHK", "DoS1", "CHK", "ExS1", "EnS2", "DoS2", "CHK", "ExS2", "EnS1", "DoS1", "CHK",
                                          "CHK", "DoS1", "CHK", "ExS1", "EnS2", "DoS2", "CHK", "ExS2", "EnS1", "DoS1", "CHK",
                                          "CHK", "DoS1", "CHK", "ExS1", "EnS2", "DoS2", "CHK", "ExS2", "EnS1", "DoS1", "CHK",
                                          "CHK", "DoS1", "CHK", "ExS1", "EnS2", "DoS2", "CHK", "ExS2", "EnS1", "DoS1", "CHK",
                                          "CHK", "DoS1", "CHK", "ExS1", "EnS2", "DoS2", "CHK", "ExS2", "EnS1", "DoS1", "CHK", };

            ActionRecorder recorder         = new ActionRecorder();
            int            transition1State = 0;

            StateMachineTemplate t = new StateMachineTemplate(StateMachineOptions.UseDoActions);

            t.Region("S1", false);
            t.State("S1", recorder.CreateAction("EnS1"), recorder.CreateAction("ExS1"), (stm) => { recorder.Add("DoS1"); transition1State += 1; });
            t.Transition("T1", "S1", "S2", null, (stm, ev, args) => transition1State == 1, null);
            t.EndState();
            t.State("S2", recorder.CreateAction("EnS2"), recorder.CreateAction("ExS2"), recorder.CreateDoAction("DoS2"));
            t.Transition("T2", "S2", "S1", null, (stm, ev, args) => true, null);
            t.EndState();
            t.EndRegion();
            StateMachine stateMachine = t.CreateStateMachine();

            stateMachine.TraceDispatchTriggerEvent = recorder.CreateTraceMethod("CHK");
            stateMachine.Startup();

            // Act
            for (int i = 0; i < 5; i++)
            {
                transition1State = 0;
                stateMachine.SendTriggerEvent(null);
            }

            // Assert
            Assert.That(recorder.RecordedActions, Is.EqualTo(expectedExec), "Unexpected action invocations");
        }
Ejemplo n.º 3
0
        private void SaveStateResume_WithHistory_UsesHistoryStateAfterResume(bool executeEntryActions)
#endif
        {
            ActionRecorder recorder = new ActionRecorder();

            TemplateFactory createTemplate = delegate()
            {
                StateMachineTemplate t = new StateMachineTemplate(StateMachineOptions.UseDoActions);
                //## Begin StateMachineTemplateSaveStateResumeWithHistory
                // Generated from <file:S:\StaMa_State_Machine_Controller_Library\StaMaShapesMaster.vst> page "UT_SaveStateResumeTests"
                // at 07-25-2015 16:55:36 using StaMaShapes Version 2300
                t.Region("StateA", false);
                t.State("StateA", recorder.CreateAction("EnterA"), recorder.CreateAction("ExitA"), recorder.CreateDoAction("DoA"));
                t.Region("StateA1A", true);
                t.State("StateA1A", recorder.CreateAction("EnterA1A"), recorder.CreateAction("ExitA1A"), recorder.CreateDoAction("DoA1A"));
                t.Transition("T1", "StateA1B", null, null, null);
                t.EndState();
                t.State("StateA1B", recorder.CreateAction("EnterA1B"), recorder.CreateAction("ExitA1B"), recorder.CreateDoAction("DoA1B"));
                t.Transition("T2", "StateB1A", "Event1", null, null);
                t.EndState();
                t.EndRegion();
                t.EndState();
                t.State("StateB", recorder.CreateAction("EnterB"), recorder.CreateAction("ExitB"), recorder.CreateDoAction("DoB"));
                t.Transition("T4", "StateA", "Event2", null, null);
                t.Region("StateB1A", true);
                t.State("StateB1A", recorder.CreateAction("EnterB1A"), recorder.CreateAction("ExitB1A"), recorder.CreateDoAction("DoB1A"));
                t.Transition("T3", "StateB1B", null, null, null);
                t.EndState();
                t.State("StateB1B", recorder.CreateAction("EnterB1B"), recorder.CreateAction("ExitB1B"), recorder.CreateDoAction("DoB1B"));
                t.EndState();
                t.EndRegion();
                t.EndState();
                t.EndRegion();
                //## End StateMachineTemplateSaveStateResumeWithHistory
                return(t);
            };

            StateMachineTemplate t1 = createTemplate();

            t1.SerializationSignatureGenerator = TestSignatureGenerator;
            StateMachine s1 = t1.CreateStateMachine();

            s1.Startup();
            s1.SendTriggerEvent(null);
            s1.SendTriggerEvent("Event1");

            StateConfiguration expectedActiveStateS1 = t1.CreateStateConfiguration("StateB1B");

            Assert.That(s1.ActiveStateConfiguration.ToString(), Is.EqualTo(expectedActiveStateS1.ToString()), "Precondition not met: Unexpected state save state.");
            Assert.That(recorder.RecordedActions, Is.EqualTo(new String[] { "EnterA", "EnterA1A", "DoA", "DoA1A", "ExitA1A", "EnterA1B", "DoA", "DoA1B", "ExitA1B", "ExitA", "EnterB", "EnterB1A", "DoB", "DoB1A", "ExitB1A", "EnterB1B", "DoB", "DoB1B" }), "Precondition not met: Unexpected action execution sequence.");
            recorder.Clear();

            // Act
            MemoryStream memoryStream = new MemoryStream();

            s1.SaveState(memoryStream);
            memoryStream.Flush();
            memoryStream.Position = 0;

            StateMachine s2 = t1.CreateStateMachine();

            s2.Resume(memoryStream, executeEntryActions);

            // Assert
            Assert.That(s2.ActiveStateConfiguration.ToString(), Is.EqualTo(s1.ActiveStateConfiguration.ToString()), "State mismatch after Resume.");
            String[] expectedActions = executeEntryActions ? new String[] { "EnterB", "EnterB1B", "DoB", "DoB1B" } : new String[] { };
            Assert.That(recorder.RecordedActions, Is.EqualTo(expectedActions), "Unexpected entry or do actions during state machine resume with history.");
            recorder.Clear();
            s2.SendTriggerEvent("Event2");
            Assert.That(s2.ActiveStateConfiguration.ToString(), Is.EqualTo(t1.CreateStateConfiguration("StateA1B").ToString()), "Unexpected state machine behavior after Resume.");
            Assert.That(recorder.RecordedActions, Is.EqualTo(new String[] { "ExitB1B", "ExitB", "EnterA", "EnterA1B", "DoA", "DoA1B" }), "Unexpected entry or do actions during state machine resume.");

            // Compatibility test assertions
            // Data obtained from
            // FileStream fileStream = new FileStream("TestData.dat", FileMode.Create);
            // s1.SaveState(fileStream);
            // fileStream.Close();
            // PowerShell> gc -encoding byte "TestData.dat" |% {write-host ("0x{0:X2}," -f $_) -noNewline ""}; write-host
            StringBuilder sb = new StringBuilder();

            Byte[] actualBytes = memoryStream.ToArray();
            for (int i = 0; i < actualBytes.Length; i++)
            {
                sb.Append("0x" + actualBytes[i].ToString("X2") + ", ");
            }
#if !MF_FRAMEWORK
            Console.WriteLine("Actual bytes:");
            Console.WriteLine(sb.ToString());
#else
            Debug.Print("Actual bytes:");
            Debug.Print(sb.ToString());
#endif
            Byte[] compatibilityTestData2300 = new Byte[] { 0xAA, 0x00, 0x23, 0xA1, 0x47, 0x28, 0x7E, 0x31, 0x2D, 0x7B, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x28, 0x7E, 0x31, 0x23, 0x7B, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x31, 0x41, 0x2C, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x31, 0x42, 0x2C, 0x7D, 0x29, 0x2C, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x28, 0x7E, 0x31, 0x23, 0x7B, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x31, 0x41, 0x2C, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x31, 0x42, 0x2C, 0x7D, 0x29, 0x2C, 0x7D, 0x29, 0xA2, 0x01, 0x00, 0xA4, 0x01, 0x00, 0xA5, 0x08, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x31, 0x42, 0xA3, 0x02, 0x00, 0xA4, 0x01, 0x00, 0xA5, 0x08, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x31, 0x42, 0xA4, 0x01, 0x00, 0xA5, 0x08, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x31, 0x42, };
            Assert.That(memoryStream.ToArray(), Is.EqualTo(compatibilityTestData2300), "Compatibility test failed. Written data different from version 2300.");

            MemoryStream         memoryStream2300 = new MemoryStream(compatibilityTestData2300);
            StateMachineTemplate t3 = createTemplate();
            t3.SerializationSignatureGenerator = null;
            StateMachine s3 = t3.CreateStateMachine();
            s3.Resume(memoryStream2300, false);
            Assert.That(s3.ActiveStateConfiguration.ToString(), Is.EqualTo(expectedActiveStateS1.ToString()), "State mismatch after Resume.");
        }
Ejemplo n.º 4
0
        private void SaveStateResume_HappyPath_BehavesAsExpected(bool executeEntryActions)
#endif
        {
            // Arrange
            ActionRecorder recorder = new ActionRecorder();

            StateMachineTemplate t = new StateMachineTemplate(StateMachineOptions.UseDoActions);

            t.Region("StateA", false);
            t.State("StateA", recorder.CreateAction("EnterA"), recorder.CreateAction("ExitA"), recorder.CreateDoAction("DoA"));
            t.Transition("T1", "StateB", null);
            t.EndState();
            t.State("StateB", recorder.CreateAction("EnterB"), recorder.CreateAction("ExitB"), recorder.CreateDoAction("DoB"));
            t.EndState();
            t.EndRegion();

            StateMachine s1 = t.CreateStateMachine();

            s1.Startup();
            recorder.Clear();

            // Act
            MemoryStream memoryStream = new MemoryStream();

            s1.SaveState(memoryStream);
            memoryStream.Flush();
            memoryStream.Position = 0;
            StateMachine s2 = t.CreateStateMachine();

            s2.Resume(memoryStream, executeEntryActions);

            // Assert
            Assert.That(s2.ActiveStateConfiguration.ToString(), Is.EqualTo(s1.ActiveStateConfiguration.ToString()), "State mismatch after Resume.");
            String[] expectedActions = executeEntryActions ? new String[] { "EnterA", "DoA" } : new String[] { };
            Assert.That(recorder.RecordedActions, Is.EqualTo(expectedActions), "Unexpected entry or do actions during state machine resume.");
            recorder.Clear();
            s2.SendTriggerEvent(null);
            Assert.That(s2.ActiveStateConfiguration.ToString(), Is.EqualTo(t.CreateStateConfiguration("StateB").ToString()), "Cannot run state machine after Resume.");
            Assert.That(recorder.RecordedActions, Is.EqualTo(new String[] { "ExitA", "EnterB", "DoB" }), "Unexpected entry or do actions during state machine resume.");
        }
Ejemplo n.º 5
0
        public void SendTriggerEvent_WithOrthogonalRegions_ExecutesActionsInExpectedSequence()
        {
            // Arrange
            const string Startup = "*Startup*";
            const string Finish  = "*Finish*";

            //## Begin StateAndTransitionNames57
            // Generated from <file:S:\StaMa_State_Machine_Controller_Library\StaMaShapesMaster.vst> page "UT_Execution1_OrthogonalRegions"
            // at 07-22-2015 22:05:11 using StaMaShapes Version 2300
            const string StateB     = "StateB";
            const string Transi8    = "Transi8";
            const string Event6     = "Event6";
            const string Transi6    = "Transi6";
            const string Transi3    = "Transi3";
            const string Event2     = "Event2";
            const string Transi5    = "Transi5";
            const string Event5     = "Event5";
            const string StateB1A   = "StateB1A";
            const string StateB1B   = "StateB1B";
            const string StateB2A   = "StateB2A";
            const string StateB2B   = "StateB2B";
            const string Transi9    = "Transi9";
            const string Event4     = "Event4";
            const string StateB2B1A = "StateB2B1A";
            const string StateB2B2A = "StateB2B2A";
            const string Transi4    = "Transi4";
            const string Event3     = "Event3";
            const string StateB2B2B = "StateB2B2B";
            const string StateB2B3A = "StateB2B3A";
            const string Transi7    = "Transi7";
            const string StateB2B3B = "StateB2B3B";
            const string StateC     = "StateC";
            const string StateA     = "StateA";
            const string Transi1    = "Transi1";
            const string Event1     = "Event1";
            //## End StateAndTransitionNames57

            //## Begin ActionNames
            // Generated from <file:S:\StaMa_State_Machine_Controller_Library\StaMaShapesMaster.vst> page "UT_Execution1_OrthogonalRegions"
            // at 07-22-2015 22:05:11 using StaMaShapes Version 2300
            const string EnterB     = "EnterB";
            const string ExitB      = "ExitB";
            const string DoB        = "DoB";
            const string EnterB1A   = "EnterB1A";
            const string ExitB1A    = "ExitB1A";
            const string DoB1A      = "DoB1A";
            const string EnterB1B   = "EnterB1B";
            const string ExitB1B    = "ExitB1B";
            const string DoB1B      = "DoB1B";
            const string EnterB2A   = "EnterB2A";
            const string ExitB2A    = "ExitB2A";
            const string DoB2A      = "DoB2A";
            const string EnterB2B   = "EnterB2B";
            const string ExitB2B    = "ExitB2B";
            const string DoB2B      = "DoB2B";
            const string EnterB2B1A = "EnterB2B1A";
            const string ExitB2B1A  = "ExitB2B1A";
            const string DoB2B1A    = "DoB2B1A";
            const string EnterB2B2A = "EnterB2B2A";
            const string ExitB2B2A  = "ExitB2B2A";
            const string DoB2B2A    = "DoB2B2A";
            const string EnterB2B2B = "EnterB2B2B";
            const string ExitB2B2B  = "ExitB2B2B";
            const string DoB2B2B    = "DoB2B2B";
            const string EnterB2B3A = "EnterB2B3A";
            const string ExitB2B3A  = "ExitB2B3A";
            const string DoB2B3A    = "DoB2B3A";
            const string EnterB2B3B = "EnterB2B3B";
            const string ExitB2B3B  = "ExitB2B3B";
            const string DoB2B3B    = "DoB2B3B";
            const string EnterC     = "EnterC";
            const string ExitC      = "ExitC";
            const string DoC        = "DoC";
            const string EnterA     = "EnterA";
            const string ExitA      = "ExitA";
            const string DoA        = "DoA";
            //## End ActionNames

            ActionRecorder recorder = new ActionRecorder();

            StateMachineTemplate t = new StateMachineTemplate(StateMachineOptions.UseDoActions);

            //## Begin StateMachineTemplate4
            // Generated from <file:S:\StaMa_State_Machine_Controller_Library\StaMaShapesMaster.vst> page "UT_Execution1_OrthogonalRegions"
            // at 07-22-2015 22:05:12 using StaMaShapes Version 2300
            t.Region(StateA, false);
            t.State(StateB, recorder.CreateAction(EnterB), recorder.CreateAction(ExitB), recorder.CreateDoAction(DoB));
            t.Transition(Transi8, StateB2A, StateC, Event6, null, null);
            t.Transition(Transi6, new string[] { StateB1B, StateB2B }, StateA, Event6, null, null);
            t.Transition(Transi3, StateB1A, new string[] { StateB1B, StateB2B }, Event2, null, null);
            t.Transition(Transi5, StateB2B2A, new string[] { StateB1B, StateB2B2A }, Event5, null, null);
            t.Region(StateB1A, false);
            t.State(StateB1A, recorder.CreateAction(EnterB1A), recorder.CreateAction(ExitB1A), recorder.CreateDoAction(DoB1A));
            t.EndState();
            t.State(StateB1B, recorder.CreateAction(EnterB1B), recorder.CreateAction(ExitB1B), recorder.CreateDoAction(DoB1B));
            t.EndState();
            t.EndRegion();
            t.Region(StateB2A, false);
            t.State(StateB2A, recorder.CreateAction(EnterB2A), recorder.CreateAction(ExitB2A), recorder.CreateDoAction(DoB2A));
            t.EndState();
            t.State(StateB2B, recorder.CreateAction(EnterB2B), recorder.CreateAction(ExitB2B), recorder.CreateDoAction(DoB2B));
            t.Transition(Transi9, StateB2B, Event4, null, null);
            t.Region(StateB2B1A, false);
            t.State(StateB2B1A, recorder.CreateAction(EnterB2B1A), recorder.CreateAction(ExitB2B1A), recorder.CreateDoAction(DoB2B1A));
            t.EndState();
            t.EndRegion();
            t.Region(StateB2B2A, false);
            t.State(StateB2B2A, recorder.CreateAction(EnterB2B2A), recorder.CreateAction(ExitB2B2A), recorder.CreateDoAction(DoB2B2A));
            t.Transition(Transi4, StateB2B2B, Event3, null, null);
            t.EndState();
            t.State(StateB2B2B, recorder.CreateAction(EnterB2B2B), recorder.CreateAction(ExitB2B2B), recorder.CreateDoAction(DoB2B2B));
            t.EndState();
            t.EndRegion();
            t.Region(StateB2B3A, true);
            t.State(StateB2B3A, recorder.CreateAction(EnterB2B3A), recorder.CreateAction(ExitB2B3A), recorder.CreateDoAction(DoB2B3A));
            t.Transition(Transi7, StateB2B3B, Event3, null, null);
            t.EndState();
            t.State(StateB2B3B, recorder.CreateAction(EnterB2B3B), recorder.CreateAction(ExitB2B3B), recorder.CreateDoAction(DoB2B3B));
            t.EndState();
            t.EndRegion();
            t.EndState();
            t.EndRegion();
            t.EndState();
            t.State(StateC, recorder.CreateAction(EnterC), recorder.CreateAction(ExitC), recorder.CreateDoAction(DoC));
            t.EndState();
            t.State(StateA, recorder.CreateAction(EnterA), recorder.CreateAction(ExitA), recorder.CreateDoAction(DoA));
            t.Transition(Transi1, StateB, Event1, null, null);
            t.EndState();
            t.EndRegion();
            //## End StateMachineTemplate4

            StateMachine stateMachine = t.CreateStateMachine(this);

            stateMachine.TraceStateChange = delegate(StateMachine stateMachinex, StateConfiguration stateConfigurationFrom, StateConfiguration stateConfigurationTo, Transition transition)
            {
                System.Console.WriteLine("TestExecConcurrent: Transition from {0} to {1} using {2}",
                                         stateConfigurationFrom.ToString(),
                                         stateConfigurationTo.ToString(),
                                         (transition != null) ? transition.Name : "*");
            };

            stateMachine.TraceTestTransition = delegate(StateMachine stateMachinex, Transition transition, object triggerEvent, EventArgs eventArgs)
            {
                System.Console.WriteLine("TestExecConcurrent: Test transition {0} with event {1} in state {2}",
                                         transition.ToString(),
                                         (triggerEvent != null) ? triggerEvent.ToString() : "*",
                                         stateMachine.ActiveStateConfiguration.ToString());
            };

            stateMachine.TraceDispatchTriggerEvent = delegate(StateMachine stateMachinex, object triggerEvent, EventArgs eventArgs)
            {
                string eventName = (triggerEvent != null) ? triggerEvent.ToString() : "*";
                System.Console.WriteLine("TestExecConcurrent: Dispatch event {0} in state {1}", eventName, stateMachine.ActiveStateConfiguration.ToString());
            };

            Assert.That(recorder.RecordedActions, Is.EqualTo(new String[] {}), "Precondition not met: Actions were executed during state machine creation.");

            foreach (TestData testData in new TestData[]
            {
                new TestData()
                {
                    EventToSend = Startup,
                    ExpectedState = t.CreateStateConfiguration(new String[] { StateA }),
                    ExpectedActions = new String[] { EnterA, DoA, },
                },
                new TestData()
                {
                    EventToSend = Event1,
                    ExpectedState = t.CreateStateConfiguration(new String[] { StateB1A, StateB2A }),
                    ExpectedActions = new String[] { ExitA, EnterB, EnterB1A, EnterB2A, DoB, DoB1A, DoB2A, },
                },
                new TestData()
                {
                    EventToSend = Event2,
                    ExpectedState = t.CreateStateConfiguration(new String[] { StateB1B, StateB2B1A, StateB2B2A, StateB2B3A }),
                    ExpectedActions = new String[] { ExitB2A, ExitB1A, ExitB, EnterB, EnterB1B, EnterB2B, EnterB2B1A, EnterB2B2A, EnterB2B3A, DoB, DoB1B, DoB2B, DoB2B1A, DoB2B2A, DoB2B3A, },
                },
                new TestData()
                {
                    EventToSend = Event3,
                    ExpectedState = t.CreateStateConfiguration(new String[] { StateB1B, StateB2B1A, StateB2B2B, StateB2B3B }),
                    ExpectedActions = new String[] { ExitB2B2A, EnterB2B2B, ExitB2B3A, EnterB2B3B, DoB, DoB1B, DoB2B, DoB2B1A, DoB2B2B, DoB2B3B, },
                },
                new TestData()
                {
                    EventToSend = Event4,
                    ExpectedState = t.CreateStateConfiguration(new String[] { StateB1B, StateB2B1A, StateB2B2A, StateB2B3B }),
                    ExpectedActions = new String[] { ExitB2B3B, ExitB2B2B, ExitB2B1A, ExitB2B, EnterB2B, EnterB2B1A, EnterB2B2A, EnterB2B3B, DoB, DoB1B, DoB2B, DoB2B1A, DoB2B2A, DoB2B3B },
                },
                new TestData()
                {
                    EventToSend = Event5,
                    ExpectedState = t.CreateStateConfiguration(new String[] { StateB1B, StateB2B1A, StateB2B2A, StateB2B3B }),
                    ExpectedActions = new String[] { ExitB2B3B, ExitB2B2A, ExitB2B1A, ExitB2B, ExitB1B, ExitB, EnterB, EnterB1B, EnterB2B, EnterB2B1A, EnterB2B2A, EnterB2B3B, DoB, DoB1B, DoB2B, DoB2B1A, DoB2B2A, DoB2B3B, },
                },
                new TestData()
                {
                    EventToSend = Event6,
                    ExpectedState = t.CreateStateConfiguration(new String[] { StateA }),
                    ExpectedActions = new String[] { ExitB2B3B, ExitB2B2A, ExitB2B1A, ExitB2B, ExitB1B, ExitB, EnterA, DoA, },
                },
                new TestData()
                {
                    EventToSend = Finish,
                    ExpectedState = t.CreateStateConfiguration(new String[] { }),
                    ExpectedActions = new String[] { ExitA },
                },
            })
            {
                recorder.Clear();

                // Act
                switch (testData.EventToSend)
                {
                case Startup:
                    stateMachine.Startup();
                    break;

                case Finish:
                    stateMachine.Finish();
                    break;

                default:
                    stateMachine.SendTriggerEvent(testData.EventToSend);
                    break;
                }

                // Assert
                Assert.That(stateMachine.ActiveStateConfiguration.ToString(), Is.EqualTo(testData.ExpectedState.ToString()), testData.EventToSend + ": Active state not as expected.");
                Assert.That(recorder.RecordedActions, Is.EqualTo(testData.ExpectedActions), testData.EventToSend + ": Unexpected entry and exit actions during state machine processing.");
            }
        }