1// Copyright 2010 Christophe Henry
2// henry UNDERSCORE christophe AT hotmail DOT com
3// This is an extended version of the state machine available in the boost::mpl library
4// Distributed under the same license as the original.
5// Copyright for the original version:
6// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
7// under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10
11// back-end
12#include <boost/msm/back/state_machine.hpp>
13#include <boost/msm/front/euml/euml.hpp>
14
15#ifndef BOOST_MSM_NONSTANDALONE_TEST
16#define BOOST_TEST_MODULE MyTest
17#endif
18#include <boost/test/unit_test.hpp>
19
20namespace msm = boost::msm;
21using namespace boost::msm::front::euml;
22
23namespace
24{
25 // events
26 BOOST_MSM_EUML_EVENT(event1)
27
28 // The list of FSM states
29 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,entry_counter)
30 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,exit_counter)
31
32 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),State1)
33 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),State2)
34 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),State3)
35 BOOST_MSM_EUML_STATE(( ++state_(entry_counter),++state_(exit_counter),attributes_ << entry_counter << exit_counter),State4)
36
37 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,state2_to_state3_counter)
38 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,state3_to_state4_counter)
39 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,always_true_counter)
40 BOOST_MSM_EUML_DECLARE_ATTRIBUTE(unsigned int,always_false_counter)
41
42 // transition actions
43 BOOST_MSM_EUML_ACTION(State2ToState3)
44 {
45 template <class FSM,class EVT,class SourceState,class TargetState>
46 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
47 {
48 ++fsm.get_attribute(state2_to_state3_counter);
49 }
50 };
51 BOOST_MSM_EUML_ACTION(State3ToState4)
52 {
53 template <class FSM,class EVT,class SourceState,class TargetState>
54 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
55 {
56 ++fsm.get_attribute(state3_to_state4_counter);
57 }
58 };
59 // guard conditions
60 BOOST_MSM_EUML_ACTION(always_true)
61 {
62 template <class FSM,class EVT,class SourceState,class TargetState>
63 bool operator()(EVT const&,FSM& fsm,SourceState& ,TargetState& )
64 {
65 ++fsm.get_attribute(always_true_counter);
66 return true;
67 }
68 };
69 BOOST_MSM_EUML_ACTION(always_false)
70 {
71 template <class FSM,class EVT,class SourceState,class TargetState>
72 bool operator()(EVT const&,FSM& fsm,SourceState& ,TargetState& )
73 {
74 ++fsm.get_attribute(always_false_counter);
75 return false;
76 }
77 };
78
79 BOOST_MSM_EUML_ACTION(No_Transition)
80 {
81 template <class FSM,class Event>
82 void operator()(Event const&,FSM&,int)
83 {
84 BOOST_FAIL("no_transition called!");
85 }
86 };
87
88 BOOST_MSM_EUML_TRANSITION_TABLE((
89 State2 == State1 ,
90 State3 == State2 / State2ToState3,
91 State4 == State3 [always_true] / State3ToState4,
92 State4 == State3 [always_false],
93 State1 == State4 + event1
94 // +------------------------------------------------------------------------------+
95 ),transition_table)
96
97 // create a state machine "on the fly"
98 BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
99 init_ << State1, // Init State
100 no_action, // Entry
101 no_action, // Exit
102 attributes_ << state2_to_state3_counter << state3_to_state4_counter
103 << always_true_counter << always_false_counter, // Attributes
104 configure_ << no_configure_, // configuration
105 No_Transition // no_transition handler
106 ),
107 my_machine_) //fsm name
108
109 // Pick a back-end
110 typedef msm::back::state_machine<my_machine_> my_machine;
111
112 //static char const* const state_names[] = { "State1", "State2", "State3", "State4" };
113
114 BOOST_AUTO_TEST_CASE( my_test )
115 {
116 my_machine p;
117
118 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
119 // in this case it will also immediately trigger all anonymous transitions
120 p.start();
121 BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
122 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(exit_counter) == 1,
123 "State1 exit not called correctly");
124 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(entry_counter) == 1,
125 "State1 entry not called correctly");
126 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(exit_counter) == 1,
127 "State2 exit not called correctly");
128 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(entry_counter) == 1,
129 "State2 entry not called correctly");
130 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(exit_counter) == 1,
131 "State3 exit not called correctly");
132 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(entry_counter) == 1,
133 "State3 entry not called correctly");
134 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State4)&>().get_attribute(entry_counter)== 1,
135 "State4 entry not called correctly");
136 BOOST_CHECK_MESSAGE(p.get_attribute(always_true_counter) == 1,"guard not called correctly");
137 BOOST_CHECK_MESSAGE(p.get_attribute(always_false_counter) == 1,"guard not called correctly");
138 BOOST_CHECK_MESSAGE(p.get_attribute(state2_to_state3_counter) == 1,"action not called correctly");
139 BOOST_CHECK_MESSAGE(p.get_attribute(state3_to_state4_counter) == 1,"action not called correctly");
140
141
142 // this event will bring us back to the initial state and thus, a new "loop" will be started
143 p.process_event(evt: event1);
144 BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"State4 should be active"); //State4
145 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(exit_counter) == 2,
146 "State1 exit not called correctly");
147 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State1)&>().get_attribute(entry_counter) == 2,
148 "State1 entry not called correctly");
149 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(exit_counter) == 2,
150 "State2 exit not called correctly");
151 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State2)&>().get_attribute(entry_counter) == 2,
152 "State2 entry not called correctly");
153 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(exit_counter) == 2,
154 "State3 exit not called correctly");
155 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State3)&>().get_attribute(entry_counter) == 2,
156 "State3 entry not called correctly");
157 BOOST_CHECK_MESSAGE(p.get_state<BOOST_MSM_EUML_STATE_NAME(State4)&>().get_attribute(entry_counter)== 2,
158 "State4 entry not called correctly");
159 BOOST_CHECK_MESSAGE(p.get_attribute(always_true_counter) == 2,"guard not called correctly");
160 BOOST_CHECK_MESSAGE(p.get_attribute(always_false_counter) == 2,"guard not called correctly");
161 BOOST_CHECK_MESSAGE(p.get_attribute(state2_to_state3_counter) == 2,"action not called correctly");
162 BOOST_CHECK_MESSAGE(p.get_attribute(state3_to_state4_counter) == 2,"action not called correctly");
163
164 }
165}
166
167

source code of boost/libs/msm/test/AnonymousEuml.cpp