Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / msm / test / OrthogonalDeferred3.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 #include <boost/msm/front/functor_row.hpp>
17
18 #ifndef BOOST_MSM_NONSTANDALONE_TEST
19 #define BOOST_TEST_MODULE MyTest
20 #endif
21 #include <boost/test/unit_test.hpp>
22
23 namespace msm = boost::msm;
24 namespace mpl = boost::mpl;
25 using namespace boost::msm::front;
26
27 namespace
28 {
29     // events
30     struct play {};
31     struct end_pause {};
32     struct stop {};
33     struct pause {};
34     struct open_close {};
35     struct NextSong {};
36     struct PreviousSong {};
37     struct error_found {};
38     struct end_error {};
39     struct do_terminate {};
40
41     // Flags. Allow information about a property of the current state
42     struct PlayingPaused{};
43     struct CDLoaded {};
44     struct FirstSongPlaying {};
45
46     // A "complicated" event type that carries some data.
47     struct cd_detected
48     {
49         cd_detected(std::string name)
50             : name(name)
51         {}
52
53         std::string name;
54     };
55
56     // front-end: define the FSM structure 
57     struct player_ : public msm::front::state_machine_def<player_>
58     {
59         // we want deferred events and no state requires deferred events (only the fsm in the
60         // transition table), so the fsm does.
61         typedef int activate_deferred_events;
62
63         unsigned int start_playback_counter;
64         unsigned int can_close_drawer_counter;
65         unsigned int report_error_counter;
66         unsigned int report_end_error_counter;
67
68         player_():
69         start_playback_counter(0),
70         can_close_drawer_counter(0),
71         report_error_counter(0),
72         report_end_error_counter(0)
73         {}
74         // The list of FSM states
75         struct Empty : 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;
82             int exit_counter;
83         };
84         struct Open : public msm::front::state<> 
85         { 
86             typedef mpl::vector1<CDLoaded>      flag_list;
87             
88             template <class Event,class FSM>
89             void on_entry(Event const&,FSM& ) {++entry_counter;}
90             template <class Event,class FSM>
91             void on_exit(Event const&,FSM& ) {++exit_counter;}
92             int entry_counter;
93             int exit_counter;
94         };
95
96         struct Stopped : public msm::front::state<> 
97         { 
98             typedef mpl::vector1<CDLoaded>      flag_list;
99
100             template <class Event,class FSM>
101             void on_entry(Event const&,FSM& ) {++entry_counter;}
102             template <class Event,class FSM>
103             void on_exit(Event const&,FSM& ) {++exit_counter;}
104             int entry_counter;
105             int exit_counter;
106         };
107
108         // the player state machine contains a state which is himself a state machine
109         // as you see, no need to declare it anywhere so Playing can be developed separately
110         // by another team in another module. For simplicity I just declare it inside player
111         struct Playing_ : public msm::front::state_machine_def<Playing_>
112         {
113             // when playing, the CD is loaded and we are in either pause or playing (duh)
114             typedef mpl::vector2<PlayingPaused,CDLoaded>        flag_list;
115
116             template <class Event,class FSM>
117             void on_entry(Event const&,FSM& ) {++entry_counter;}
118             template <class Event,class FSM>
119             void on_exit(Event const&,FSM& ) {++exit_counter;}
120             int entry_counter;
121             int exit_counter;
122             unsigned int start_next_song_counter;
123             unsigned int start_prev_song_guard_counter;
124
125             Playing_():
126             start_next_song_counter(0),
127             start_prev_song_guard_counter(0)
128             {}
129
130             // The list of FSM states
131             struct Song1 : public msm::front::state<>
132             {
133                 typedef mpl::vector1<FirstSongPlaying>      flag_list;
134
135                 template <class Event,class FSM>
136                 void on_entry(Event const&,FSM& ) {++entry_counter;}
137                 template <class Event,class FSM>
138                 void on_exit(Event const&,FSM& ) {++exit_counter;}
139                 int entry_counter;
140                 int exit_counter;
141             };
142             struct Song2 : public msm::front::state<>
143             { 
144                 template <class Event,class FSM>
145                 void on_entry(Event const&,FSM& ) {++entry_counter;}
146                 template <class Event,class FSM>
147                 void on_exit(Event const&,FSM& ) {++exit_counter;}
148                 int entry_counter;
149                 int exit_counter;
150             };
151             struct Song3 : public msm::front::state<>
152             { 
153                 template <class Event,class FSM>
154                 void on_entry(Event const&,FSM& ) {++entry_counter;}
155                 template <class Event,class FSM>
156                 void on_exit(Event const&,FSM& ) {++exit_counter;}
157                 int entry_counter;
158                 int exit_counter;
159             };
160             // the initial state. Must be defined
161             typedef Song1 initial_state;
162             // transition actions
163             void start_next_song(NextSong const&)       {++start_next_song_counter; }
164             void start_prev_song(PreviousSong const&)       {  }
165             // guard conditions
166             bool start_prev_song_guard(PreviousSong const&)       {++start_prev_song_guard_counter;return true; }
167
168             typedef Playing_ pl; // makes transition table cleaner
169             // Transition table for Playing
170             struct transition_table : mpl::vector4<
171                 //      Start     Event         Next      Action               Guard
172                 //    +---------+-------------+---------+---------------------+----------------------+
173                  _row < Song1   , NextSong    , Song2                                                >,
174                   row < Song2   , PreviousSong, Song1   , &pl::start_prev_song,&pl::start_prev_song_guard>,
175                 a_row < Song2   , NextSong    , Song3   , &pl::start_next_song                       >,
176                 g_row < Song3   , PreviousSong, Song2                         ,&pl::start_prev_song_guard>
177                 //    +---------+-------------+---------+---------------------+----------------------+
178             > {};
179             // Replaces the default no-transition response.
180             template <class FSM,class Event>
181             void no_transition(Event const&, FSM&,int)
182             {
183                 BOOST_FAIL("no_transition called!");
184             }
185         };
186         // back-end
187         typedef msm::back::state_machine<Playing_> Playing;
188
189         // state not defining any entry or exit
190         struct Paused : public msm::front::state<>
191         {
192             typedef mpl::vector2<PlayingPaused,CDLoaded>        flag_list;
193
194             template <class Event,class FSM>
195             void on_entry(Event const&,FSM& ) {++entry_counter;}
196             template <class Event,class FSM>
197             void on_exit(Event const&,FSM& ) {++exit_counter;}
198             int entry_counter;
199             int exit_counter;
200         };
201         struct AllOk : public msm::front::state<>
202         {
203             template <class Event,class FSM>
204             void on_entry(Event const&,FSM& ) {++entry_counter;}
205             template <class Event,class FSM>
206             void on_exit(Event const&,FSM& ) {++exit_counter;}
207             int entry_counter;
208             int exit_counter;
209         };
210         // this state is also made terminal so that all the events are blocked
211         struct ErrorMode :  //public msm::front::terminate_state<> // ErrorMode terminates the state machine
212             public msm::front::interrupt_state<end_error>   // ErroMode just interrupts. Will resume if
213                                                             // the event end_error is generated
214         {
215             template <class Event,class FSM>
216             void on_entry(Event const&,FSM& ) {++entry_counter;}
217             template <class Event,class FSM>
218             void on_exit(Event const&,FSM& ) {++exit_counter;}
219             int entry_counter;
220             int exit_counter;
221         };
222         struct ErrorTerminate :  public msm::front::terminate_state<> // terminates the state machine
223         {
224             template <class Event,class FSM>
225             void on_entry(Event const&,FSM& ) {++entry_counter;}
226             template <class Event,class FSM>
227             void on_exit(Event const&,FSM& ) {++exit_counter;}
228             int entry_counter;
229             int exit_counter;
230         };
231         // the initial state of the player SM. Must be defined
232         typedef mpl::vector<Empty,AllOk> initial_state;
233
234         // transition actions
235         void start_playback(play const&)       {++start_playback_counter; }
236         void open_drawer(open_close const&)    {  }
237         void store_cd_info(cd_detected const&) {  }
238         void stop_playback(stop const&)        {  }
239         void pause_playback(pause const&)      {  }
240         void resume_playback(end_pause const&)      {  }
241         void stop_and_open(open_close const&)  {  }
242         void stopped_again(stop const&){}
243         void report_error(error_found const&) {++report_error_counter;}
244         void report_end_error(end_error const&) {++report_end_error_counter;}
245
246         //guards
247         bool can_close_drawer(open_close const&)   
248         {
249             ++can_close_drawer_counter;
250             return true;
251         }
252         struct is_play_event
253         {
254             template <class EVT,class FSM,class SourceState,class TargetState>
255             bool operator()(EVT const& evt,FSM&,SourceState& ,TargetState& )
256             {
257                 bool is_play = boost::any_cast<play>(&evt) != 0;
258                 return is_play;
259             }
260         };
261         struct MyDefer
262         {
263             // mark as deferring to avoid stack overflows in certain conditions
264             typedef int deferring_action;
265             template <class EVT,class FSM,class SourceState,class TargetState>
266             void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& ) const
267             {
268                 fsm.defer_event(play());
269             }
270         };
271         typedef player_ p; // makes transition table cleaner
272
273         // Transition table for player
274         struct transition_table : mpl::vector<
275             //      Start     Event         Next      Action               Guard
276             //    +---------+-------------+---------+---------------------+----------------------+
277             a_row < Stopped , play        , Playing , &p::start_playback                         >,
278             a_row < Stopped , open_close  , Open    , &p::open_drawer                            >,
279              _row < Stopped , stop        , Stopped                                              >,
280             //  +---------+-------------+---------+---------------------+----------------------+
281             g_row < Open    , open_close  , Empty   ,                     &p::can_close_drawer   >,
282             Row   < Open    , play        , none    , Defer             , none                   >,
283             //  +---------+-------------+---------+---------------------+----------------------+
284             a_row < Empty   , open_close  , Open    , &p::open_drawer                            >,
285             a_row < Empty   , cd_detected , Stopped , &p::store_cd_info                          >,
286             Row   < Empty   , boost::any        , none    , MyDefer             , is_play_event                   >,
287             //  +---------+-------------+---------+---------------------+----------------------+
288             a_row < Playing , stop        , Stopped , &p::stop_playback                          >,
289             a_row < Playing , pause       , Paused  , &p::pause_playback                         >,
290             a_row < Playing , open_close  , Open    , &p::stop_and_open                          >,
291             //  +---------+-------------+---------+---------------------+----------------------+
292             a_row < Paused  , end_pause   , Playing , &p::resume_playback                        >,
293             a_row < Paused  , stop        , Stopped , &p::stop_playback                          >,
294             a_row < Paused  , open_close  , Open    , &p::stop_and_open                          >,
295             //    +---------+-------------+---------+---------------------+----------------------+
296             a_row < AllOk   , error_found ,ErrorMode, &p::report_error                           >,
297             a_row <ErrorMode, end_error   ,AllOk    , &p::report_end_error                       >,
298              _row < AllOk   , do_terminate,ErrorTerminate                                        >
299             //    +---------+-------------+---------+---------------------+----------------------+
300         > {};
301
302         // Replaces the default no-transition response.
303         template <class FSM,class Event>
304         void no_transition(Event const& , FSM&,int)
305         {
306             BOOST_ERROR("no_transition called!");
307         }
308         // init counters
309         template <class Event,class FSM>
310         void on_entry(Event const&,FSM& fsm) 
311         {
312             fsm.template get_state<player_::Stopped&>().entry_counter=0;
313             fsm.template get_state<player_::Stopped&>().exit_counter=0;
314             fsm.template get_state<player_::Open&>().entry_counter=0;
315             fsm.template get_state<player_::Open&>().exit_counter=0;
316             fsm.template get_state<player_::Empty&>().entry_counter=0;
317             fsm.template get_state<player_::Empty&>().exit_counter=0;
318             fsm.template get_state<player_::Playing&>().entry_counter=0;
319             fsm.template get_state<player_::Playing&>().exit_counter=0;
320             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().entry_counter=0;
321             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song1&>().exit_counter=0;
322             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().entry_counter=0;
323             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song2&>().exit_counter=0;
324             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().entry_counter=0;
325             fsm.template get_state<player_::Playing&>().template get_state<player_::Playing::Song3&>().exit_counter=0;
326             fsm.template get_state<player_::Paused&>().entry_counter=0;
327             fsm.template get_state<player_::Paused&>().exit_counter=0;
328             fsm.template get_state<player_::AllOk&>().entry_counter=0;
329             fsm.template get_state<player_::AllOk&>().exit_counter=0;
330             fsm.template get_state<player_::ErrorMode&>().entry_counter=0;
331             fsm.template get_state<player_::ErrorMode&>().exit_counter=0;
332             fsm.template get_state<player_::ErrorTerminate&>().entry_counter=0;
333             fsm.template get_state<player_::ErrorTerminate&>().exit_counter=0;
334         }
335     };
336     // Pick a back-end
337     typedef msm::back::state_machine<player_> player;
338
339     //static char const* const state_names[] = { "Stopped", "Open", "Empty", "Playing", "Paused","AllOk","ErrorMode" };
340
341     BOOST_AUTO_TEST_CASE( my_test )
342     {
343         player p;
344         // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
345         p.start(); 
346         // test deferred event
347         // deferred in Empty and Open, will be handled only after event cd_detected
348         p.process_event(play());
349         BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
350         BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 0,"Open exit not called correctly");
351         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 0,"Playing entry not called correctly");
352         BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 1,"Empty entry not called correctly");
353         //flags
354         BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == false,"CDLoaded should not be active");
355         p.process_event(open_close()); 
356         BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
357         BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 1,"Empty exit not called correctly");
358         BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().entry_counter == 1,"Open entry not called correctly");
359         p.process_event(open_close()); 
360         BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
361         BOOST_CHECK_MESSAGE(p.get_state<player_::Open&>().exit_counter == 1,"Open exit not called correctly");
362         BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().entry_counter == 2,"Empty entry not called correctly");
363         BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
364         //deferred event should have been processed
365         p.process_event(cd_detected("louie, louie")); 
366         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
367         BOOST_CHECK_MESSAGE(p.get_state<player_::Empty&>().exit_counter == 2,"Empty exit not called correctly");
368         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 1,"Stopped entry not called correctly");
369         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 1,"Stopped exit not called correctly");
370         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 1,"Playing entry not called correctly");
371         BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
372         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 0,"Song1 should be active");
373         BOOST_CHECK_MESSAGE(
374             p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().entry_counter == 1,
375             "Song1 entry not called correctly");
376
377         //flags
378         BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
379         BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == true,"FirstSongPlaying should be active");
380
381
382         p.process_event(NextSong());
383         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
384         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
385         BOOST_CHECK_MESSAGE(
386             p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 1,
387             "Song2 entry not called correctly");
388         BOOST_CHECK_MESSAGE(
389             p.get_state<player_::Playing&>().get_state<player_::Playing::Song1&>().exit_counter == 1,
390             "Song1 exit not called correctly");
391         BOOST_CHECK_MESSAGE(
392             p.get_state<player_::Playing&>().start_next_song_counter == 0,
393             "submachine action not called correctly");
394
395         p.process_event(NextSong());
396         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
397         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 2,"Song3 should be active");
398         BOOST_CHECK_MESSAGE(
399             p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().entry_counter == 1,
400             "Song3 entry not called correctly");
401         BOOST_CHECK_MESSAGE(
402             p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().exit_counter == 1,
403             "Song2 exit not called correctly");
404         BOOST_CHECK_MESSAGE(
405             p.get_state<player_::Playing&>().start_next_song_counter == 1,
406             "submachine action not called correctly");
407
408         p.process_event(PreviousSong());
409         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
410         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().current_state()[0] == 1,"Song2 should be active");
411         BOOST_CHECK_MESSAGE(
412             p.get_state<player_::Playing&>().get_state<player_::Playing::Song2&>().entry_counter == 2,
413             "Song2 entry not called correctly");
414         BOOST_CHECK_MESSAGE(
415             p.get_state<player_::Playing&>().get_state<player_::Playing::Song3&>().exit_counter == 1,
416             "Song3 exit not called correctly");
417         BOOST_CHECK_MESSAGE(
418             p.get_state<player_::Playing&>().start_prev_song_guard_counter == 1,
419             "submachine guard not called correctly");
420         //flags
421         BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
422         BOOST_CHECK_MESSAGE(p.is_flag_active<FirstSongPlaying>() == false,"FirstSongPlaying should not be active");
423
424         p.process_event(pause());
425         BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
426         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 1,"Playing exit not called correctly");
427         BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 1,"Paused entry not called correctly");
428         //flags
429         BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == true,"PlayingPaused should be active");
430
431         // go back to Playing
432         p.process_event(end_pause());  
433         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
434         BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 1,"Paused exit not called correctly");
435         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 2,"Playing entry not called correctly");
436
437         p.process_event(pause()); 
438         BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
439         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
440         BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().entry_counter == 2,"Paused entry not called correctly");
441
442         p.process_event(stop());  
443         BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
444         BOOST_CHECK_MESSAGE(p.get_state<player_::Paused&>().exit_counter == 2,"Paused exit not called correctly");
445         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 2,"Stopped entry not called correctly");
446         //flags
447         BOOST_CHECK_MESSAGE(p.is_flag_active<PlayingPaused>() == false,"PlayingPaused should not be active");
448         BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded>() == true,"CDLoaded should be active");
449         //BOOST_CHECK_MESSAGE(p.is_flag_active<CDLoaded,player::Flag_AND>() == false,"CDLoaded with AND should not be active");
450
451         p.process_event(stop());  
452         BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
453         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
454         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
455
456         //test interrupt
457         BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
458         p.process_event(error_found());
459         BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
460         BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
461         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
462
463         // try generating more events
464         p.process_event(play());
465         BOOST_CHECK_MESSAGE(p.current_state()[1] == 6,"ErrorMode should be active"); //ErrorMode
466         BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 1,"AllOk exit not called correctly");
467         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().entry_counter == 1,"ErrorMode entry not called correctly");
468         BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
469         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 2,"Stopped exit not called correctly");
470         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
471
472         p.process_event(end_error());
473         BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
474         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorMode&>().exit_counter == 1,"ErrorMode exit not called correctly");
475         BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().entry_counter == 2,"AllOk entry not called correctly");
476
477         p.process_event(play());
478         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
479         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().exit_counter == 3,"Stopped exit not called correctly");
480         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().entry_counter == 3,"Playing entry not called correctly");
481
482         //test terminate
483         BOOST_CHECK_MESSAGE(p.current_state()[1] == 5,"AllOk should be active"); //AllOk
484         p.process_event(do_terminate());
485         BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
486         BOOST_CHECK_MESSAGE(p.get_state<player_::AllOk&>().exit_counter == 2,"AllOk exit not called correctly");
487         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().entry_counter == 1,"ErrorTerminate entry not called correctly");
488
489         // try generating more events
490         p.process_event(stop());
491         BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
492         BOOST_CHECK_MESSAGE(p.get_state<player_::ErrorTerminate&>().exit_counter == 0,"ErrorTerminate exit not called correctly");
493         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
494         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
495         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
496
497         p.process_event(end_error());
498         BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
499         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
500         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
501         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
502
503         p.process_event(stop());
504         BOOST_CHECK_MESSAGE(p.current_state()[1] == 7,"ErrorTerminate should be active"); //ErrorTerminate
505         BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
506         BOOST_CHECK_MESSAGE(p.get_state<player_::Playing&>().exit_counter == 2,"Playing exit not called correctly");
507         BOOST_CHECK_MESSAGE(p.get_state<player_::Stopped&>().entry_counter == 3,"Stopped entry not called correctly");
508
509     }
510 }
511