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

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