]>
git.proxmox.com Git - ceph.git/blob - 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)
13 #include <boost/msm/back/state_machine.hpp>
15 #include <boost/msm/front/state_machine_def.hpp>
17 #include <boost/msm/front/functor_row.hpp>
18 #include <boost/msm/front/euml/common.hpp>
20 #include <boost/msm/front/euml/operator.hpp>
22 #ifndef BOOST_MSM_NONSTANDALONE_TEST
23 #define BOOST_TEST_MODULE MyTest
25 #include <boost/test/unit_test.hpp>
28 namespace msm
= boost::msm
;
29 namespace mpl
= boost::mpl
;
30 using namespace msm::front
;
32 using namespace msm::front::euml
;
43 // A "complicated" event type that carries some data.
51 cd_detected(std::string name
, DiskTypeEnum diskType
)
57 DiskTypeEnum disc_type
;
60 // front-end: define the FSM structure
61 struct player_
: public msm::front::state_machine_def
<player_
>
63 unsigned int start_playback_counter
;
64 unsigned int can_close_drawer_counter
;
65 unsigned int test_fct_counter
;
68 start_playback_counter(0),
69 can_close_drawer_counter(0),
73 // The list of FSM states
74 struct Empty
: public msm::front::state
<>
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
;}
83 struct Open
: public msm::front::state
<>
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
;}
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
<>
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
;}
104 struct Playing
: public msm::front::state
<>
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
;}
114 // state not defining any entry or exit
115 struct Paused
: public msm::front::state
<>
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
;}
125 // the initial state of the player SM. Must be defined
126 typedef Empty initial_state
;
128 // transition actions
131 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
132 void operator()(EVT
const&, FSM
& fsm
,SourceState
& ,TargetState
& )
134 ++fsm
.test_fct_counter
;
137 struct start_playback
139 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
140 void operator()(EVT
const& ,FSM
& fsm
,SourceState
& ,TargetState
& )
142 ++fsm
.start_playback_counter
;
147 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
148 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
154 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
155 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
161 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
162 void operator()(EVT
const&,FSM
& fsm
,SourceState
& ,TargetState
& )
164 fsm
.process_event(play());
169 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
170 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
174 struct pause_playback
176 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
177 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
181 struct resume_playback
183 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
184 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
190 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
191 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
197 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
198 void operator()(EVT
const& ,FSM
& ,SourceState
& ,TargetState
& )
205 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
206 bool operator()(EVT
const&,FSM
&,SourceState
&,TargetState
&)
211 struct good_disk_format
213 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
214 bool operator()(EVT
const& evt
,FSM
&,SourceState
& ,TargetState
& )
216 // to test a guard condition, let's say we understand only CDs, not DVD
217 if (evt
.disc_type
!= DISK_CD
)
226 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
227 bool operator()(EVT
const& ,FSM
&,SourceState
& ,TargetState
& )
232 struct can_close_drawer
234 template <class EVT
,class FSM
,class SourceState
,class TargetState
>
235 bool operator()(EVT
const& ,FSM
& fsm
,SourceState
& ,TargetState
& )
237 ++fsm
.can_close_drawer_counter
;
242 typedef player_ p
; // makes transition table cleaner
244 // Transition table for player
245 struct transition_table
: mpl::vector
<
246 // Start Event Next Action Guard
247 // +---------+-------------+---------+---------------------+----------------------+
248 Row
< Stopped
, play
, Playing
, ActionSequence_
250 TestFct
,start_playback
> >
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
,
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
>
269 // +---------+-------------+---------+---------------------+----------------------+
271 // Replaces the default no-transition response.
272 template <class FSM
,class Event
>
273 void no_transition(Event
const&, FSM
&,int)
275 BOOST_FAIL("no_transition called!");
278 template <class Event
,class FSM
>
279 void on_entry(Event
const&,FSM
& fsm
)
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;
295 typedef msm::back::state_machine
<player_
> player
;
297 // static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
300 BOOST_AUTO_TEST_CASE( my_test
)
305 BOOST_CHECK_MESSAGE(p
.get_state
<player_::Empty
&>().entry_counter
== 1,"Empty entry not called correctly");
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");
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");
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");
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");
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");
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");
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");
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");
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");