]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/msm/test/SimpleWithFunctors.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / msm / test / SimpleWithFunctors.cpp
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 #include <iostream>
12 // back-end
13 #include <boost/msm/back/state_machine.hpp>
14 //front-end
15 #include <boost/msm/front/state_machine_def.hpp>
16 // functors
17 #include <boost/msm/front/functor_row.hpp>
18 #include <boost/msm/front/euml/common.hpp>
19 // for And_ operator
20 #include <boost/msm/front/euml/operator.hpp>
21
22 #ifndef BOOST_MSM_NONSTANDALONE_TEST
23 #define BOOST_TEST_MODULE MyTest
24 #endif
25 #include <boost/test/unit_test.hpp>
26
27 using namespace std;
28 namespace msm = boost::msm;
29 namespace mpl = boost::mpl;
30 using namespace msm::front;
31 // for And_ operator
32 using namespace msm::front::euml;
33
34 namespace
35 {
36 // events
37 struct play {};
38 struct end_pause {};
39 struct stop {};
40 struct pause {};
41 struct open_close {};
42
43 // A "complicated" event type that carries some data.
44 enum DiskTypeEnum
45 {
46 DISK_CD=0,
47 DISK_DVD=1
48 };
49 struct cd_detected
50 {
51 cd_detected(std::string name, DiskTypeEnum diskType)
52 : name(name),
53 disc_type(diskType)
54 {}
55
56 std::string name;
57 DiskTypeEnum disc_type;
58 };
59
60 // front-end: define the FSM structure
61 struct player_ : public msm::front::state_machine_def<player_>
62 {
63 unsigned int start_playback_counter;
64 unsigned int can_close_drawer_counter;
65 unsigned int test_fct_counter;
66
67 player_():
68 start_playback_counter(0),
69 can_close_drawer_counter(0),
70 test_fct_counter(0)
71 {}
72
73 // The list of FSM states
74 struct Empty : public msm::front::state<>
75 {
76 template <class Event,class FSM>
77 void on_entry(Event const&,FSM& ) {++entry_counter;}
78 template <class Event,class FSM>
79 void on_exit(Event const&,FSM& ) {++exit_counter;}
80 int entry_counter;
81 int exit_counter;
82 };
83 struct Open : public msm::front::state<>
84 {
85 template <class Event,class FSM>
86 void on_entry(Event const&,FSM& ) {++entry_counter;}
87 template <class Event,class FSM>
88 void on_exit(Event const&,FSM& ) {++exit_counter;}
89 int entry_counter;
90 int exit_counter;
91 };
92
93 // sm_ptr still supported but deprecated as functors are a much better way to do the same thing
94 struct Stopped : public msm::front::state<>
95 {
96 template <class Event,class FSM>
97 void on_entry(Event const&,FSM& ) {++entry_counter;}
98 template <class Event,class FSM>
99 void on_exit(Event const&,FSM& ) {++exit_counter;}
100 int entry_counter;
101 int exit_counter;
102 };
103
104 struct Playing : public msm::front::state<>
105 {
106 template <class Event,class FSM>
107 void on_entry(Event const&,FSM& ) {++entry_counter;}
108 template <class Event,class FSM>
109 void on_exit(Event const&,FSM& ) {++exit_counter;}
110 int entry_counter;
111 int exit_counter;
112 };
113
114 // state not defining any entry or exit
115 struct Paused : public msm::front::state<>
116 {
117 template <class Event,class FSM>
118 void on_entry(Event const&,FSM& ) {++entry_counter;}
119 template <class Event,class FSM>
120 void on_exit(Event const&,FSM& ) {++exit_counter;}
121 int entry_counter;
122 int exit_counter;
123 };
124
125 // the initial state of the player SM. Must be defined
126 typedef Empty initial_state;
127
128 // transition actions
129 struct TestFct
130 {
131 template <class EVT,class FSM,class SourceState,class TargetState>
132 void operator()(EVT const&, FSM& fsm,SourceState& ,TargetState& )
133 {
134 ++fsm.test_fct_counter;
135 }
136 };
137 struct start_playback
138 {
139 template <class EVT,class FSM,class SourceState,class TargetState>
140 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
141 {
142 ++fsm.start_playback_counter;
143 }
144 };
145 struct open_drawer
146 {
147 template <class EVT,class FSM,class SourceState,class TargetState>
148 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
149 {
150 }
151 };
152 struct close_drawer
153 {
154 template <class EVT,class FSM,class SourceState,class TargetState>
155 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
156 {
157 }
158 };
159 struct store_cd_info
160 {
161 template <class EVT,class FSM,class SourceState,class TargetState>
162 void operator()(EVT const&,FSM& fsm ,SourceState& ,TargetState& )
163 {
164 fsm.process_event(play());
165 }
166 };
167 struct stop_playback
168 {
169 template <class EVT,class FSM,class SourceState,class TargetState>
170 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
171 {
172 }
173 };
174 struct pause_playback
175 {
176 template <class EVT,class FSM,class SourceState,class TargetState>
177 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
178 {
179 }
180 };
181 struct resume_playback
182 {
183 template <class EVT,class FSM,class SourceState,class TargetState>
184 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
185 {
186 }
187 };
188 struct stop_and_open
189 {
190 template <class EVT,class FSM,class SourceState,class TargetState>
191 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
192 {
193 }
194 };
195 struct stopped_again
196 {
197 template <class EVT,class FSM,class SourceState,class TargetState>
198 void operator()(EVT const& ,FSM& ,SourceState& ,TargetState& )
199 {
200 }
201 };
202 // guard conditions
203 struct DummyGuard
204 {
205 template <class EVT,class FSM,class SourceState,class TargetState>
206 bool operator()(EVT const&,FSM&,SourceState&,TargetState&)
207 {
208 return true;
209 }
210 };
211 struct good_disk_format
212 {
213 template <class EVT,class FSM,class SourceState,class TargetState>
214 bool operator()(EVT const& evt ,FSM&,SourceState& ,TargetState& )
215 {
216 // to test a guard condition, let's say we understand only CDs, not DVD
217 if (evt.disc_type != DISK_CD)
218 {
219 return false;
220 }
221 return true;
222 }
223 };
224 struct always_true
225 {
226 template <class EVT,class FSM,class SourceState,class TargetState>
227 bool operator()(EVT const& ,FSM&,SourceState& ,TargetState& )
228 {
229 return true;
230 }
231 };
232 struct can_close_drawer
233 {
234 template <class EVT,class FSM,class SourceState,class TargetState>
235 bool operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
236 {
237 ++fsm.can_close_drawer_counter;
238 return true;
239 }
240 };
241
242 typedef player_ p; // makes transition table cleaner
243
244 // Transition table for player
245 struct transition_table : mpl::vector<
246 // Start Event Next Action Guard
247 // +---------+-------------+---------+---------------------+----------------------+
248 Row < Stopped , play , Playing , ActionSequence_
249 <mpl::vector<
250 TestFct,start_playback> >
251 , DummyGuard >,
252 Row < Stopped , open_close , Open , open_drawer , none >,
253 Row < Stopped , stop , Stopped , none , none >,
254 // +---------+-------------+---------+---------------------------+----------------------+
255 Row < Open , open_close , Empty , close_drawer , can_close_drawer >,
256 // +---------+-------------+---------+---------------------------+----------------------+
257 Row < Empty , open_close , Open , open_drawer , none >,
258 Row < Empty , cd_detected , Stopped , store_cd_info , And_<good_disk_format,
259 always_true> >,
260 // +---------+-------------+---------+---------------------------+----------------------+
261 Row < Playing , stop , Stopped , stop_playback , none >,
262 Row < Playing , pause , Paused , pause_playback , none >,
263 Row < Playing , open_close , Open , stop_and_open , none >,
264 // +---------+-------------+---------+---------------------------+----------------------+
265 Row < Paused , end_pause , Playing , resume_playback , none >,
266 Row < Paused , stop , Stopped , stop_playback , none >,
267 Row < Paused , open_close , Open , stop_and_open , none >
268
269 // +---------+-------------+---------+---------------------+----------------------+
270 > {};
271 // Replaces the default no-transition response.
272 template <class FSM,class Event>
273 void no_transition(Event const&, FSM&,int)
274 {
275 BOOST_FAIL("no_transition called!");
276 }
277 // init counters
278 template <class Event,class FSM>
279 void on_entry(Event const&,FSM& fsm)
280 {
281 fsm.template get_state<player_::Stopped&>().entry_counter=0;
282 fsm.template get_state<player_::Stopped&>().exit_counter=0;
283 fsm.template get_state<player_::Open&>().entry_counter=0;
284 fsm.template get_state<player_::Open&>().exit_counter=0;
285 fsm.template get_state<player_::Empty&>().entry_counter=0;
286 fsm.template get_state<player_::Empty&>().exit_counter=0;
287 fsm.template get_state<player_::Playing&>().entry_counter=0;
288 fsm.template get_state<player_::Playing&>().exit_counter=0;
289 fsm.template get_state<player_::Paused&>().entry_counter=0;
290 fsm.template get_state<player_::Paused&>().exit_counter=0;
291 }
292
293 };
294 // Pick a back-end
295 typedef msm::back::state_machine<player_> player;
296
297 // static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
298
299
300 BOOST_AUTO_TEST_CASE( my_test )
301 {
302 player p;
303
304 p.start();
305 BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
306
307 p.process_event(open_close());
308 BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
309 BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
310 BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
311
312 p.process_event(open_close());
313 BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
314 BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
315 BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
316 BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
317
318 p.process_event(
319 cd_detected("louie, louie",DISK_DVD));
320 BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
321 BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
322 BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
323
324 p.process_event(
325 cd_detected("louie, louie",DISK_CD));
326 BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
327 BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
328 BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
329 BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
330 BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
331 BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
332 BOOST_CHECK_MESSAGE(p.test_fct_counter == 1,"action not called correctly");
333
334 p.process_event(pause());
335 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
336 BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
337 BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
338
339 // go back to Playing
340 p.process_event(end_pause());
341 BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
342 BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
343 BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
344
345 p.process_event(pause());
346 BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
347 BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
348 BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
349
350 p.process_event(stop());
351 BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
352 BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
353 BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
354
355 p.process_event(stop());
356 BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
357 BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
358 BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
359 }
360 }
361