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 | |
20 | namespace msm = boost::msm; |
21 | using namespace boost::msm::front::euml; |
22 | |
23 | namespace |
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 | |