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//front-end
14#include <boost/msm/front/state_machine_def.hpp>
15
16#include <boost/test/unit_test.hpp>
17
18namespace msm = boost::msm;
19namespace mpl = boost::mpl;
20using namespace boost::msm::front;
21
22namespace
23{
24 // events
25 struct event1 {};
26 struct event2 {};
27
28
29 // front-end: define the FSM structure
30 struct my_machine_ : public msm::front::state_machine_def<my_machine_>
31 {
32
33 my_machine_()
34 {}
35
36 // The list of FSM states
37 struct State1 : public msm::front::state<>
38 {
39 template <class Event,class FSM>
40 void on_entry(Event const&,FSM& ) {++entry_counter;}
41 template <class Event,class FSM>
42 void on_exit(Event const&,FSM& ) {++exit_counter;}
43 int entry_counter=0;
44 int exit_counter=0;
45 };
46 struct State2 : public msm::front::state<>
47 {
48 template <class Event,class FSM>
49 void on_entry(Event const&,FSM& ) {++entry_counter;}
50 template <class Event,class FSM>
51 void on_exit(Event const&,FSM& ) {++exit_counter;}
52 int entry_counter=0;
53 int exit_counter=0;
54 };
55 struct State3 : public msm::front::state<>
56 {
57 template <class Event,class FSM>
58 void on_entry(Event const&,FSM& ) {++entry_counter;}
59 template <class Event,class FSM>
60 void on_exit(Event const&,FSM& ) {++exit_counter;}
61 int entry_counter=0;
62 int exit_counter=0;
63 };
64 struct State4 : public msm::front::state<>
65 {
66 template <class Event,class FSM>
67 void on_entry(Event const&,FSM& ) {++entry_counter;}
68 template <class Event,class FSM>
69 void on_exit(Event const&,FSM& ) {++exit_counter;}
70 int entry_counter=0;
71 int exit_counter=0;
72 };
73 struct State5 : public msm::front::state<>
74 {
75 template <class Event,class FSM>
76 void on_entry(Event const&,FSM& ) {++entry_counter;}
77 template <class Event,class FSM>
78 void on_exit(Event const&,FSM& ) {++exit_counter;}
79 int entry_counter=0;
80 int exit_counter=0;
81 };
82 struct State6 : public msm::front::state<>
83 {
84 template <class Event,class FSM>
85 void on_entry(Event const&,FSM& ) {++entry_counter;}
86 template <class Event,class FSM>
87 void on_exit(Event const&,FSM& ) {++exit_counter;}
88 int entry_counter=0;
89 int exit_counter=0;
90 };
91 struct State7 : public msm::front::state<>
92 {
93 template <class Event,class FSM>
94 void on_entry(Event const&,FSM& ) {++entry_counter;}
95 template <class Event,class FSM>
96 void on_exit(Event const&,FSM& ) {++exit_counter;}
97 int entry_counter=0;
98 int exit_counter=0;
99 };
100 struct State8 : public msm::front::state<>
101 {
102 template <class Event,class FSM>
103 void on_entry(Event const&,FSM& ) {++entry_counter;}
104 template <class Event,class FSM>
105 void on_exit(Event const&,FSM& ) {++exit_counter;}
106 int entry_counter=0;
107 int exit_counter=0;
108 };
109 struct State9 : public msm::front::state<>
110 {
111 template <class Event,class FSM>
112 void on_entry(Event const&,FSM& ) {++entry_counter;}
113 template <class Event,class FSM>
114 void on_exit(Event const&,FSM& ) {++exit_counter;}
115 int entry_counter=0;
116 int exit_counter=0;
117 };
118 struct State10 : public msm::front::state<>
119 {
120 template <class Event,class FSM>
121 void on_entry(Event const&,FSM& ) {++entry_counter;}
122 template <class Event,class FSM>
123 void on_exit(Event const&,FSM& ) {++exit_counter;}
124 int entry_counter=0;
125 int exit_counter=0;
126 };
127 struct State11 : public msm::front::state<>
128 {
129 template <class Event,class FSM>
130 void on_entry(Event const&,FSM& ) {++entry_counter;}
131 template <class Event,class FSM>
132 void on_exit(Event const&,FSM& ) {++exit_counter;}
133 int entry_counter=0;
134 int exit_counter=0;
135 };
136 struct State12 : public msm::front::state<>
137 {
138 template <class Event,class FSM>
139 void on_entry(Event const&,FSM& ) {++entry_counter;}
140 template <class Event,class FSM>
141 void on_exit(Event const&,FSM& ) {++exit_counter;}
142 int entry_counter=0;
143 int exit_counter=0;
144 };
145
146 // the initial state of the player SM. Must be defined
147 typedef State1 initial_state;
148
149 // transition actions
150
151 // guard conditions
152
153 typedef my_machine_ p; // makes transition table cleaner
154
155 // Transition table for player
156 struct transition_table : mpl::vector<
157 // Start Event Next Action Guard
158 // +---------+-------------+---------+---------------------+----------------------+
159 _row < State1 , event1 , State2 >,
160 _row < State2 , event1 , State3 >,
161 _row < State3 , event1 , State4 >,
162 _row < State4 , event1 , State5 >,
163 _row < State5 , event1 , State6 >,
164 _row < State6 , event1 , State7 >,
165 _row < State7 , event1 , State8 >,
166 _row < State8 , event1 , State9 >,
167 _row < State9 , event1 , State10 >,
168 _row < State10 , event1 , State11 >,
169 _row < State11 , event1 , State12 >,
170
171 _row < State12 , event2 , State11 >,
172 _row < State11 , event2 , State10 >,
173 _row < State10 , event2 , State9 >,
174 _row < State9 , event2 , State8 >,
175 _row < State8 , event2 , State7 >,
176 _row < State7 , event2 , State6 >,
177 _row < State6 , event2 , State5 >,
178 _row < State5 , event2 , State4 >,
179 _row < State4 , event2 , State3 >,
180 _row < State3 , event2 , State2 >,
181 _row < State2 , event2 , State1 >
182 // +---------+-------------+---------+---------------------+----------------------+
183 > {};
184 // Replaces the default no-transition response.
185 template <class FSM,class Event>
186 void no_transition(Event const&, FSM&,int)
187 {
188 BOOST_FAIL("no_transition called!");
189 }
190 // init counters
191 template <class Event,class FSM>
192 void on_entry(Event const&,FSM&)
193 {
194
195 }
196 };
197 // Pick a back-end
198 typedef msm::back::state_machine<my_machine_> my_machine;
199
200
201 BOOST_AUTO_TEST_CASE( big_with_functors_test )
202 {
203 my_machine p;
204
205 // needed to start the highest-level SM.
206 p.start();
207 BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active"); //State1
208 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 0,"State1 exit not called correctly");
209 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 1,"State1 entry not called correctly");
210 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State5&>().exit_counter == 0,"State5 exit not called correctly");
211 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State5&>().entry_counter == 0,"State5 entry not called correctly");
212
213 p.process_event(evt: event1());
214 p.process_event(evt: event1());
215 p.process_event(evt: event1());
216 p.process_event(evt: event1());
217 p.process_event(evt: event1());
218 p.process_event(evt: event1());
219 p.process_event(evt: event1());
220 p.process_event(evt: event1());
221 p.process_event(evt: event1());
222 p.process_event(evt: event1());
223 p.process_event(evt: event1());
224
225 BOOST_CHECK_MESSAGE(p.current_state()[0] == 11,"State12 should be active"); //State12
226 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State12&>().exit_counter == 0,"State12 exit not called correctly");
227 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State12&>().entry_counter == 1,"State12 entry not called correctly");
228 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 1,"State2 exit not called correctly");
229 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 1,"State2 entry not called correctly");
230 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().exit_counter == 1,"State7 exit not called correctly");
231 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().entry_counter == 1,"State7 entry not called correctly");
232 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().exit_counter == 1,"State10 exit not called correctly");
233 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().entry_counter == 1,"State10 entry not called correctly");
234
235
236 p.process_event(evt: event2());
237 p.process_event(evt: event2());
238 p.process_event(evt: event2());
239 p.process_event(evt: event2());
240 p.process_event(evt: event2());
241 p.process_event(evt: event2());
242 p.process_event(evt: event2());
243 p.process_event(evt: event2());
244 p.process_event(evt: event2());
245 p.process_event(evt: event2());
246 p.process_event(evt: event2());
247
248 BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"State1 should be active"); //State1
249 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().exit_counter == 1,"State1 exit not called correctly");
250 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State1&>().entry_counter == 2,"State1 entry not called correctly");
251 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().exit_counter == 2,"State2 exit not called correctly");
252 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State2&>().entry_counter == 2,"State2 entry not called correctly");
253 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().exit_counter == 2,"State7 exit not called correctly");
254 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State7&>().entry_counter == 2,"State7 entry not called correctly");
255 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().exit_counter == 2,"State10 exit not called correctly");
256 BOOST_CHECK_MESSAGE(p.get_state<my_machine_::State10&>().entry_counter == 2,"State10 entry not called correctly");
257
258 }
259}
260
261

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